1+ // Core
2+ import {
3+ Diagnostic ,
4+ Range ,
5+ SemanticTokenModifiers ,
6+ SemanticTokenTypes ,
7+ SymbolInformation ,
8+ SymbolKind
9+ } from 'vscode-languageserver' ;
10+
11+ // Antlr
12+ import { ParserRuleContext , TerminalNode } from 'antlr4ng' ;
13+
14+ // Project
15+ import { SemanticToken } from '../capabilities/semanticTokens' ;
16+ import { FoldingRange , FoldingRangeKind } from '../capabilities/folding' ;
17+ import { BaseContextSyntaxElement , BaseIdentifyableSyntaxElement , HasSemanticTokenCapability } from '../project/elements/base' ;
18+
19+
20+ abstract class BaseCapability {
21+ element : BaseContextSyntaxElement < ParserRuleContext >
22+
23+ constructor ( element : BaseContextSyntaxElement < ParserRuleContext > ) {
24+ this . element = element ;
25+ }
26+ }
27+
28+
29+ export class FoldingRangeCapability extends BaseCapability {
30+ foldingRangeKind ?: FoldingRangeKind ;
31+
32+ get foldingRange ( ) : FoldingRange {
33+ return new FoldingRange ( this . element . context . range , this . foldingRangeKind ) ;
34+ }
35+
36+ constructor ( element : BaseContextSyntaxElement < ParserRuleContext > , foldingRangeKind ?: FoldingRangeKind ) {
37+ super ( element ) ;
38+ this . foldingRangeKind = foldingRangeKind ;
39+ }
40+ }
41+
42+
43+ export class DiagnosticCapability extends BaseCapability {
44+ diagnostics : Diagnostic [ ] = [ ] ;
45+ evaluate : ( ...args : any [ ] ) => Diagnostic [ ]
46+
47+ constructor ( element : BaseContextSyntaxElement < ParserRuleContext > , evaluate ?: ( ...args : any [ ] ) => Diagnostic [ ] ) {
48+ super ( element ) ;
49+ this . evaluate = evaluate ?? ( ( ) => this . diagnostics ) ;
50+ }
51+ }
52+
53+
54+ export class SemanticTokenCapability extends BaseCapability {
55+ semanticToken : SemanticToken ;
56+
57+ constructor ( element : BaseContextSyntaxElement < ParserRuleContext > & HasSemanticTokenCapability , tokenType : SemanticTokenTypes , tokenModifiers : SemanticTokenModifiers [ ] , range ?: Range , tokLength ?: number ) {
58+ super ( element ) ;
59+
60+ const context = ! ! element . identifierCapability
61+ ? element . identifierCapability . element . context
62+ : element . context ;
63+
64+ const startLine = range ?. start . line ?? context . range . start . line ;
65+ const startChar = range ?. start . character ?? context . range . start . character ;
66+ const textLength = tokLength ?? context . text . length ;
67+
68+ this . semanticToken = new SemanticToken (
69+ element ,
70+ startLine ,
71+ startChar ,
72+ textLength ,
73+ tokenType ,
74+ tokenModifiers
75+ ) ;
76+ }
77+ }
78+
79+
80+ export class SymbolInformationCapability extends BaseCapability {
81+ private symbolKind : SymbolKind
82+
83+ get SymbolInformation ( ) : SymbolInformation {
84+ const element = this . element as BaseIdentifyableSyntaxElement < ParserRuleContext > ;
85+ return SymbolInformation . create (
86+ element . identifierCapability . name ,
87+ this . symbolKind ,
88+ element . context . range ,
89+ element . context . document . uri
90+ )
91+ }
92+
93+ constructor ( element : BaseIdentifyableSyntaxElement < ParserRuleContext > , symbolKind : SymbolKind ) {
94+ super ( element ) ;
95+ this . symbolKind = symbolKind ;
96+ }
97+ }
98+
99+ interface IdentifierArgs {
100+ element : BaseContextSyntaxElement < ParserRuleContext > ,
101+ getNameContext ?: ( ) => ParserRuleContext | TerminalNode | null | undefined ,
102+ formatName ?: ( name : string ) => string ,
103+ defaultName ?: string ;
104+ defaultRange ?: ( ) => Range ;
105+ }
106+
107+
108+ export class IdentifierCapability extends BaseCapability {
109+ nameContext ?: ParserRuleContext | TerminalNode | null ;
110+ range : Range ;
111+ name : string ;
112+
113+ constructor ( args : IdentifierArgs ) {
114+ super ( args . element ) ;
115+
116+ this . nameContext = ( args . getNameContext ?? ( ( ) => args . element . context . rule ) ) ( ) ;
117+
118+ if ( ! ! this . nameContext ) {
119+ // Use the context to set the values.
120+ this . name = ( args . formatName ?? ( ( name : string ) => name ) ) ( this . nameContext . getText ( ) ) ;
121+ this . range = this . nameContext . toRange ( args . element . context . document ) ;
122+ } else {
123+ // Use the defaults to set the values.
124+ if ( ! args . defaultRange ) throw new Error ( "Default range not optional where name context not found." ) ;
125+ this . name = ( args . defaultName ?? "Unknown Element" ) ;
126+ this . range = ! ! args . defaultRange ? args . defaultRange ( ) : args . element . context . range ;
127+ }
128+ }
129+ }
0 commit comments