UNPKG

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