.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / needlessDisables.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/needlessDisables.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/needlessDisables.js
new file mode 100644 (file)
index 0000000..46b25f5
--- /dev/null
@@ -0,0 +1,123 @@
+/* @flow */
+"use strict";
+
+const _ = require("lodash");
+
+/*:: type rangeDataType = {
+  all: Array<Object>,
+}
+*/
+
+/*:: type rangeType = {
+  end?: number,
+  start: number,
+  used?: boolean,
+}*/
+
+/*:: type unusedRangeT = {
+  start: number,
+  end?: number,
+}*/
+
+module.exports = function(
+  results /*: Array<stylelint$result>*/
+) /*: stylelint$needlessDisablesReport*/ {
+  const report = [];
+
+  results.forEach(result => {
+    // File with `CssSyntaxError` have not `_postcssResult`
+    if (!result._postcssResult) {
+      return;
+    }
+
+    const unused = { source: result.source, ranges: [] };
+    const rangeData /*: ?rangeDataType*/ = _.cloneDeep(
+      result._postcssResult.stylelint.disabledRanges
+    );
+
+    if (!rangeData) {
+      return;
+    }
+
+    result.warnings.forEach(warning => {
+      const rule /*: string*/ = warning.rule;
+
+      const ruleRanges /*: Array<Object>*/ = rangeData[rule];
+      if (ruleRanges) {
+        // Back to front so we get the *last* range that applies to the warning
+        for (const range of ruleRanges.reverse()) {
+          if (isWarningInRange(warning, range)) {
+            range.used = true;
+            return;
+          }
+        }
+      }
+
+      for (const range of rangeData.all.reverse()) {
+        if (isWarningInRange(warning, range)) {
+          range.used = true;
+          return;
+        }
+      }
+    });
+
+    Object.keys(rangeData).forEach(rule => {
+      rangeData[rule].forEach((range /*: rangeType*/) => {
+        // Is an equivalent range already marked as unused?
+        const alreadyMarkedUnused /*: ?unusedRangeT*/ = unused.ranges.find((
+          unusedRange /*: unusedRangeT*/
+        ) => {
+          return (
+            unusedRange.start === range.start && unusedRange.end === range.end
+          );
+        });
+
+        // If this range is unused and no equivalent is marked,
+        // mark this range as unused
+        if (!range.used && !alreadyMarkedUnused) {
+          unused.ranges.push(range);
+        }
+
+        // If this range is used but an equivalent has been marked as unused,
+        // remove that equivalent. This can happen because of the duplication
+        // of ranges in rule-specific range sets and the "all" range set
+        if (range.used && alreadyMarkedUnused) {
+          _.remove(unused.ranges, alreadyMarkedUnused);
+        }
+      });
+    });
+
+    unused.ranges = _.sortBy(unused.ranges, ["start", "end"]);
+
+    report.push(unused);
+  });
+
+  return report;
+};
+
+function isWarningInRange(
+  warning /*: {
+    column: number,
+    rule: string,
+    line: number,
+    severity: string,
+    text: string,
+  }*/,
+  range /*: {
+    rules?: Array<string>,
+    start: number,
+    end?: number,
+    used?: boolean,
+  }*/
+) /*: boolean*/ {
+  const rule = warning.rule,
+    line = warning.line;
+
+  // Need to check if range.end exist, because line number type cannot be compared to undefined
+  return (
+    range.start <= line &&
+    ((range.end !== undefined && range.end >= line) ||
+      range.end === undefined) &&
+    (!range.rules || range.rules.indexOf(rule) !== -1)
+  );
+}