Repository: stylelint-scss/stylelint-scss (js)

Issue:
Rule idea: forbid assignment to namespaced variables
When using a Sass module with `@use`, exported variables are writable currently (except for built-in modules, so you cannot reassign `math.$pi` to a different value).
I started a discussion in https://github.com/sass/sass/issues/3171 about that, as I find that this makes modules harder to use (the whole point of modules was to make it easier to reason about files locally, but we can still be impacted by assignments done anywhere else).

I think it would make sense to have a linter rule forbidding assignment to namespaced variables (which does not cover the case of `@use "some-module" as *` but covers all other cases):

```scss
@use "some-module" as identifier;

identifer.$var: "should be rejected";
```

The idea would be to forbid variable assignments of the form `<identifier>.$<identifier>`

Pull request:
Implement the dollar-variable-no-namespaced-assignment rule
Closes #556

Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a6c3f9d..8d263b2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,7 +13,7 @@ There work on the plugin's rules is still in progress, so if you feel like it, y
 * Contribute to [stylelint](https://github.com/stylelint/stylelint)
 * Spread the word.
 
-We communicate via [issues](https://github.com/stylelint-scss/stylelint-scss/issues) and [pull requests](https://github.com/stylelint-scss/stylelint-scss/pulls).
+We communicate via [issues](https://github.com/kristerkari/stylelint-scss/issues) and [pull requests](https://github.com/kristerkari/stylelint-scss/pulls).
 
 ## Links
 
diff --git a/README.md b/README.md
index e0d5ff5..24a6e18 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,7 @@ Please also see the [example configs](./docs/examples/) for special cases.
 - [`dollar-variable-empty-line-before`](./src/rules/dollar-variable-empty-line-before/README.md): Require a single empty line or disallow empty lines before `$`-variable declarations (Autofixable).
 - [`dollar-variable-first-in-block`](./src/rules/dollar-variable-first-in-block/README.md): Require for variables to be put first in a block (a rule or in root).
 - [`dollar-variable-no-missing-interpolation`](./src/rules/dollar-variable-no-missing-interpolation/README.md): Disallow Sass variables that are used without interpolation with CSS features that use custom identifiers.
+- [`dollar-variable-no-namespaced-assignment`](./src/rules/dollar-variable-no-namespaced-assignment/README.md): Disallow assignment to namespaced Sass variables.
 - [`dollar-variable-pattern`](./src/rules/dollar-variable-pattern/README.md): Specify a pattern for Sass-like variables.
 
 ### `%`-placeholder
diff --git a/src/rules/at-else-empty-line-before/README.md b/src/rules/at-else-empty-line-before/README.md
index 724a83e..9961fe6 100644
--- a/src/rules/at-else-empty-line-before/README.md
+++ b/src/rules/at-else-empty-line-before/README.md
@@ -66,4 +66,4 @@ a {
 
 ## Caveats
 
-If you use autofix, this rule could clash with [`at-mixin-parentheses-space-before`](../at-mixin-parentheses-space-before/README.md) rule.
+If you use autofix, this rule could clash with [`at-mixin-parentheses-space-before`](https://github.com/kristerkari/stylelint-scss/tree/master/src/rules/at-mixin-parentheses-space-before) rule.
diff --git a/src/rules/dollar-variable-no-namespaced-assignment/README.md b/src/rules/dollar-variable-no-namespaced-assignment/README.md
new file mode 100644
index 0000000..850094f
--- /dev/null
+++ b/src/rules/dollar-variable-no-namespaced-assignment/README.md
@@ -0,0 +1,24 @@
+# dollar-variable-no-namespaced-assignment
+
+Disallow assignment to namespaced variables. 
+
+```scss
+a { imported.$foo: 1px; }
+/** ↑
+ * This assignment */
+```
+
+## Examples
+
+The following patterns are considered warnings:
+
+```scss
+imported.$foo: 1;
+```
+
+The following patterns are *not* considered warnings:
+
+```scss
+a { b: imported.$foo-bar; }
+a { $foo: 0; }
+```
diff --git a/src/rules/dollar-variable-no-namespaced-assignment/index.js b/src/rules/dollar-variable-no-namespaced-assignment/index.js
new file mode 100644
index 0000000..6a54111
--- /dev/null
+++ b/src/rules/dollar-variable-no-namespaced-assignment/index.js
@@ -0,0 +1,31 @@
+import { utils } from "stylelint";
+import { namespace } from "../../utils";
+
+export const ruleName = namespace("dollar-variable-no-namespaced-assignment");
+
+export const messages = utils.ruleMessages(ruleName, {
+  rejected: "Unexpected assignment to a namespaced $ variable"
+});
+
+export default function(actual) {
+  return (root, result) => {
+    const validOptions = utils.validateOptions(result, ruleName, { actual });
+
+    if (!validOptions) {
+      return;
+    }
+
+    root.walkDecls(decl => {
+      if (!/^[^$.]+\.\$./.test(decl.prop)) {
+        return;
+      }
+
+      utils.report({
+        message: messages.rejected,
+        node: decl,
+        result,
+        ruleName
+      });
+    });
+  };
+}
diff --git a/src/rules/index.js b/src/rules/index.js
index 94d0ab5..00447f4 100644
--- a/src/rules/index.js
+++ b/src/rules/index.js
@@ -33,6 +33,7 @@ import dollarVariableEmptyLineAfter from "./dollar-variable-empty-line-after";
 import dollarVariableEmptyLineBefore from "./dollar-variable-empty-line-before";
 import dollarVariableFirstInBlock from "./dollar-variable-first-in-block";
 import dollarVariableNoMissingInterpolation from "./dollar-variable-no-missing-interpolation";
+import dollarVariableNoNamespacedAssignment from "./dollar-variable-no-namespaced-assignment";
 import dollarVariablePattern from "./dollar-variable-pattern";
 import doubleSlashCommentEmptyLineBefore from "./double-slash-comment-empty-line-before";
 import doubleSlashCommentInline from "./double-slash-comment-inline";
@@ -91,6 +92,7 @@ export default {
   "dollar-variable-empty-line-before": dollarVariableEmptyLineBefore,
   "dollar-variable-first-in-block": dollarVariableFirstInBlock,
   "dollar-variable-no-missing-interpolation": dollarVariableNoMissingInterpolation,
+  "dollar-variable-no-namespaced-assignment": dollarVariableNoNamespacedAssignment,
   "dollar-variable-pattern": dollarVariablePattern,
   "double-slash-comment-empty-line-before": doubleSlashCommentEmptyLineBefore,
   "double-slash-comment-inline": doubleSlashCommentInline,
diff --git a/src/rules/no-global-function-names/index.js b/src/rules/no-global-function-names/index.js
index 41246d6..65a35cc 100644
--- a/src/rules/no-global-function-names/index.js
+++ b/src/rules/no-global-function-names/index.js
@@ -13,6 +13,8 @@ const rules = {
   saturation: "color",
   lightness: "color",
   complement: "color",
+  invert: "color",
+  alpha: "color",
   "adjust-color": "color",
   "scale-color": "color",
   "change-color": "color",
@@ -37,6 +39,8 @@ const rules = {
   ceil: "math",
   floor: "math",
   abs: "math",
+  min: "math",
+  max: "math",
   random: "math",
   unit: "math",
   unitless: "math",
@@ -73,6 +77,7 @@ const rules = {
   darken: "color",
   desaturate: "color",
   opacify: "color",
+  saturate: "color",
   transparentize: "color"
 };
 


Test patch:
diff --git a/src/rules/dollar-variable-no-namespaced-assignment/__tests__/index.js b/src/rules/dollar-variable-no-namespaced-assignment/__tests__/index.js
new file mode 100644
index 0000000..fdd44c5
--- /dev/null
+++ b/src/rules/dollar-variable-no-namespaced-assignment/__tests__/index.js
@@ -0,0 +1,39 @@
+import { messages, ruleName } from "..";
+
+testRule({
+  ruleName,
+  config: [true],
+  customSyntax: "postcss-scss",
+
+  accept: [
+    {
+      code: `
+      p {
+        $foo: 10px;
+      }
+    `,
+      description: "Non-namespaced assignment"
+    },
+    {
+      code: `
+      p {
+        a: imported.$foo;
+      }
+    `,
+      description: "Namespaced usage"
+    }
+  ],
+
+  reject: [
+    {
+      code: `
+      p {
+        imported.$foo: 10px;
+      }
+    `,
+      line: 3,
+      message: messages.rejected,
+      description: "Namespaced assignment"
+    }
+  ]
+});
diff --git a/src/rules/no-global-function-names/__tests__/index.js b/src/rules/no-global-function-names/__tests__/index.js
index 4458dbc..41d8ee7 100644
--- a/src/rules/no-global-function-names/__tests__/index.js
+++ b/src/rules/no-global-function-names/__tests__/index.js
@@ -38,46 +38,6 @@ testRule({
     `,
       description: "An allowed global function"
     },
-    {
-      code: `
-      a {
-       min-width: min(30vw, 300px);
-      }
-    `,
-      description: "An allowed global function"
-    },
-    {
-      code: `
-      a {
-       min-width: max(30vw, 300px);
-      }
-    `,
-      description: "An allowed global function"
-    },
-    {
-      code: `
-      a {
-       filter: invert(1);
-      }
-    `,
-      description: "An allowed global function"
-    },
-    {
-      code: `
-      a {
-       filter: saturate(140%);
-      }
-    `,
-      description: "An allowed global function"
-    },
-    {
-      code: `
-      a {
-       filter: alpha(opacity=50);
-      }
-    `,
-      description: "An allowed global function"
-    },
     {
       code: `
       @use "sass:color";
@@ -369,6 +329,17 @@ testRule({
       message: messages.rejected("lightness"),
       description: "lightness"
     },
+    {
+      code: `
+      a {
+        background: alpha(#6b717f);
+      }
+    `,
+      line: 3,
+      column: 21,
+      message: messages.rejected("alpha"),
+      description: "alpha"
+    },
     {
       code: `
       a {