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