Repository: stylelint-scss/stylelint-scss
Pull request #569 (2021-12-01 12:49:43)

Implement the at-use-no-unnamespaced rule
Closes https://github.com/stylelint-scss/stylelint-scss/issues/565

stof: My implementation is incomplete. It won't catch configured modules, as the configuration comes after the namespace in the rule.
stof: And here is the complete implementation

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..1a45042 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,10 @@ Please also see the [example configs](./docs/examples/) for special cases.
 - [`at-rule-conditional-no-parentheses`](./src/rules/at-rule-conditional-no-parentheses/README.md): Disallow parentheses in conditional @ rules (if, elsif, while) (Autofixable).
 - [`at-rule-no-unknown`](./src/rules/at-rule-no-unknown/README.md): Disallow unknown at-rules. Should be used **instead of** stylelint's [at-rule-no-unknown](https://stylelint.io/user-guide/rules/at-rule-no-unknown).
 
+### `@`-use
+
+- [`at-use-no-unnamespaced`](./src/rules/at-use-no-unnamespaced/README.md): Disallow `@use` without a namespace (i.e. `@use "..." as *`).
+
 ### `$`-variable
 
 - [`dollar-variable-colon-newline-after`](./src/rules/dollar-variable-colon-newline-after/README.md): Require a newline after the colon in `$`-variable declarations (Autofixable).
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/at-use-no-unnamespaced/README.md b/src/rules/at-use-no-unnamespaced/README.md
new file mode 100644
index 0000000..35d8b5d
--- /dev/null
+++ b/src/rules/at-use-no-unnamespaced/README.md
@@ -0,0 +1,25 @@
+# at-use-no-unnamespaced
+
+Disallow usage of `@use` without a namespace.
+
+```scss
+@use "foo" as *;
+/**           ↑
+ * Disallow this */
+```
+
+The following patterns are considered warnings:
+
+```scss
+@use "foo" as *;
+```
+
+The following patterns are _not_ considered warnings:
+
+```scss
+@use "foo";
+```
+
+```scss
+@use "foo" as bar;
+```
diff --git a/src/rules/at-use-no-unnamespaced/index.js b/src/rules/at-use-no-unnamespaced/index.js
new file mode 100644
index 0000000..e3781e8
--- /dev/null
+++ b/src/rules/at-use-no-unnamespaced/index.js
@@ -0,0 +1,29 @@
+import { utils } from "stylelint";
+import { namespace } from "../../utils";
+
+export const ruleName = namespace("at-use-no-unnamespaced");
+
+export const messages = utils.ruleMessages(ruleName, {
+  rejected: "Unexpected @use without namespace"
+});
+
+export default function(actual) {
+  return (root, result) => {
+    const validOptions = utils.validateOptions(result, ruleName, { actual });
+
+    if (!validOptions) {
+      return;
+    }
+
+    root.walkAtRules("use", decl => {
+      if (/as\s*\*\s*(?:$|with\s*\()/.test(decl.params)) {
+        utils.report({
+          message: messages.rejected,
+          node: decl,
+          result,
+          ruleName
+        });
+      }
+    });
+  };
+}
diff --git a/src/rules/index.js b/src/rules/index.js
index 94d0ab5..53648c0 100644
--- a/src/rules/index.js
+++ b/src/rules/index.js
@@ -20,6 +20,7 @@ import atMixinParenthesesSpaceBefore from "./at-mixin-parentheses-space-before";
 import atMixinPattern from "./at-mixin-pattern";
 import atRuleConditionalNoParen from "./at-rule-conditional-no-parentheses";
 import atRuleNoUnknown from "./at-rule-no-unknown";
+import atUseNoUnnamespaced from "./at-use-no-unnamespaced";
 import commentNoEmpty from "./comment-no-empty";
 import commentNoLoud from "./comment-no-loud";
 import declarationNestedProperties from "./declaration-nested-properties";
@@ -78,6 +79,7 @@ export default {
   "at-each-key-value-single-line": atEachKeyValue,
   "at-rule-conditional-no-parentheses": atRuleConditionalNoParen,
   "at-rule-no-unknown": atRuleNoUnknown,
+  "at-use-no-unnamespaced": atUseNoUnnamespaced,
   "comment-no-empty": commentNoEmpty,
   "comment-no-loud": commentNoLoud,
   "declaration-nested-properties": declarationNestedProperties,
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/at-use-no-unnamespaced/__tests__/index.js b/src/rules/at-use-no-unnamespaced/__tests__/index.js
new file mode 100644
index 0000000..cf59365
--- /dev/null
+++ b/src/rules/at-use-no-unnamespaced/__tests__/index.js
@@ -0,0 +1,72 @@
+import { messages, ruleName } from "..";
+
+testRule({
+  ruleName,
+  config: [true],
+  customSyntax: "postcss-scss",
+
+  accept: [
+    {
+      code: `
+      @use "foo";
+    `,
+      description: "Default namespace"
+    },
+    {
+      code: `
+      @use "foo" as bar;
+    `,
+      description: "Explicit namespace"
+    }
+  ],
+
+  reject: [
+    {
+      code: `
+      @use "foo" as *;
+    `,
+      line: 2,
+      column: 7,
+      message: messages.rejected,
+      description: "Without namespace"
+    },
+    {
+      code: `
+      @use "foo"as*;
+    `,
+      line: 2,
+      column: 7,
+      message: messages.rejected,
+      description: "Without space"
+    },
+    {
+      code: `
+      @use "foo"   as   *  ;
+    `,
+      line: 2,
+      column: 7,
+      message: messages.rejected,
+      description: "With many spaces"
+    },
+    {
+      code: `
+      @use "foo" as * with ($baz: 1px);
+    `,
+      line: 2,
+      column: 7,
+      message: messages.rejected,
+      description: "Configured"
+    },
+    {
+      code: `
+      @use "foo" as * with (
+        $baz: 1px
+      );
+    `,
+      line: 2,
+      column: 7,
+      message: messages.rejected,
+      description: "Configured multiline"
+    }
+  ]
+});
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 {