Skip to content

Commit

Permalink
Add DefinitionMatcher because definition.key options was getting too …
Browse files Browse the repository at this point in the history
…complicated
  • Loading branch information
cooolbros committed Jan 20, 2025
1 parent d4aaf16 commit ae4ead9
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 96 deletions.
26 changes: 20 additions & 6 deletions packages/server/src/VDF/Popfile/PopfileTextDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ export class PopfileTextDocument extends VDFTextDocument<PopfileTextDocument, Po
{
type: Symbol.for("template"),
definition: {
directParentKeys: ["Templates".toLowerCase()],
children: true,
key: null
match: (documentSymbol, path) => {
if (documentSymbol.children != undefined && path.length == 2 && path.at(-1)!.key.toLowerCase() == "Templates".toLowerCase()) {
return {
key: documentSymbol.key,
keyRange: documentSymbol.nameRange,
}
}
}
},
reference: {
keys: new Set(["Template".toLowerCase()]),
Expand All @@ -37,9 +42,18 @@ export class PopfileTextDocument extends VDFTextDocument<PopfileTextDocument, Po
{
type: Symbol.for("wavespawn"),
definition: {
directParentKeys: ["Wave".toLowerCase()],
children: true,
key: { name: "name", priority: true }
match: (documentSymbol, path) => {
if (documentSymbol.children != undefined && path.length == 2 && documentSymbol.key.toLowerCase() == "WaveSpawn".toLowerCase() && path.at(-1)!.key.toLowerCase() == "Wave".toLowerCase()) {
const name = documentSymbol.children.find((documentSymbol) => documentSymbol.key.toLowerCase() == "Name".toLowerCase())
if (name && name.detail != undefined) {
return {
key: name.detail,
keyRange: documentSymbol.nameRange,
nameRange: name.detailRange,
}
}
}
}
},
reference: {
keys: new Set([
Expand Down
67 changes: 19 additions & 48 deletions packages/server/src/VDF/VDFTextDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,7 @@ export interface VDFTextDocumentSchema {
values: Record<string, { kind: number, enumIndex?: boolean, values: string[], fix?: Record<string, string> }>
definitionReferences: {
type: symbol
definition: {
directParentKeys: string[]
children: boolean
key: {
/**
* @example "fieldName"
* @example "name"
*/
name: string,
/**
* Whether to override documentSymbol.key
*/
priority: boolean
} | null
} | null
definition: DefinitionMatcher | null
reference?: {
keys: Set<string>
match: ((string: string) => boolean) | null
Expand Down Expand Up @@ -125,6 +111,16 @@ export interface VDFTextDocumentSchema {
}
}

export interface DefinitionMatcher {
match(documentSymbol: VDFDocumentSymbol, path: VDFDocumentSymbol[]): DefinitionResult | void
}

export interface DefinitionResult {
key: string
keyRange: VDFRange
nameRange?: VDFRange
}

export abstract class VDFTextDocument<TDocument extends VDFTextDocument<TDocument, TDependencies>, TDependencies> extends TextDocumentBase<VDFDocumentSymbols, VDFTextDocumentDependencies> {

public readonly configuration: VDFTextDocumentConfiguration<TDocument, TDependencies>
Expand Down Expand Up @@ -310,43 +306,18 @@ export abstract class VDFTextDocument<TDocument extends VDFTextDocument<TDocumen
for (const { type, definition, reference } of dependencies.schema.definitionReferences) {

if (definition) {

let key: string | undefined, keyRange: VDFRange | undefined, nameRange: VDFRange | undefined

if (definition.key != null) {
const keyDocumentSymbol = documentSymbol.children?.find((i) => i.key.toLowerCase() == definition.key!.name && i.detail != undefined)
if (keyDocumentSymbol) {
key = documentSymbol.key
keyRange = documentSymbol.nameRange
nameRange = keyDocumentSymbol.detailRange!
}
else if (!definition.key.priority) {
// If key does not need priority, fall back to documentSymbol.key, used for VGUI elements that don't have a fieldName
key = documentSymbol.key
keyRange = documentSymbol.nameRange
nameRange = undefined
}
else {
key = undefined
keyRange = undefined
nameRange = undefined
}
}
else {
key = documentSymbol.key
keyRange = documentSymbol.nameRange
nameRange = undefined
}

if (key && keyRange && ArrayEndsWithArray(path, definition.directParentKeys, (a, b,) => a.key.toLowerCase() == b.toLowerCase()) && ((definition.children ? documentSymbol.children : documentSymbol.detail) != undefined)) {
definitionReferences.definitions.add(type, key, {
const result = definition.match(documentSymbol, path)
if (result) {
definitionReferences.definitions.add(type, result.key, {
uri: this.uri,
key: key,
key: result.key,
range: documentSymbol.range,
keyRange: keyRange,
nameRange: nameRange,
keyRange: result.keyRange,
nameRange: result.nameRange,
detail: documentSymbol.detail
})

return
}
}

Expand Down
52 changes: 19 additions & 33 deletions packages/server/src/VDF/VGUI/schemas/ClientSchemeSchema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import type { VDFDocumentSymbol } from "vdf-documentsymbols"
import { CompletionItemKind } from "vscode-languageserver"
import type { VDFTextDocumentSchema } from "../../VDFTextDocument"
import type { DefinitionMatcher, DefinitionResult, VDFTextDocumentSchema } from "../../VDFTextDocument"

class SchemeDefinitionMatcher implements DefinitionMatcher {

constructor(private readonly type: string, private readonly children: boolean) { }
match(documentSymbol: VDFDocumentSymbol, path: VDFDocumentSymbol[]): DefinitionResult | undefined {
if (path.length == 2 && (documentSymbol.children != undefined) == this.children && path[0].key.toLowerCase() == "Scheme".toLowerCase() && path[1].key.toLowerCase() == this.type.toLowerCase()) {
return {
key: documentSymbol.key,
keyRange: documentSymbol.nameRange,
}
}
}
}

export const ClientSchemeSchema: VDFTextDocumentSchema = {
keys: {},
Expand All @@ -22,14 +36,7 @@ export const ClientSchemeSchema: VDFTextDocumentSchema = {
definitionReferences: [
{
type: Symbol.for("color"),
definition: {
directParentKeys: [
"Scheme".toLowerCase(),
"Colors".toLowerCase(),
],
children: false,
key: null,
},
definition: new SchemeDefinitionMatcher("Colors", false),
reference: {
keys: new Set("color"),
match: null
Expand All @@ -50,14 +57,7 @@ export const ClientSchemeSchema: VDFTextDocumentSchema = {
},
{
type: Symbol.for("color"),
definition: {
directParentKeys: [
"Scheme".toLowerCase(),
"BaseSettings".toLowerCase(),
],
children: false,
key: null,
},
definition: new SchemeDefinitionMatcher("BaseSettings", false),
reference: {
keys: new Set("color"),
match: null
Expand All @@ -78,14 +78,7 @@ export const ClientSchemeSchema: VDFTextDocumentSchema = {
},
{
type: Symbol.for("border"),
definition: {
directParentKeys: [
"Scheme".toLowerCase(),
"Borders".toLowerCase(),
],
children: true,
key: null,
},
definition: new SchemeDefinitionMatcher("Borders", true),
reference: {
keys: new Set(),
match: null
Expand All @@ -94,14 +87,7 @@ export const ClientSchemeSchema: VDFTextDocumentSchema = {
},
{
type: Symbol.for("font"),
definition: {
directParentKeys: [
"Scheme".toLowerCase(),
"Fonts".toLowerCase(),
],
children: true,
key: null,
},
definition: new SchemeDefinitionMatcher("Fonts", true),
reference: {
keys: new Set(),
match: null
Expand Down
14 changes: 8 additions & 6 deletions packages/server/src/VDF/VGUI/schemas/LanguageTokensSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ export const LanguageTokensSchema: VDFTextDocumentSchema = {
{
type: Symbol.for("string"),
definition: {
directParentKeys: [
"lang",
"Tokens".toLowerCase()
],
children: false,
key: null,
match: (documentSymbol, path) => {
if (path.length == 2 && documentSymbol.detail != undefined && path[0].key.toLowerCase() == "lang".toLowerCase() && path[1].key.toLowerCase() == "Tokens".toLowerCase()) {
return {
key: documentSymbol.key,
keyRange: documentSymbol.nameRange,
}
}
}
},
toReference: (value) => `#${value}`,
toCompletionItem: (definition) => ({ kind: CompletionItemKind.Text, insertText: `#${definition.key}` })
Expand Down
12 changes: 9 additions & 3 deletions packages/server/src/VDF/VGUI/schemas/VGUISchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export const VGUISchema: VDFTextDocumentSchema = {
{
type: Symbol.for("element"),
definition: {
directParentKeys: [],
children: true,
key: { name: "fieldName".toLowerCase(), priority: false }
match: (documentSymbol, path) => {
if (documentSymbol.children != undefined && path.length != 0) {
return {
key: documentSymbol.key,
keyRange: documentSymbol.nameRange,
nameRange: documentSymbol.children?.find((i) => i.key.toLowerCase() == "fieldName".toLowerCase() && i.detail != undefined)?.detailRange
}
}
}
},
reference: {
keys: new Set([
Expand Down

0 comments on commit ae4ead9

Please sign in to comment.