Home

tailwind-ctp-intellisense @master - refs - log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
tree log patch
consolidate conflict diagnostics and update quick fixes
Brad Cornes <bradlc41@gmail.com>
4 years ago
6 changed files, 105 additions(+), 68 deletions(-)
M src/lsp/providers/codeActionProvider/index.ts -> src/lsp/providers/codeActionProvider/index.ts
diff --git a/src/lsp/providers/codeActionProvider/index.ts b/src/lsp/providers/codeActionProvider/index.ts
index 959411af30b8194c3b3cf7531771774e91424ead..5bced1dd72db162e0e77354f2d931bcdf89927a5 100644
--- a/src/lsp/providers/codeActionProvider/index.ts
+++ b/src/lsp/providers/codeActionProvider/index.ts
@@ -11,7 +11,7 @@ import { isWithinRange } from '../../util/isWithinRange'
 import { getClassNameParts } from '../../util/getClassNameAtPosition'
 const dlv = require('dlv')
 import dset from 'dset'
-import { removeRangeFromString } from '../../util/removeRangeFromString'
+import { removeRangesFromString } from '../../util/removeRangesFromString'
 import detectIndent from 'detect-indent'
 import { cssObjToAst } from '../../util/cssObjToAst'
 import isObject from '../../../util/isObject'
@@ -26,6 +26,7 @@   isUtilityConflictsDiagnostic,
   UtilityConflictsDiagnostic,
 } from '../diagnostics/types'
 import { flatten, dedupeBy } from '../../../util/array'
