Home

tailwind-ctp-intellisense @master - refs - log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
tree log patch
enable diagnostics in multi-language documents
Brad Cornes <bradlc41@gmail.com>
4 years ago
4 changed files, 273 additions(+), 153 deletions(-)
M src/lsp/providers/diagnosticsProvider.ts -> src/lsp/providers/diagnosticsProvider.ts
diff --git a/src/lsp/providers/diagnosticsProvider.ts b/src/lsp/providers/diagnosticsProvider.ts
index 866c07d56dabc00b1759e3d154f43154c872931c..bb59ff571ca903793d4eb34a45d4775e9e9beaca 100644
--- a/src/lsp/providers/diagnosticsProvider.ts
+++ b/src/lsp/providers/diagnosticsProvider.ts
@@ -2,6 +2,7 @@ import {
   TextDocument,
   Diagnostic,
   DiagnosticSeverity,
+  Range,
 } from 'vscode-languageserver'
 import { State, Settings } from '../util/state'
 import { isCssDoc } from '../util/css'
@@ -18,6 +19,9 @@ import { equal, flatten } from '../../util/array'
 import { getDocumentSettings } from '../util/getDocumentSettings'
 const dlv = require('dlv')
 import {
+  findClassListsInDocument,
+import { getLanguageBoundaries } from '../util/getLanguageBoundaries'
+
   findClassListsInDocument,
 
 function getUnsupportedApplyDiagnostics(
@@ -141,56 +145,83 @@ ): Diagnostic[] {
   let severity = settings.lint.unknownScreen
   if (severity === 'ignore') return []
 
-  let text = document.getText()
+  let diagnostics: Diagnostic[] = []
+  TextDocument,
   getClassNamesInClassList,
-  findClassNamesInRange,
 
+  TextDocument,
 import {
-  findClassListsInDocument,
+import {
+  TextDocument,
 import {
+  TextDocument,
+  TextDocument,
 import {
+  Diagnostic,
+  TextDocument,
 import {
+  DiagnosticSeverity,
+  TextDocument,
 import {
+} from 'vscode-languageserver'
+  TextDocument,
 import {
+import { State, Settings } from '../util/state'
+  }
 
+  TextDocument,
 import {
+  findClassNamesInRange,
+  TextDocument,
 import {
+  findClassListsInDocument,
   TextDocument,
+
+
+  state: State,
 import {
-import {
+      dlv(state.config, 'theme.screens', dlv(state.config, 'screens', {}))
+  state: State,
   Diagnostic,
+
+    matches.forEach((match) => {
       if (screens.includes(match.groups.screen)) {
         return null
       }
 
+  state: State,
 } from 'vscode-languageserver'
-  Diagnostic,
-  findAll,
+  state: State,
 import { State, Settings } from '../util/state'
-  findAll,
+  state: State,
 import { isCssDoc } from '../util/css'
-  findAll,
+  state: State,
   findClassNamesInRange,
-  findAll,
+  state: State,
   findClassListsInDocument,
-import {
   TextDocument,
+  Diagnostic,
-import {
   TextDocument,
+  Diagnostic,
 import {
-import {
+            end: indexToPosition(text, match.index + match[0].length),
   TextDocument,
+      let message: string
   TextDocument,
+      if (Array.isArray(meta)) {
+        ),
         severity:
           severity === 'error'
             ? DiagnosticSeverity.Error
             : DiagnosticSeverity.Warning,
         message: 'Unknown screen',
-} from 'vscode-languageserver'
 import {
+  Diagnostic,
     })
+  })
+
 import { State, Settings } from '../util/state'
-import {
+  TextDocument,
 }
 
 function getUnknownVariantDiagnostics(
@@ -200,73 +232,90 @@ ): Diagnostic[] {
   let severity = settings.lint.unknownVariant
   if (severity === 'ignore') return []
 
+  let diagnostics: Diagnostic[] = []
+  TextDocument,
   getClassNamesInClassList,
-import { isCssDoc } from '../util/css'
-import {
   TextDocument,
-import { State, Settings } from '../util/state'
   TextDocument,
 import {
+import {
   TextDocument,
-import { isCssDoc } from '../util/css'
   indexToPosition,
-  findClassNamesInRange,
-import {
   TextDocument,
-  findClassListsInDocument,
 } from '../util/find'
+  TextDocument,
 import {
-  Diagnostic,
+  DiagnosticSeverity,
+  TextDocument,
 import {
+} from 'vscode-languageserver'
-} from '../util/find'
   TextDocument,
+import { equal, flatten } from '../../util/array'
+  TextDocument,
 import {
-      let message: string
+import { isCssDoc } from '../util/css'
 
+  TextDocument,
 import {
-      if (Array.isArray(meta)) {
+  findClassNamesInRange,
+  TextDocument,
 import {
-        message = `\`@apply\` cannot be used with \`.${className}\` because it is included in multiple rulesets.`
+  findClassListsInDocument,
-import {
+  TextDocument,
       } else if (meta.source !== 'utilities') {
-import {
+
+    matches.forEach((match) => {
+  TextDocument,
         message = `\`@apply\` cannot be used with \`.${className}\` because it is not a utility.`
-import {
+  TextDocument,
       } else if (meta.context && meta.context.length > 0) {
   TextDocument,
+        if (meta.context.length === 1) {
+  TextDocument,
+      for (let i = 0; i < variants.length; i += 2) {
+  settings: Settings
 import {
+        if (state.variants.includes(variant)) {
+  settings: Settings
   Diagnostic,
-  findClassListsInDocument,
-import {
   DiagnosticSeverity,
+} from 'vscode-languageserver'
+  TextDocument,
   TextDocument,
+          )}).`
+          listStartIndex + variants.slice(0, i).join('').length
+  TextDocument,
-  findClassNamesInRange,
+  settings: Settings
 import { State, Settings } from '../util/state'
-import {
+          range: absoluteRange(
+  TextDocument,
   DiagnosticSeverity,
-import {
+  findClassNamesInRange,
               start: indexToPosition(text, variantStartIndex),
               end: indexToPosition(text, variantStartIndex + variant.length),
             },
-            severity:
+            range
-              severity === 'error'
+          ),
-  findClassListsInDocument,
+): Diagnostic[] {
-  findClassListsInDocument,
+): Diagnostic[] {
 import {
-import { getClassNameMeta } from '../util/getClassNameMeta'
+  TextDocument,
 } from 'vscode-languageserver'
+  TextDocument,
-  getClassNamesInClassList,
   TextDocument,
+      return {
-  DiagnosticSeverity,
+  TextDocument,
 } from 'vscode-languageserver'
+  DiagnosticSeverity,
   TextDocument,
+          severity === 'error'
+} from 'vscode-languageserver'
 import {
-  DiagnosticSeverity,
 import { State, Settings } from '../util/state'
   getClassNamesInClassList,
-  Diagnostic,
+  DiagnosticSeverity,
-      .filter(Boolean)
+
-  )
+  return diagnostics
 }
 
 function getUnknownConfigKeyDiagnostics(
@@ -274,24 +323,42 @@ ): Diagnostic[] {
   let severity = settings.lint.unknownConfigKey
   if (severity === 'ignore') return []
 
+  let diagnostics: Diagnostic[] = []
+  TextDocument,
   getClassNamesInClassList,
-import { isCssDoc } from '../util/css'
-import { getClassNameDecls } from '../util/getClassNameDecls'
+  TextDocument,
+  TextDocument,
 import {
-} from 'vscode-languageserver'
 import {
+  TextDocument,
 import {
-} from 'vscode-languageserver'
   TextDocument,
+  TextDocument,
 import {
+  Diagnostic,
+  TextDocument,
 import {
+  DiagnosticSeverity,
+  TextDocument,
 import {
+} from 'vscode-languageserver'
+    ranges.push(...boundaries.css)
+  }
 
+  TextDocument,
 import {
+  findClassNamesInRange,
+  TextDocument,
 import {
+  findClassListsInDocument,
   TextDocument,
+            ? DiagnosticSeverity.Error
-  findAll,
+      /(?<prefix>\s|^)(?<helper>config|theme)\((?<quote>['"])(?<key>[^)]+)\k<quote>\)/g,
+      text
+  state: State,
   Diagnostic,
+
+    matches.forEach((match) => {
       let base = match.groups.helper === 'theme' ? ['theme'] : []
       let keys = match.groups.key.split(/[.\[\]]/).filter(Boolean)
       let value = dlv(state.config, [...base, ...keys])
@@ -309,27 +376,33 @@         match.groups.helper.length +
         1 + // open paren
         match.groups.quote.length
 
+  state: State,
 } from 'vscode-languageserver'
-  Diagnostic,
-  findAll,
+  state: State,
 import { State, Settings } from '../util/state'
-import { equal, flatten } from '../../util/array'
+          {
+  TextDocument,
 } from 'vscode-languageserver'
+  findClassListsInDocument,
-import { equal, flatten } from '../../util/array'
+  TextDocument,
 import { State, Settings } from '../util/state'
-import {
   TextDocument,
+      let message: string
   TextDocument,
+      if (Array.isArray(meta)) {
+        ),
         severity:
           severity === 'error'
             ? DiagnosticSeverity.Error
             : DiagnosticSeverity.Warning,
         message: `Unknown ${match.groups.helper} key: ${match.groups.key}`,
-} from 'vscode-languageserver'
 import {
+  Diagnostic,
     })
+  })
+
 import { State, Settings } from '../util/state'
-import {
+  TextDocument,
 }
 
 function getUnsupportedTailwindDirectiveDiagnostics(
@@ -340,58 +412,74 @@ ): Diagnostic[] {
   let severity = settings.lint.unsupportedTailwindDirective
   if (severity === 'ignore') return []
 
-  let text = document.getText()
+  let diagnostics: Diagnostic[] = []
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
 
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
 import {
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
   TextDocument,
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
   Diagnostic,
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
   DiagnosticSeverity,
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
 } from 'vscode-languageserver'
+  TextDocument,
 import {
-import { isCssDoc } from '../util/css'
 import { State, Settings } from '../util/state'
   TextDocument,
+import { getDocumentSettings } from '../util/getDocumentSettings'
+  TextDocument,
+  TextDocument,
 import {
-import {
+  findClassNamesInRange,
   TextDocument,
 import {
+  findClassListsInDocument,
+  let severity = settings.lint.unsupportedApply
 import {
+
+    let valid = [
+  let severity = settings.lint.unsupportedApply
   Diagnostic,
-import {
+      'components',
+      'screens',
+      semver.gte(state.version, '1.0.0-beta.1') ? 'base' : 'preflight',
+  let severity = settings.lint.unsupportedApply
 import { isCssDoc } from '../util/css'
-import { isCssDoc } from '../util/css'
+
+    matches.forEach((match) => {
+      if (valid.includes(match.groups.value)) {
         return null
       }
 
+  state: State,
 } from 'vscode-languageserver'
-  Diagnostic,
-  findAll,
+  state: State,
 import { State, Settings } from '../util/state'
-  findAll,
+  state: State,
 import { isCssDoc } from '../util/css'
-  findAll,
+  state: State,
   findClassNamesInRange,
-            match.index + match[0].length - match.groups.value.length
+              text,
-import {
   TextDocument,
+    const classNames = getClassNamesInClassList(classList)
-import {
   TextDocument,
+  Diagnostic,
 import {
-import {
   TextDocument,
+  Diagnostic,
   TextDocument,
+          },
+          range
+        ),
         severity:
           severity === 'error'
             ? DiagnosticSeverity.Error
@@ -397,11 +487,13 @@             : DiagnosticSeverity.Warning,
         message: `Unsupported value: ${match.groups.value}${
           match.groups.value === 'preflight' ? '. Use base instead.' : ''
         }`,
-} from 'vscode-languageserver'
 import {
+  Diagnostic,
     })
+  })
+
 import { State, Settings } from '../util/state'
-import {
+  TextDocument,
 }
 
 export async function provideDiagnostics(
@@ -413,26 +505,23 @@
   const diagnostics: Diagnostic[] = settings.validate
     ? [
         ...getUtilityConflictDiagnostics(state, document, settings),
-        ...(isCssDoc(state, document)
-import semver from 'semver'
+  if (severity === 'ignore') return []
-import semver from 'semver'
+  if (severity === 'ignore') return []
 import {
-import semver from 'semver'
+  if (severity === 'ignore') return []
   TextDocument,
-import semver from 'semver'
+  if (severity === 'ignore') return []
   Diagnostic,
-import semver from 'semver'
+  if (severity === 'ignore') return []
   DiagnosticSeverity,
-import semver from 'semver'
+  if (severity === 'ignore') return []
 } from 'vscode-languageserver'
-import semver from 'semver'
+  if (severity === 'ignore') return []
 import { State, Settings } from '../util/state'
-import semver from 'semver'
+  if (severity === 'ignore') return []
 import { isCssDoc } from '../util/css'
-                settings
-              ),
   TextDocument,
-          : []),
+        message = `\`@apply\` cannot be used with \`.${className}\` because it is included in multiple rulesets.`
       ]
     : []
 
I src/lsp/util/absoluteRange.ts
diff --git a/src/lsp/util/absoluteRange.ts b/src/lsp/util/absoluteRange.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9250e4fb9ec9b13ff3124072808f2013ef5009a0
--- /dev/null
+++ b/src/lsp/util/absoluteRange.ts
@@ -0,0 +1,18 @@
+import { Range } from 'vscode-languageserver'
+
+export function absoluteRange(range: Range, reference?: Range) {
+  return {
+    start: {
+      line: (reference?.start.line || 0) + range.start.line,
+      character:
+        (range.end.line === 0 ? reference?.start.character || 0 : 0) +
+        range.start.character,
+    },
+    end: {
+      line: (reference?.start.line || 0) + range.end.line,
+      character:
+        (range.end.line === 0 ? reference?.start.character || 0 : 0) +
+        range.end.character,
+    },
+  }
+}
M src/lsp/util/find.ts -> src/lsp/util/find.ts
diff --git a/src/lsp/util/find.ts b/src/lsp/util/find.ts
index 0f996a43f914e393b546ae08a4410908687126b3..609de6207d066862bb645e4d9ca199c915010b61 100644
--- a/src/lsp/util/find.ts
+++ b/src/lsp/util/find.ts
@@ -10,6 +10,7 @@ import {
   getClassAttributeLexer,
   getComputedClassAttributeLexer,
 } from './lexers'
+import { getLanguageBoundaries } from './getLanguageBoundaries'
 
 export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
   let match: RegExpMatchArray
@@ -230,86 +231,25 @@   if (isCssDoc(state, doc)) {
     return findClassListsInCssRange(doc)
   }
 
-  if (isVueDoc(doc)) {
-    let text = doc.getText()
-    let blocks = findAll(
-  while ((match = re.exec(str)) !== null) {
 import { DocumentClassName, DocumentClassList, State } from './state'
-  while ((match = re.exec(str)) !== null) {
 import lineColumn from 'line-column'
-    )
-    let htmlRanges: Range[] = []
-    let cssRanges: Range[] = []
-    for (let i = 0; i < blocks.length; i++) {
-      let range = {
-        start: indexToPosition(text, blocks[i].index),
-        end: indexToPosition(text, blocks[i].index + blocks[i][0].length),
-      }
-      if (blocks[i].groups.type === 'style') {
-        cssRanges.push(range)
-      } else {
-    matches.push({ ...match })
 import lineColumn from 'line-column'
-import { TextDocument, Range, Position } from 'vscode-languageserver'
 import { DocumentClassName, DocumentClassList, State } from './state'
-    }
-    return [].concat.apply(
-      [],
-      [
-        ...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)),
-        ...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
-      ]
-    )
-  }
-import { TextDocument, Range, Position } from 'vscode-languageserver'
 import lineColumn from 'line-column'
-  if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) {
-    let text = doc.getText()
-    let styleBlocks = findAll(/<style(?:\s[^>]*>|>).*?(<\/style>|$)/gis, text)
-  while ((match = re.exec(str)) !== null) {
 import { isCssContext, isCssDoc } from './css'
 import { TextDocument, Range, Position } from 'vscode-languageserver'
-      match.index + match[1].length + match.groups.classList.length
-    let currentIndex = 0
-import { TextDocument, Range, Position } from 'vscode-languageserver'
 import lineColumn from 'line-column'
-    for (let i = 0; i < styleBlocks.length; i++) {
-      htmlRanges.push({
-        start: indexToPosition(text, currentIndex),
-        end: indexToPosition(text, styleBlocks[i].index),
-      })
-      cssRanges.push({
-        start: indexToPosition(text, styleBlocks[i].index),
-        end: indexToPosition(
 import { DocumentClassName, DocumentClassList, State } from './state'
-          styleBlocks[i].index + styleBlocks[i][0].length
-        ),
-      })
-  return matches
 import lineColumn from 'line-column'
 import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html'
-import { TextDocument, Range, Position } from 'vscode-languageserver'
 import { DocumentClassName, DocumentClassList, State } from './state'
-import { isCssContext, isCssDoc } from './css'
-      start: indexToPosition(text, currentIndex),
-  return matches
+import lineColumn from 'line-column'
 import { isWithinRange } from './isWithinRange'
 import { DocumentClassName, DocumentClassList, State } from './state'
-import { isJsContext, isJsDoc } from './js'
-import { TextDocument, Range, Position } from 'vscode-languageserver'
 import lineColumn from 'line-column'
-    return [].concat.apply(
-      [],
-      [
-    matches.push({ ...match })
 import { isJsContext, isJsDoc } from './js'
-        ...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
-      ]
-    )
-  }
-import { TextDocument, Range, Position } from 'vscode-languageserver'
+import { DocumentClassName, DocumentClassList, State } from './state'
 import lineColumn from 'line-column'
-  return matches
 import { flatten } from '../../util/array'
 }
 
I src/lsp/util/getLanguageBoundaries.ts
diff --git a/src/lsp/util/getLanguageBoundaries.ts b/src/lsp/util/getLanguageBoundaries.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dfef2300d3a9052cb3f60970538858b81d8af39b
--- /dev/null
+++ b/src/lsp/util/getLanguageBoundaries.ts
@@ -0,0 +1,75 @@
+import { TextDocument, Range } from 'vscode-languageserver'
+import { isVueDoc, isHtmlDoc, isSvelteDoc } from './html'
+import { State } from './state'
+import { findAll, indexToPosition } from './find'
+import { isJsDoc } from './js'
+
+export interface LanguageBoundaries {
+  html: Range[]
+  css: Range[]
+}
+
+export function getLanguageBoundaries(
+  state: State,
+  doc: TextDocument
+): LanguageBoundaries | null {
+  if (isVueDoc(doc)) {
+    let text = doc.getText()
+    let blocks = findAll(
+      /<(?<type>template|style|script)\b[^>]*>.*?(<\/\k<type>>|$)/gis,
+      text
+    )
+    let htmlRanges: Range[] = []
+    let cssRanges: Range[] = []
+    for (let i = 0; i < blocks.length; i++) {
+      let range = {
+        start: indexToPosition(text, blocks[i].index),
+        end: indexToPosition(text, blocks[i].index + blocks[i][0].length),
+      }
+      if (blocks[i].groups.type === 'style') {
+        cssRanges.push(range)
+      } else {
+        htmlRanges.push(range)
+      }
+    }
+
+    return {
+      html: htmlRanges,
+      css: cssRanges,
+    }
+  }
+
+  if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) {
+    let text = doc.getText()
+    let styleBlocks = findAll(/<style(?:\s[^>]*>|>).*?(<\/style>|$)/gis, text)
+    let htmlRanges: Range[] = []
+    let cssRanges: Range[] = []
+    let currentIndex = 0
+
+    for (let i = 0; i < styleBlocks.length; i++) {
+      htmlRanges.push({
+        start: indexToPosition(text, currentIndex),
+        end: indexToPosition(text, styleBlocks[i].index),
+      })
+      cssRanges.push({
+        start: indexToPosition(text, styleBlocks[i].index),
+        end: indexToPosition(
+          text,
+          styleBlocks[i].index + styleBlocks[i][0].length
+        ),
+      })
+      currentIndex = styleBlocks[i].index + styleBlocks[i][0].length
+    }
+    htmlRanges.push({
+      start: indexToPosition(text, currentIndex),
+      end: indexToPosition(text, text.length),
+    })
+
+    return {
+      html: htmlRanges,
+      css: cssRanges,
+    }
+  }
+
+  return null
+}