UNPKG

3.27 kBJavaScriptView Raw
1/**
2 * @fileoverview Validates newlines before and after dots
3 * @author Greg Cochard
4 */
5
6"use strict";
7
8const astUtils = require("../util/ast-utils");
9
10//------------------------------------------------------------------------------
11// Rule Definition
12//------------------------------------------------------------------------------
13
14module.exports = {
15 meta: {
16 type: "layout",
17
18 docs: {
19 description: "enforce consistent newlines before and after dots",
20 category: "Best Practices",
21 recommended: false,
22 url: "https://eslint.org/docs/rules/dot-location"
23 },
24
25 schema: [
26 {
27 enum: ["object", "property"]
28 }
29 ],
30
31 fixable: "code",
32
33 messages: {
34 expectedDotAfterObject: "Expected dot to be on same line as object.",
35 expectedDotBeforeProperty: "Expected dot to be on same line as property."
36 }
37 },
38
39 create(context) {
40
41 const config = context.options[0];
42
43 // default to onObject if no preference is passed
44 const onObject = config === "object" || !config;
45
46 const sourceCode = context.getSourceCode();
47
48 /**
49 * Reports if the dot between object and property is on the correct loccation.
50 * @param {ASTNode} obj The object owning the property.
51 * @param {ASTNode} prop The property of the object.
52 * @param {ASTNode} node The corresponding node of the token.
53 * @returns {void}
54 */
55 function checkDotLocation(obj, prop, node) {
56 const dot = sourceCode.getTokenBefore(prop);
57 const textBeforeDot = sourceCode.getText().slice(obj.range[1], dot.range[0]);
58 const textAfterDot = sourceCode.getText().slice(dot.range[1], prop.range[0]);
59
60 if (dot.type === "Punctuator" && dot.value === ".") {
61 if (onObject) {
62 if (!astUtils.isTokenOnSameLine(obj, dot)) {
63 const neededTextAfterObj = astUtils.isDecimalInteger(obj) ? " " : "";
64
65 context.report({
66 node,
67 loc: dot.loc.start,
68 messageId: "expectedDotAfterObject",
69 fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${neededTextAfterObj}.${textBeforeDot}${textAfterDot}`)
70 });
71 }
72 } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
73 context.report({
74 node,
75 loc: dot.loc.start,
76 messageId: "expectedDotBeforeProperty",
77 fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
78 });
79 }
80 }
81 }
82
83 /**
84 * Checks the spacing of the dot within a member expression.
85 * @param {ASTNode} node The node to check.
86 * @returns {void}
87 */
88 function checkNode(node) {
89 checkDotLocation(node.object, node.property, node);
90 }
91
92 return {
93 MemberExpression: checkNode
94 };
95 }
96};