(node)
| 29 | |
| 30 | return { |
| 31 | StyleSheet(node) { |
| 32 | for (const child of node.children) { |
| 33 | if (child.type !== 'Rule') { |
| 34 | continue; |
| 35 | } |
| 36 | |
| 37 | let line = child.loc.start.line - 1; |
| 38 | const leadingComments = []; |
| 39 | while (line >= 1) { |
| 40 | // `line` is 1-based from source locations; sourceCode.lines is 0-based. |
| 41 | const lineText = (sourceCode.lines[line - 1] ?? '').trim(); |
| 42 | if (lineText === '') { |
| 43 | line--; |
| 44 | continue; |
| 45 | } |
| 46 | |
| 47 | const comment = commentsByEndLine.get(line); |
| 48 | if (!comment) { |
| 49 | break; |
| 50 | } |
| 51 | |
| 52 | leadingComments.unshift(comment); |
| 53 | line = comment.loc.start.line - 1; |
| 54 | } |
| 55 | |
| 56 | let hasInfo = false; |
| 57 | let hasTest = false; |
| 58 | let hasDescription = false; |
| 59 | for (const comment of leadingComments) { |
| 60 | const commentValue = comment.value.trim().toLowerCase(); |
| 61 | hasInfo ||= commentValue.startsWith('info:'); |
| 62 | hasTest ||= commentValue.startsWith('test:'); |
| 63 | hasDescription ||= commentValue.length > 0 && !isNonDescriptionMetadataLine(commentValue); |
| 64 | } |
| 65 | |
| 66 | const missingRequirements = []; |
| 67 | if (!hasDescription) { |
| 68 | missingRequirements.push('Description'); |
| 69 | } |
| 70 | |
| 71 | if (!hasInfo) { |
| 72 | missingRequirements.push('Info'); |
| 73 | } |
| 74 | |
| 75 | if (!hasTest) { |
| 76 | missingRequirements.push('Test'); |
| 77 | } |
| 78 | |
| 79 | if (missingRequirements.length > 0) { |
| 80 | context.report({ |
| 81 | node: child, |
| 82 | messageId: 'invalidComments', |
| 83 | data: { |
| 84 | missing: missingRequirements.join(', '), |
| 85 | }, |
| 86 | }); |
| 87 | } |
| 88 | } |
nothing calls this directly
no test coverage detected