Skip to content

Commit

Permalink
Merge pull request #453 from srawlins/fix-277
Browse files Browse the repository at this point in the history
no-duplicate-dollar-variables: allow dup vars in unrelated scopes
  • Loading branch information
kristerkari committed Mar 15, 2020
2 parents 6ff1539 + c630871 commit c1ab933
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 2 deletions.
16 changes: 16 additions & 0 deletions src/rules/no-duplicate-dollar-variables/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ Disallow duplicate dollar variables within a stylesheet.
* These are duplicates */
```

A dollar variable is considered a duplicate if it shadows a variable of the same name (see the
[Sass documentation](https://sass-lang.com/documentation/variables#shadowing)). Two dollar
variables are not duplicates if their scopes are unrelated.

```scss
.one {
$a: 1;
/** ↑
* Not a duplicate */
}
.two {
$a: 2;
/** ↑
* Not a duplicate */
}

## Options

### `true`
Expand Down
54 changes: 54 additions & 0 deletions src/rules/no-duplicate-dollar-variables/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,39 @@ testRule(rule, {
}
`,
description: "A single variable and a normal CSS property."
},
{
code: `
.a {
$ab: 1;
}
.b {
$ab: 2;
}
`,
description: "Two variables in unrelated scopes."
},
{
code: `
@mixin a {
$ab: 1;
}
@mixin c {
$ab: 2;
}
`,
description: "Two variables in unrelated at-rule scopes."
},
{
code: `
@if 1 == 2 {
$ab: 1;
}
@else {
$ab: 2;
}
`,
description: "Two variables in unrelated at-rule scope cases."
}
],

Expand Down Expand Up @@ -222,6 +255,27 @@ testRule(rule, {
message: messages.rejected("$ab"),
description:
"Two dollar variables with the same name and multi-level nesting."
},
{
code: `
.a {
$ab: 1;
}
.b {
$ab: 2;
}
.c {
$ab: 3;
.d {
$ab: 4;
}
}
`,
line: 11,
column: 11,
message: messages.rejected("$ab"),
description:
"Two dollar variables with the same name and multi-level nesting."
}
]
});
Expand Down
51 changes: 49 additions & 2 deletions src/rules/no-duplicate-dollar-variables/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ export default function(value, secondaryOptions) {

const vars = {};

/**
* Traverse the [vars] tree through the path defined by [ancestors], creating nodes as needed.
*
* Return the tree of the node defined by the last of [ancestors].
*/
function getScope(ancestors) {
let scope = vars;

for (const node of ancestors) {
if (!(node in scope)) {
scope[node] = {};
}

scope = scope[node];
}

return scope;
}

/**
* Returns whether [variable] is declared anywhere in the scopes along the path defined by
* [ancestors].
*/
function isDeclared(ancestors, variable) {
let scope = vars;

for (const node of ancestors) {
scope = scope[node];

if (scope[variable]) return true;
}

return false;
}

root.walkDecls(decl => {
const isVar = decl.prop[0] === "$";
const isInsideIgnoredAtRule =
Expand Down Expand Up @@ -60,7 +95,19 @@ export default function(value, secondaryOptions) {
return;
}

if (vars[decl.prop]) {
const ancestors = [];
let parent = decl.parent;

while (parent !== null && parent !== undefined) {
const parentKey = parent.toString();

ancestors.unshift(parentKey);
parent = parent.parent;
}

const scope = getScope(ancestors);

if (isDeclared(ancestors, decl.prop)) {
utils.report({
message: messages.rejected(decl.prop),
node: decl,
Expand All @@ -69,7 +116,7 @@ export default function(value, secondaryOptions) {
});
}

vars[decl.prop] = true;
scope[decl.prop] = true;
});
};
}

0 comments on commit c1ab933

Please sign in to comment.