Improve conflict diagnostics (#503)
parent
86497bb380
commit
ddfaea21cc
|
@ -20,7 +20,9 @@ export async function getCssConflictDiagnostics(
|
|||
const classLists = await findClassListsInDocument(state, document)
|
||||
|
||||
classLists.forEach((classList) => {
|
||||
const classNames = getClassNamesInClassList(classList)
|
||||
const classNames = Array.isArray(classList)
|
||||
? classList.flatMap(getClassNamesInClassList)
|
||||
: getClassNamesInClassList(classList)
|
||||
|
||||
classNames.forEach((className, index) => {
|
||||
if (state.jit) {
|
||||
|
|
|
@ -22,7 +22,7 @@ export async function getRecommendedVariantOrderDiagnostics(
|
|||
let diagnostics: RecommendedVariantOrderDiagnostic[] = []
|
||||
const classLists = await findClassListsInDocument(state, document)
|
||||
|
||||
classLists.forEach((classList) => {
|
||||
classLists.flat().forEach((classList) => {
|
||||
const classNames = getClassNamesInClassList(classList)
|
||||
classNames.forEach((className) => {
|
||||
let { rules } = jit.generateRules(state, [className.className])
|
||||
|
|
|
@ -20,7 +20,7 @@ export async function getDocumentColors(
|
|||
if (settings.tailwindCSS.colorDecorators === false) return colors
|
||||
|
||||
let classLists = await findClassListsInDocument(state, document)
|
||||
classLists.forEach((classList) => {
|
||||
classLists.flat().forEach((classList) => {
|
||||
let classNames = getClassNamesInClassList(classList)
|
||||
classNames.forEach((className) => {
|
||||
let color = getColor(state, className.className)
|
||||
|
|
|
@ -77,7 +77,15 @@ export async function findClassNamesInRange(
|
|||
includeCustom: boolean = true
|
||||
): Promise<DocumentClassName[]> {
|
||||
const classLists = await findClassListsInRange(state, doc, range, mode, includeCustom)
|
||||
return flatten(classLists.map(getClassNamesInClassList))
|
||||
return flatten(
|
||||
classLists.flatMap((classList) => {
|
||||
if (Array.isArray(classList)) {
|
||||
return classList.map(getClassNamesInClassList)
|
||||
} else {
|
||||
return [getClassNamesInClassList(classList)]
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export async function findClassNamesInDocument(
|
||||
|
@ -85,7 +93,15 @@ export async function findClassNamesInDocument(
|
|||
doc: TextDocument
|
||||
): Promise<DocumentClassName[]> {
|
||||
const classLists = await findClassListsInDocument(state, doc)
|
||||
return flatten(classLists.map(getClassNamesInClassList))
|
||||
return flatten(
|
||||
classLists.flatMap((classList) => {
|
||||
if (Array.isArray(classList)) {
|
||||
return classList.map(getClassNamesInClassList)
|
||||
} else {
|
||||
return [getClassNamesInClassList(classList)]
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export function findClassListsInCssRange(doc: TextDocument, range?: Range): DocumentClassList[] {
|
||||
|
@ -182,7 +198,7 @@ export async function findClassListsInHtmlRange(
|
|||
state: State,
|
||||
doc: TextDocument,
|
||||
range?: Range
|
||||
): Promise<DocumentClassList[]> {
|
||||
): Promise<Array<DocumentClassList | DocumentClassList[]>> {
|
||||
const text = doc.getText(range)
|
||||
|
||||
const matches = matchClassAttributes(
|
||||
|
@ -190,7 +206,7 @@ export async function findClassListsInHtmlRange(
|
|||
(await state.editor.getConfiguration(doc.uri)).tailwindCSS.classAttributes
|
||||
)
|
||||
|
||||
const result: DocumentClassList[] = []
|
||||
const result: Array<DocumentClassList | DocumentClassList[]> = []
|
||||
|
||||
matches.forEach((match) => {
|
||||
const subtext = text.substr(match.index + match[0].length - 1)
|
||||
|
@ -201,9 +217,11 @@ export async function findClassListsInHtmlRange(
|
|||
: getClassAttributeLexer()
|
||||
lexer.reset(subtext)
|
||||
|
||||
let classLists: { value: string; offset: number }[] = []
|
||||
let token: moo.Token
|
||||
let classLists: Array<{ value: string; offset: number } | { value: string; offset: number }[]> =
|
||||
[]
|
||||
let rootClassList: { value: string; offset: number }[] = []
|
||||
let currentClassList: { value: string; offset: number }
|
||||
let depth = 0
|
||||
|
||||
try {
|
||||
for (let token of lexer) {
|
||||
|
@ -218,56 +236,53 @@ export async function findClassListsInHtmlRange(
|
|||
}
|
||||
} else {
|
||||
if (currentClassList) {
|
||||
classLists.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
if (depth === 0) {
|
||||
rootClassList.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
} else {
|
||||
classLists.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
}
|
||||
}
|
||||
currentClassList = undefined
|
||||
}
|
||||
if (token.type === 'lbrace') {
|
||||
depth += 1
|
||||
} else if (token.type === 'rbrace') {
|
||||
depth -= 1
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
if (currentClassList) {
|
||||
classLists.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
if (depth === 0) {
|
||||
rootClassList.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
} else {
|
||||
classLists.push({
|
||||
value: currentClassList.value,
|
||||
offset: currentClassList.offset,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
classLists.push(rootClassList)
|
||||
|
||||
result.push(
|
||||
...classLists
|
||||
.map(({ value, offset }) => {
|
||||
if (value.trim() === '') {
|
||||
return null
|
||||
}
|
||||
|
||||
const before = value.match(/^\s*/)
|
||||
const beforeOffset = before === null ? 0 : before[0].length
|
||||
const after = value.match(/\s*$/)
|
||||
const afterOffset = after === null ? 0 : -after[0].length
|
||||
|
||||
const start = indexToPosition(
|
||||
text,
|
||||
match.index + match[0].length - 1 + offset + beforeOffset
|
||||
)
|
||||
const end = indexToPosition(
|
||||
text,
|
||||
match.index + match[0].length - 1 + offset + value.length + afterOffset
|
||||
)
|
||||
|
||||
return {
|
||||
classList: value.substr(beforeOffset, value.length + afterOffset),
|
||||
range: {
|
||||
start: {
|
||||
line: (range?.start.line || 0) + start.line,
|
||||
character: (end.line === 0 ? range?.start.character || 0 : 0) + start.character,
|
||||
},
|
||||
end: {
|
||||
line: (range?.start.line || 0) + end.line,
|
||||
character: (end.line === 0 ? range?.start.character || 0 : 0) + end.character,
|
||||
},
|
||||
},
|
||||
.map((classList) => {
|
||||
if (Array.isArray(classList)) {
|
||||
return classList
|
||||
.map((classList) => resolveClassList(classList, text, match, range))
|
||||
.filter((x) => x !== null)
|
||||
} else {
|
||||
return resolveClassList(classList, text, match, range)
|
||||
}
|
||||
})
|
||||
.filter((x) => x !== null)
|
||||
|
@ -277,14 +292,51 @@ export async function findClassListsInHtmlRange(
|
|||
return result
|
||||
}
|
||||
|
||||
function resolveClassList(
|
||||
classList: { value: string; offset: number },
|
||||
text: string,
|
||||
match: RegExpMatchArray,
|
||||
range?: Range
|
||||
): DocumentClassList {
|
||||
let { value, offset } = classList
|
||||
if (value.trim() === '') {
|
||||
return null
|
||||
}
|
||||
|
||||
const before = value.match(/^\s*/)
|
||||
const beforeOffset = before === null ? 0 : before[0].length
|
||||
const after = value.match(/\s*$/)
|
||||
const afterOffset = after === null ? 0 : -after[0].length
|
||||
|
||||
const start = indexToPosition(text, match.index + match[0].length - 1 + offset + beforeOffset)
|
||||
const end = indexToPosition(
|
||||
text,
|
||||
match.index + match[0].length - 1 + offset + value.length + afterOffset
|
||||
)
|
||||
|
||||
return {
|
||||
classList: value.substr(beforeOffset, value.length + afterOffset),
|
||||
range: {
|
||||
start: {
|
||||
line: (range?.start.line || 0) + start.line,
|
||||
character: (end.line === 0 ? range?.start.character || 0 : 0) + start.character,
|
||||
},
|
||||
end: {
|
||||
line: (range?.start.line || 0) + end.line,
|
||||
character: (end.line === 0 ? range?.start.character || 0 : 0) + end.character,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function findClassListsInRange(
|
||||
state: State,
|
||||
doc: TextDocument,
|
||||
range?: Range,
|
||||
mode?: 'html' | 'css',
|
||||
includeCustom: boolean = true
|
||||
): Promise<DocumentClassList[]> {
|
||||
let classLists: DocumentClassList[]
|
||||
): Promise<Array<DocumentClassList | DocumentClassList[]>> {
|
||||
let classLists: Array<DocumentClassList | DocumentClassList[]>
|
||||
if (mode === 'css') {
|
||||
classLists = findClassListsInCssRange(doc, range)
|
||||
} else {
|
||||
|
@ -296,7 +348,7 @@ export async function findClassListsInRange(
|
|||
export async function findClassListsInDocument(
|
||||
state: State,
|
||||
doc: TextDocument
|
||||
): Promise<DocumentClassList[]> {
|
||||
): Promise<Array<DocumentClassList | DocumentClassList[]>> {
|
||||
if (isCssDoc(state, doc)) {
|
||||
return findClassListsInCssRange(doc)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue