tailwind-ctp-intellisense @master -
refs -
log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
diagnostics
5 changed files, 96 additions(+), 6 deletions(-)
diff --git a/src/lsp/providers/diagnosticsProvider.ts b/src/lsp/providers/diagnosticsProvider.ts
new file mode 100644
index 0000000000000000000000000000000000000000..51565e9c5cb5a4d1f3291a37a4c28d99a220d47d
--- /dev/null
+++ b/src/lsp/providers/diagnosticsProvider.ts
@@ -0,0 +1,79 @@
+import {
+ TextDocument,
+ Diagnostic,
+ DiagnosticSeverity,
+} from 'vscode-languageserver'
+import { State } from '../util/state'
+import { isCssDoc } from '../util/css'
+import { findClassNamesInRange } from '../util/find'
+import { getClassNameParts } from '../util/getClassNameAtPosition'
+const dlv = require('dlv')
+
+function provideCssDiagnostics(state: State, document: TextDocument): void {
+ const classNames = findClassNamesInRange(document)
+
+ let diagnostics: Diagnostic[] = classNames
+ .map(({ className, range }) => {
+ const parts = getClassNameParts(state, className)
+ if (!parts) return null
+ const info = dlv(state.classNames.classNames, parts)
+ let message: string
+ if (info.__context && info.__context.length > 0) {
+ if (info.__context.length === 1) {
+ message = `\`@apply\` cannot be used with \`.${className}\` because it is nested inside of an at-rule (${info.__context[0]}).`
+ } else {
+ message = `\`@apply\` cannot be used with \`.${className}\` because it is nested inside of at-rules (${info.__context.join(
+ ', '
+ )}).`
+ }
+ } else if (info.__pseudo && info.__pseudo.length > 0) {
+ if (info.__pseudo.length === 1) {
+ message = `\`@apply\` cannot be used with \`.${className}\` because its definition includes a pseudo-selector (${info.__pseudo[0]})`
+ } else {
+ message = `\`@apply\` cannot be used with \`.${className}\` because its definition includes pseudo-selectors (${info.__pseudo.join(
+ ', '
+ )})`
+ }
+ }
+
+ if (!message) return null
+
+ return {
+ severity: DiagnosticSeverity.Error,
+ range,
+ message,
+ // source: 'ex',
+ }
+ })
+ .filter(Boolean)
+
+ // if (state.editor.capabilities.diagnosticRelatedInformation) {
+ // diagnostic.relatedInformation = [
+ // {
+ // location: {
+ // uri: document.uri,
+ // range: Object.assign({}, diagnostic.range),
+ // },
+ // message: '',
+ // },
+ // {
+ // location: {
+ // uri: document.uri,
+ // range: Object.assign({}, diagnostic.range),
+ // },
+ // message: '',
+ // },
+ // ]
+ // }
+
+ state.editor.connection.sendDiagnostics({ uri: document.uri, diagnostics })
+}
+
+export async function provideDiagnostics(
+ state: State,
+ document: TextDocument
+): Promise<void> {
+ if (isCssDoc(state, document)) {
+ return provideCssDiagnostics(state, document)
+ }
+}
diff --git a/src/lsp/server.ts b/src/lsp/server.ts
index b28b1bad9d226222f5d9e24472c9d8d698df6187..480aa289e7b5035e907891fd287bf45baeddd159 100644
--- a/src/lsp/server.ts
+++ b/src/lsp/server.ts
@@ -26,6 +26,7 @@ } from './providers/completionProvider'
import { provideHover } from './providers/hoverProvider'
import { URI } from 'vscode-uri'
import { getDocumentSettings } from './util/getDocumentSettings'
+import { provideDiagnostics } from './providers/diagnosticsProvider'
let state: State = { enabled: false }
let connection = createConnection(ProposedFeatures.all)
@@ -45,6 +46,9 @@ })
documents.onDidClose((event) => {
documentSettings.delete(event.document.uri)
})
+documents.onDidChangeContent((change) => {
+ provideDiagnostics(state, change.document)
+})
documents.listen(connection)
connection.onInitialize(
@@ -64,6 +68,10 @@ : {},
capabilities: {
configuration:
capabilities.workspace && !!capabilities.workspace.configuration,
+ diagnosticRelatedInformation:
+ capabilities.textDocument &&
+ capabilities.textDocument.publishDiagnostics &&
+ capabilities.textDocument.publishDiagnostics.relatedInformation,
},
}
diff --git a/src/lsp/util/css.ts b/src/lsp/util/css.ts
index 84b788889c876707b4201ba3d2093b8bb472dd2f..d1acbea2b4e6e166e57d7d604ac2e615d1e94a0b 100644
--- a/src/lsp/util/css.ts
+++ b/src/lsp/util/css.ts
@@ -11,8 +11,8 @@ 'scss',
'stylus',
]
-import { TextDocument, Position } from 'vscode-languageserver'
import { State } from './state'
+
const userCssLanguages = Object.keys(
state.editor.userLanguages
).filter((lang) => CSS_LANGUAGES.includes(state.editor.userLanguages[lang]))
diff --git a/src/lsp/util/find.ts b/src/lsp/util/find.ts
index 3fb04517624e5208d2b2c4f2152e3285e1bb9d8a..17b6a127654ae8b748941e828167512078286361 100644
--- a/src/lsp/util/find.ts
+++ b/src/lsp/util/find.ts
@@ -72,7 +72,7 @@ }
export function findClassNamesInRange(
doc: TextDocument,
- range: Range
+ range?: Range
): DocumentClassName[] {
const classLists = findClassListsInRange(doc, range)
return [].concat.apply(
@@ -111,10 +111,11 @@ }
export function findClassListsInRange(
doc: TextDocument,
- range: Range
+ range?: Range
): DocumentClassList[] {
const text = doc.getText(range)
const matches = findAll(/(@apply\s+)(?<classList>[^;}]+)[;}]/g, text)
+ const globalStart: Position = range ? range.start : { line: 0, character: 0 }
return matches.map((match) => {
const start = indexToPosition(text, match.index + match[1].length)
@@ -127,15 +128,16 @@ classList: match.groups.classList,
range: {
start: {
import { TextDocument, Range, Position } from 'vscode-languageserver'
- let match: RegExpMatchArray
+ for (let i = arr.length - 1; i >= 0; --i) {
import { TextDocument, Range, Position } from 'vscode-languageserver'
+import { DocumentClassName, DocumentClassList } from './state'
- let matches: RegExpMatchArray[] = []
},
end: {
import { TextDocument, Range, Position } from 'vscode-languageserver'
+import { DocumentClassName, DocumentClassList } from './state'
import { TextDocument, Range, Position } from 'vscode-languageserver'
import { TextDocument, Range, Position } from 'vscode-languageserver'
- return matches
+ return x
},
},
}
diff --git a/src/lsp/util/state.ts b/src/lsp/util/state.ts
index daaa0501c05f20e0e88dc85c4357533d26e4a74d..fc474eb4e418d6628542a8d78c69e54d6d9288b6 100644
--- a/src/lsp/util/state.ts
+++ b/src/lsp/util/state.ts
@@ -21,6 +21,7 @@ globalSettings: Settings
userLanguages: Record<string, string>
capabilities: {
configuration: boolean
+ diagnosticRelatedInformation: boolean
}
}