+import { joinWithAnd } from '../../util/joinWithAnd'
 
 async function getDiagnosticsFromCodeActionParams(
   state: State,
@@ -174,7 +175,11 @@   diagnostic: UtilityConflictsDiagnostic
 ): Promise<CodeAction[]> {
   return [
     {
-      title: `Delete '${diagnostic.className.className}'`,
+      title: `Delete ${joinWithAnd(
+        diagnostic.otherClassNames.map(
+          (otherClassName) => `'${otherClassName.className}'`
+        )
+      )}`,
       kind: CodeActionKind.QuickFix,
       diagnostics: [diagnostic],
       edit: {
@@ -182,27 +187,11 @@         changes: {
           [params.textDocument.uri]: [
             {
               range: diagnostic.className.classList.range,
-              newText: removeRangeFromString(
+              newText: removeRangesFromString(
                 diagnostic.className.classList.classList,
-                diagnostic.className.relativeRange
-              ),
-            },
-          ],
-        },
-      },
-    },
-    {
-      title: `Delete '${diagnostic.otherClassName.className}'`,
-      kind: CodeActionKind.QuickFix,
-      diagnostics: [diagnostic],
-      edit: {
-        changes: {
-          [params.textDocument.uri]: [
-            {
-              range: diagnostic.className.classList.range,
-              newText: removeRangeFromString(
-                diagnostic.className.classList.classList,
-                diagnostic.otherClassName.relativeRange
+                diagnostic.otherClassNames.map(
+                  (otherClassName) => otherClassName.relativeRange
+                )
               ),
             },
           ],
@@ -323,7 +312,7 @@             ...(totalClassNamesInClassList > 1
               ? [
                   {
                     range: diagnostic.className.classList.range,
-                    newText: removeRangeFromString(
+                    newText: removeRangesFromString(
                       diagnostic.className.classList.classList,
                       diagnostic.className.relativeRange
                     ),
M src/lsp/providers/diagnostics/diagnosticsProvider.ts -> src/lsp/providers/diagnostics/diagnosticsProvider.ts
diff --git a/src/lsp/providers/diagnostics/diagnosticsProvider.ts b/src/lsp/providers/diagnostics/diagnosticsProvider.ts
index 56362d5488cc8776715de6feac2096c57149f255..1c98a391dfe30bdfd994e1c474d0c5251b6fdc42 100644
--- a/src/lsp/providers/diagnostics/diagnosticsProvider.ts
+++ b/src/lsp/providers/diagnostics/diagnosticsProvider.ts
@@ -29,6 +29,7 @@   InvalidConfigPathDiagnostic,
   InvalidTailwindDirectiveDiagnostic,
   AugmentedDiagnostic,
 } from './types'
+import { joinWithAnd } from '../../util/joinWithAnd'
 
 function getInvalidApplyDiagnostics(
   state: State,
@@ -104,45 +105,58 @@   classLists.forEach((classList) => {
     const classNames = getClassNamesInClassList(classList)
 
     classNames.forEach((className, index) => {
+      let decls = getClassNameDecls(state, className.className)
+      if (!decls) return
+
+      let properties = Object.keys(decls)
+      let meta = getClassNameMeta(state, className.className)
+
       let otherClassNames = classNames.filter((_className, i) => i !== index)
-      otherClassNames.forEach((otherClassName) => {
-        let decls = getClassNameDecls(state, className.className)
-        if (!decls) return
 
+      let conflictingClassNames = otherClassNames.filter((otherClassName) => {
         let otherDecls = getClassNameDecls(state, otherClassName.className)
-        if (!otherDecls) return
+        if (!otherDecls) return false
 
-        let meta = getClassNameMeta(state, className.className)
         let otherMeta = getClassNameMeta(state, otherClassName.className)
 
-        if (
-          equal(Object.keys(decls), Object.keys(otherDecls)) &&
+        return (
+          equal(properties, Object.keys(otherDecls)) &&
           !Array.isArray(meta) &&
           !Array.isArray(otherMeta) &&
           equal(meta.context, otherMeta.context) &&
           equal(meta.pseudo, otherMeta.pseudo)
-        ) {
-          diagnostics.push({
-            code: DiagnosticKind.UtilityConflicts,
-            className,
-            otherClassName,
-            range: className.range,
-            severity:
-              severity === 'error'
-                ? DiagnosticSeverity.Error
-                : DiagnosticSeverity.Warning,
-            message: `'${className.className}' and '${otherClassName.className}' apply the same CSS properties.`,
-            relatedInformation: [
-              {
-                message: otherClassName.className,
-                location: {
-                  uri: document.uri,
-                  range: otherClassName.range,
-                },
+        )
+      })
+
+      if (conflictingClassNames.length === 0) return
+
+      diagnostics.push({
+        code: DiagnosticKind.UtilityConflicts,
+        className,
+        otherClassNames: conflictingClassNames,
+        range: className.range,
+        severity:
+          severity === 'error'
+            ? DiagnosticSeverity.Error
+            : DiagnosticSeverity.Warning,
+        message: `'${className.className}' applies the same CSS ${
+          properties.length === 1 ? 'property' : 'properties'
+        } as ${joinWithAnd(
+          conflictingClassNames.map(
+            (conflictingClassName) => `'${conflictingClassName.className}'`
+          )
+        )}.`,
+        relatedInformation: conflictingClassNames.map(
+          (conflictingClassName) => {
+            return {
+              message: conflictingClassName.className,
+              location: {
+                uri: document.uri,
+                range: conflictingClassName.range,
               },
-            ],
-          })
-        }
+            }
+          }
+        ),
       })
     })
   })
M src/lsp/providers/diagnostics/types.ts -> src/lsp/providers/diagnostics/types.ts
diff --git a/src/lsp/providers/diagnostics/types.ts b/src/lsp/providers/diagnostics/types.ts
index 684cda7c824aa7cc382c6ffed6b30010d31ddc97..00fc979386386abbad601bf15ba40c8be6cd12c0 100644
--- a/src/lsp/providers/diagnostics/types.ts
+++ b/src/lsp/providers/diagnostics/types.ts
@@ -13,7 +13,7 @@
 export type UtilityConflictsDiagnostic = Diagnostic & {
   code: DiagnosticKind.UtilityConflicts
   className: DocumentClassName
-  otherClassName: DocumentClassName
+  otherClassNames: DocumentClassName[]
 }
 
 export function isUtilityConflictsDiagnostic(
I src/lsp/util/joinWithAnd.ts
diff --git a/src/lsp/util/joinWithAnd.ts b/src/lsp/util/joinWithAnd.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2b2efb716afd1394a91dd44fc6f16c05d053b438
--- /dev/null
+++ b/src/lsp/util/joinWithAnd.ts
@@ -0,0 +1,11 @@
+export function joinWithAnd(strings: string[]): string {
+  return strings.reduce((acc, cur, i) => {
+    if (i === 0) {
+      return cur
+    }
+    if (strings.length > 1 && i === strings.length - 1) {
+      return `${acc} and ${cur}`
+    }
+    return `${acc}, ${cur}`
+  }, '')
+}
D src/lsp/util/removeRangeFromString.ts
diff --git a/src/lsp/util/removeRangeFromString.ts b/src/lsp/util/removeRangeFromString.ts
deleted file mode 100644
index 7479373ced8326e6a6429b1c0642560a13fc076a..0000000000000000000000000000000000000000
--- a/src/lsp/util/removeRangeFromString.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Range } from 'vscode-languageserver'
-import lineColumn from 'line-column'
-
-export function removeRangeFromString(str: string, range: Range): string {
-  let finder = lineColumn(str + '\n', { origin: 0 })
-  let start = finder.toIndex(range.start.line, range.start.character)
-  let end = finder.toIndex(range.end.line, range.end.character)
-  for (let i = start - 1; i >= 0; i--) {
-    if (/\s/.test(str.charAt(i))) {
-      start = i
-    } else {
-      break
-    }
-  }
-  return (str.substr(0, start) + str.substr(end)).trim()
-}
I src/lsp/util/removeRangesFromString.ts
diff --git a/src/lsp/util/removeRangesFromString.ts b/src/lsp/util/removeRangesFromString.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f97d62b95b2aecae61c0e4195fba475af541a17e
--- /dev/null
+++ b/src/lsp/util/removeRangesFromString.ts
@@ -0,0 +1,39 @@
+import { Range } from 'vscode-languageserver'
+import lineColumn from 'line-column'
+import { ensureArray } from '../../util/array'
+
+export function removeRangesFromString(
+  str: string,
+  rangeOrRanges: Range | Range[]
+): string {
+  let ranges = ensureArray(rangeOrRanges)
+  let finder = lineColumn(str + '\n', { origin: 0 })
+  let indexRanges: { start: number; end: number }[] = []
+
+  ranges.forEach((range) => {
+    let start = finder.toIndex(range.start.line, range.start.character)
+    let end = finder.toIndex(range.end.line, range.end.character)
+    for (let i = start - 1; i >= 0; i--) {
+      if (/\s/.test(str.charAt(i))) {
+        start = i
+      } else {
+        break
+      }
+    }
+    indexRanges.push({ start, end })
+  })
+
+  indexRanges.sort((a, b) => a.start - b.start)
+
+  let result = ''
+  let i = 0
+
+  indexRanges.forEach((indexRange) => {
+    result += str.substring(i, indexRange.start)
+    i = indexRange.end
+  })
+
+  result += str.substring(i)
+
+  return result.trim()
+}