修代码补全
This commit is contained in:
+28
-11
@@ -1,6 +1,10 @@
|
||||
import * as vscode from "vscode";
|
||||
import { parseXml, type XmlElement } from "../language/xmlParser";
|
||||
import { analyzeContext, type CompletionContext } from "../language/context";
|
||||
import {
|
||||
analyzeContext,
|
||||
splitListValuePrefix,
|
||||
type CompletionContext,
|
||||
} from "../language/context";
|
||||
import { resolveElementType } from "../language/typeContext";
|
||||
import * as model from "../model/schemaModel";
|
||||
import { isLocalReferenceAttribute } from "../indexer/refs";
|
||||
@@ -178,12 +182,31 @@ export class Ra3CompletionProvider implements vscode.CompletionItemProvider {
|
||||
const el = ctx.element;
|
||||
const attr = ctx.attr;
|
||||
if (!el || !attr) return [];
|
||||
const prefix = ctx.valuePrefix;
|
||||
const rawPrefix = ctx.valuePrefix;
|
||||
|
||||
const endOffset = attr.quoteEnd > attr.valueEnd ? attr.valueEnd : document.offsetAt(position);
|
||||
const attrName = attr.name.toLowerCase();
|
||||
const elType = resolveElementType(el);
|
||||
const attrInfo = model
|
||||
.attributesOfType(elType)
|
||||
.find((a) => a.name.toLowerCase() === attrName);
|
||||
|
||||
// xs:list values (bit flags such as Surfaces="GROUND WATER") are
|
||||
// whitespace-separated: only the token currently being edited is used for
|
||||
// filtering, and the replacement range covers that token instead of the
|
||||
// whole value.
|
||||
const seg = attrInfo?.isList
|
||||
? splitListValuePrefix(rawPrefix)
|
||||
: { token: rawPrefix, start: 0 };
|
||||
const prefix = seg.token;
|
||||
|
||||
const valueStartOffset =
|
||||
attr.valueStart >= 0 ? attr.valueStart : document.offsetAt(position);
|
||||
const endOffset =
|
||||
attr.quoteEnd > attr.valueEnd ? attr.valueEnd : document.offsetAt(position);
|
||||
const rangeStart = valueStartOffset + seg.start;
|
||||
const valueRange = new vscode.Range(
|
||||
document.positionAt(attr.valueStart),
|
||||
document.positionAt(Math.max(attr.valueStart, endOffset)),
|
||||
document.positionAt(rangeStart),
|
||||
document.positionAt(Math.max(rangeStart, endOffset)),
|
||||
);
|
||||
|
||||
const make = (
|
||||
@@ -201,7 +224,6 @@ export class Ra3CompletionProvider implements vscode.CompletionItemProvider {
|
||||
};
|
||||
|
||||
const isInclude = el.name === "Include";
|
||||
const attrName = attr.name.toLowerCase();
|
||||
|
||||
// Include type / source
|
||||
if (isInclude && attrName === "type") {
|
||||
@@ -218,11 +240,6 @@ export class Ra3CompletionProvider implements vscode.CompletionItemProvider {
|
||||
);
|
||||
}
|
||||
|
||||
const elType = resolveElementType(el);
|
||||
const attrInfo = model
|
||||
.attributesOfType(elType)
|
||||
.find((a) => a.name.toLowerCase() === attrName);
|
||||
|
||||
// inheritFrom: same element type first, then everything.
|
||||
if (attrName === "inheritfrom") {
|
||||
return this.assetIdItems(idx, el.name, null, prefix, make);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import * as vscode from "vscode";
|
||||
import { parseXml } from "../language/xmlParser";
|
||||
import { buildSemanticTokenRanges } from "../language/semanticTokens";
|
||||
|
||||
const TOKEN_TYPES = ["type", "property", "string"] as const;
|
||||
|
||||
export const RA3_SEMANTIC_TOKENS_LEGEND = new vscode.SemanticTokensLegend([
|
||||
...TOKEN_TYPES,
|
||||
]);
|
||||
|
||||
/**
|
||||
* Highlighting fallback for malformed XML.
|
||||
*
|
||||
* While the document is well-formed, the built-in TextMate XML grammar colors
|
||||
* it as usual and this provider returns no tokens, so nothing changes. When
|
||||
* parsing reports errors (e.g. an attribute value whose closing quote has not
|
||||
* been typed yet), the TextMate structure is lost, and these semantic tokens
|
||||
* keep element names, attribute names and values colored.
|
||||
*/
|
||||
export class Ra3SemanticTokensProvider
|
||||
implements vscode.DocumentSemanticTokensProvider
|
||||
{
|
||||
async provideDocumentSemanticTokens(
|
||||
document: vscode.TextDocument,
|
||||
_token: vscode.CancellationToken,
|
||||
): Promise<vscode.SemanticTokens> {
|
||||
const text = document.getText();
|
||||
const doc = parseXml(text);
|
||||
if (doc.errors.length === 0) {
|
||||
return new vscode.SemanticTokens(new Uint32Array(0));
|
||||
}
|
||||
const ranges = buildSemanticTokenRanges(doc, text);
|
||||
const builder = new vscode.SemanticTokensBuilder(RA3_SEMANTIC_TOKENS_LEGEND);
|
||||
for (const r of ranges) {
|
||||
builder.push(
|
||||
new vscode.Range(r.line, r.startChar, r.line, r.startChar + r.length),
|
||||
r.tokenType,
|
||||
);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user