1/** 2 * @fileoverview Rule to enforce the position of line comments 3 * @author Alberto Rodríguez 4 */ 5"use strict"; 6 7const astUtils = require("./utils/ast-utils"); 8 9//------------------------------------------------------------------------------ 10// Rule Definition 11//------------------------------------------------------------------------------ 12 13module.exports = { 14 meta: { 15 type: "layout", 16 17 docs: { 18 description: "enforce position of line comments", 19 category: "Stylistic Issues", 20 recommended: false, 21 url: "https://eslint.org/docs/rules/line-comment-position" 22 }, 23 24 schema: [ 25 { 26 oneOf: [ 27 { 28 enum: ["above", "beside"] 29 }, 30 { 31 type: "object", 32 properties: { 33 position: { 34 enum: ["above", "beside"] 35 }, 36 ignorePattern: { 37 type: "string" 38 }, 39 applyDefaultPatterns: { 40 type: "boolean" 41 }, 42 applyDefaultIgnorePatterns: { 43 type: "boolean" 44 } 45 }, 46 additionalProperties: false 47 } 48 ] 49 } 50 ], 51 messages: { 52 above: "Expected comment to be above code.", 53 beside: "Expected comment to be beside code." 54 } 55 }, 56 57 create(context) { 58 const options = context.options[0]; 59 60 let above, 61 ignorePattern, 62 applyDefaultIgnorePatterns = true; 63 64 if (!options || typeof options === "string") { 65 above = !options || options === "above"; 66 67 } else { 68 above = !options.position || options.position === "above"; 69 ignorePattern = options.ignorePattern; 70 71 if (Object.prototype.hasOwnProperty.call(options, "applyDefaultIgnorePatterns")) { 72 applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns; 73 } else { 74 applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false; 75 } 76 } 77 78 const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN; 79 const fallThroughRegExp = /^\s*falls?\s?through/u; 80 const customIgnoreRegExp = new RegExp(ignorePattern, "u"); 81 const sourceCode = context.getSourceCode(); 82 83 //-------------------------------------------------------------------------- 84 // Public 85 //-------------------------------------------------------------------------- 86 87 return { 88 Program() { 89 const comments = sourceCode.getAllComments(); 90 91 comments.filter(token => token.type === "Line").forEach(node => { 92 if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) { 93 return; 94 } 95 96 if (ignorePattern && customIgnoreRegExp.test(node.value)) { 97 return; 98 } 99 100 const previous = sourceCode.getTokenBefore(node, { includeComments: true }); 101 const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line; 102 103 if (above) { 104 if (isOnSameLine) { 105 context.report({ 106 node, 107 messageId: "above" 108 }); 109 } 110 } else { 111 if (!isOnSameLine) { 112 context.report({ 113 node, 114 messageId: "beside" 115 }); 116 } 117 } 118 }); 119 } 120 }; 121 } 122}; 123