Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions client/src/test/diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ suite('Should get diagnostics', () => {
range: toRange(28, 7, 32, 8),
severity: vscode.DiagnosticSeverity.Error,
source: 'ex'
},
{
message: 'Invalid syntax: InvalidSubCall(arg)',
range: toRange(43, 4, 43, 23),
severity: vscode.DiagnosticSeverity.Error,
source: 'ex'
}
]);
});
Expand Down Expand Up @@ -156,8 +162,8 @@ async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.D

expectedDiagnostics.forEach((expectedDiagnostic, i) => {
const actualDiagnostic = actualDiagnostics[i];
assert.equal(actualDiagnostic.message, expectedDiagnostic.message, "Message");
assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range, "Range");
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity, "Severity");
assert.equal(actualDiagnostic.message, expectedDiagnostic.message, `Message: expected '${expectedDiagnostic.message}' got '${actualDiagnostic.message}'.`);
assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range, `Range: expected '${JSON.stringify(expectedDiagnostic.range)}' got '${JSON.stringify(actualDiagnostic.range)}'.`);
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity, `Severity: expected '${expectedDiagnostic.severity}' got '${actualDiagnostic.severity}'.`);
});
}
29 changes: 16 additions & 13 deletions server/src/capabilities/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import { ParserRuleContext, TerminalNode } from 'antlr4ng';
// Project
import { SemanticToken } from '../capabilities/semanticTokens';
import { FoldingRange, FoldingRangeKind } from '../capabilities/folding';
import { BaseContextSyntaxElement, BaseIdentifyableSyntaxElement, Context, HasSemanticTokenCapability } from '../project/elements/base';
import { BaseRuleSyntaxElement, BaseIdentifyableSyntaxElement, BaseSyntaxElement, Context, HasSemanticTokenCapability } from '../project/elements/base';
import { BaseDiagnostic, DuplicateDeclarationDiagnostic, MethodVariableIsPublicDiagnostic, ShadowDeclarationDiagnostic, SubOrFunctionNotDefinedDiagnostic, VariableNotDefinedDiagnostic } from './diagnostics';
import { Services } from '../injection/services';


abstract class BaseCapability {
element: BaseContextSyntaxElement<ParserRuleContext>;
element: BaseRuleSyntaxElement<ParserRuleContext> | BaseSyntaxElement;

constructor(element: BaseContextSyntaxElement<ParserRuleContext>) {
constructor(element: BaseRuleSyntaxElement<ParserRuleContext> | BaseSyntaxElement) {
this.element = element;
}
}
Expand All @@ -34,17 +34,20 @@ export class FoldingRangeCapability extends BaseCapability {
closeWord?: string;

get foldingRange(): FoldingRange {
const trailingLineCount = this.element.context.rule.countTrailingLineEndings();
const start = this.element.context.range.start;
// Cast the element to the same type we get in the constructor.
const element = this.element as unknown as BaseRuleSyntaxElement<ParserRuleContext>;

const trailingLineCount = element.context.rule.countTrailingLineEndings();
const start = element.context.range.start;
const end = {
line: this.element.context.range.end.line - trailingLineCount,
character: this.element.context.range.end.character
line: element.context.range.end.line - trailingLineCount,
character: element.context.range.end.character
};
const range = Range.create(start, end);
return new FoldingRange(range, this.foldingRangeKind, this.openWord, this.closeWord);
}

constructor(element: BaseContextSyntaxElement<ParserRuleContext>, foldingRangeKind?: FoldingRangeKind) {
constructor(element: BaseRuleSyntaxElement<ParserRuleContext>, foldingRangeKind?: FoldingRangeKind) {
super(element);
this.foldingRangeKind = foldingRangeKind;
}
Expand All @@ -55,7 +58,7 @@ export class DiagnosticCapability extends BaseCapability {
diagnostics: Diagnostic[] = [];
evaluate: (...args: any[]) => Diagnostic[];

constructor(element: BaseContextSyntaxElement<ParserRuleContext>, evaluate?: (...args: any[]) => Diagnostic[]) {
constructor(element: BaseSyntaxElement, evaluate?: (...args: any[]) => Diagnostic[]) {
super(element);
this.evaluate = evaluate ?? (() => this.diagnostics);
}
Expand All @@ -69,7 +72,7 @@ export class SemanticTokenCapability extends BaseCapability {
private overrideLength?: number;

get semanticToken(): SemanticToken {
const element = this.element as BaseContextSyntaxElement<ParserRuleContext> & HasSemanticTokenCapability;
const element = this.element as BaseRuleSyntaxElement<ParserRuleContext> & HasSemanticTokenCapability;
const context = element.identifierCapability
? new Context(element.identifierCapability.nameContext, element.context.document)
: element.context;
Expand All @@ -89,7 +92,7 @@ export class SemanticTokenCapability extends BaseCapability {
);
}

constructor(element: BaseContextSyntaxElement<ParserRuleContext> & HasSemanticTokenCapability, tokenType: SemanticTokenTypes, tokenModifiers: SemanticTokenModifiers[], overrideRange?: Range, overrideLength?: number) {
constructor(element: BaseRuleSyntaxElement<ParserRuleContext> & HasSemanticTokenCapability, tokenType: SemanticTokenTypes, tokenModifiers: SemanticTokenModifiers[], overrideRange?: Range, overrideLength?: number) {
super(element);
this.tokenType = tokenType;
this.tokenModifiers = tokenModifiers;
Expand Down Expand Up @@ -119,7 +122,7 @@ export class SymbolInformationCapability extends BaseCapability {
}

interface IdentifierArgs {
element: BaseContextSyntaxElement<ParserRuleContext>,
element: BaseRuleSyntaxElement<ParserRuleContext>,
getNameContext?: () => ParserRuleContext | TerminalNode | null | undefined,
formatName?: (name: string) => string,
defaultName?: string;
Expand Down Expand Up @@ -217,7 +220,7 @@ export class ScopeItemCapability {
visibilityModifierContext?: ParserRuleContext;

constructor(
readonly element?: BaseContextSyntaxElement<ParserRuleContext>,
readonly element?: BaseRuleSyntaxElement<ParserRuleContext>,
public type: ItemType = ItemType.REFERENCE,
public assignmentType: AssignmentType = AssignmentType.NONE,
public parent?: ScopeItemCapability,
Expand Down
4 changes: 2 additions & 2 deletions server/src/capabilities/semanticTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { ParserRuleContext } from 'antlr4ng/dist/ParserRuleContext';

// Project
import { BaseContextSyntaxElement, HasSemanticTokenCapability } from '../project/elements/base';
import { BaseRuleSyntaxElement, HasSemanticTokenCapability } from '../project/elements/base';

const registeredTokenTypes = new Map<string, number>((Object.keys(SemanticTokenTypes) as (keyof typeof SemanticTokenTypes)[]).map((k, i) => ([k, i])));
const registeredTokenModifiers = new Map<string, number>((Object.keys(SemanticTokenModifiers) as (keyof typeof SemanticTokenModifiers)[]).map((k, i) => ([k, 2 ** i])));
Expand All @@ -30,7 +30,7 @@ export function activateSemanticTokenProvider(result: InitializeResult) {


type SemanticElementType = HasSemanticTokenCapability
& BaseContextSyntaxElement<ParserRuleContext>;
& BaseRuleSyntaxElement<ParserRuleContext>;

export class SemanticToken {
line: uinteger;
Expand Down
6 changes: 3 additions & 3 deletions server/src/project/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { SyntaxParser } from './parser/vbaParser';
import { FoldingRange } from '../capabilities/folding';
import { SemanticTokensManager } from '../capabilities/semanticTokens';
import {
BaseContextSyntaxElement,
BaseRuleSyntaxElement,
BaseSyntaxElement,
DeclarableElement,
HasDiagnosticCapability,
Expand Down Expand Up @@ -54,7 +54,7 @@ export abstract class BaseProjectDocument {
protected foldableElements: FoldingRange[] = [];
protected hasDiagnosticElements: HasDiagnosticCapability[] = [];
protected properties: Dictionary<string, PropertyDeclarationElement> = new Dictionary(() => new PropertyDeclarationElement());
protected redactedElements: BaseContextSyntaxElement<ParserRuleContext>[] = [];
protected redactedElements: BaseRuleSyntaxElement<ParserRuleContext>[] = [];
protected semanticTokens: SemanticTokensManager = new SemanticTokensManager();
protected symbolInformations: SymbolInformation[] = [];
protected unhandledNamedElements: [] = [];
Expand Down Expand Up @@ -255,7 +255,7 @@ export abstract class BaseProjectDocument {
return this;
};

registerSubtractElement = (element: BaseContextSyntaxElement<ParserRuleContext>) => {
registerSubtractElement = (element: BaseRuleSyntaxElement<ParserRuleContext>) => {
this.redactedElements.push(element);
return this;
};
Expand Down
47 changes: 25 additions & 22 deletions server/src/project/elements/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Position, Range } from 'vscode-languageserver';
import { TextDocument } from 'vscode-languageserver-textdocument';

// Antlr
import { ParserRuleContext, TerminalNode } from 'antlr4ng';
import { Parser, ParserRuleContext, TerminalNode } from 'antlr4ng';

// Project
import {
Expand All @@ -16,9 +16,9 @@ import {
} from '../../capabilities/capabilities';


export abstract class BaseSyntaxElement<T extends ParserRuleContext> {
export abstract class BaseSyntaxElement {
// Base Properties
context?: Context<T>;
context?: Context<ParserRuleContext | TerminalNode>;
identifierCapability?: IdentifierCapability;

// Capabilities
Expand All @@ -28,21 +28,33 @@ export abstract class BaseSyntaxElement<T extends ParserRuleContext> {
symbolInformationCapability?: SymbolInformationCapability;
scopeItemCapability?: ScopeItemCapability;

constructor();
constructor(ctx: T, doc: TextDocument)
constructor(ctx?: T, doc?: TextDocument) {
if (!!ctx && !!doc) this.context = new Context(ctx, doc);
/**
*
*/
constructor() {
let x: TerminalNode | ParserRuleContext;

}
}


export abstract class BaseRuleSyntaxElement<T extends ParserRuleContext> extends BaseSyntaxElement {
context!: Context<T>;

constructor(ctx: T, doc: TextDocument) {
super();
this.context = new Context(ctx, doc);
}

/**
* Checks if this element is a child of another element.
* @returns True if the element is a child of the passed element.
*/
isChildOf(range: Range): boolean;
isChildOf(element: BaseSyntaxElement<T>): boolean;
isChildOf(elementOrRange: BaseSyntaxElement<T> | Range): boolean {
isChildOf(element: BaseRuleSyntaxElement<T>): boolean;
isChildOf(elementOrRange: BaseRuleSyntaxElement<T> | Range): boolean {
const a = this.context?.range;
const b = ((o: any): o is BaseSyntaxElement<T> => 'context' in o)(elementOrRange)
const b = ((o: any): o is BaseRuleSyntaxElement<T> => 'context' in o)(elementOrRange)
? elementOrRange.context?.range
: elementOrRange;

Expand All @@ -59,7 +71,7 @@ export abstract class BaseSyntaxElement<T extends ParserRuleContext> {
* Compare two syntax elements for equality.
* @returns True if the document, range, and text match.
*/
equals(element: BaseSyntaxElement<T>): boolean {
equals(element: BaseRuleSyntaxElement<T>): boolean {
const a = this.context;
const b = element.context;

Expand All @@ -71,16 +83,7 @@ export abstract class BaseSyntaxElement<T extends ParserRuleContext> {
}


export abstract class BaseContextSyntaxElement<T extends ParserRuleContext> extends BaseSyntaxElement<T> implements HasContext<T> {
context!: Context<T>;

constructor(ctx: T, doc: TextDocument) {
super(ctx, doc);
}
}


export abstract class BaseIdentifyableSyntaxElement<T extends ParserRuleContext> extends BaseContextSyntaxElement<T> implements IsIdentifiable {
export abstract class BaseIdentifyableSyntaxElement<T extends ParserRuleContext> extends BaseRuleSyntaxElement<T> implements IsIdentifiable {
abstract identifierCapability: IdentifierCapability;

constructor(ctx: T, doc: TextDocument) {
Expand Down Expand Up @@ -155,4 +158,4 @@ export interface HasFoldingRangeCapability {
// Compound Types
// ---------------------------------------------------------

export type DeclarableElement = BaseContextSyntaxElement<ParserRuleContext> & IsIdentifiable & HasDiagnosticCapability;
export type DeclarableElement = BaseRuleSyntaxElement<ParserRuleContext> & IsIdentifiable & HasDiagnosticCapability;
8 changes: 4 additions & 4 deletions server/src/project/elements/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { AnyOperatorContext, IfStatementContext, WhileStatementContext } from '.

// Project
import { DiagnosticCapability, FoldingRangeCapability } from '../../capabilities/capabilities';
import { BaseContextSyntaxElement, HasDiagnosticCapability } from './base';
import { BaseRuleSyntaxElement, HasDiagnosticCapability } from './base';
import { MultipleOperatorsDiagnostic, WhileWendDeprecatedDiagnostic } from '../../capabilities/diagnostics';

export class IfElseBlock extends BaseContextSyntaxElement<IfStatementContext> {
export class IfElseBlock extends BaseRuleSyntaxElement<IfStatementContext> {
constructor(context: IfStatementContext, document: TextDocument) {
super(context, document);
this.foldingRangeCapability = new FoldingRangeCapability(this);
Expand All @@ -19,7 +19,7 @@ export class IfElseBlock extends BaseContextSyntaxElement<IfStatementContext> {
}


export class WhileLoopElement extends BaseContextSyntaxElement<WhileStatementContext> implements HasDiagnosticCapability {
export class WhileLoopElement extends BaseRuleSyntaxElement<WhileStatementContext> implements HasDiagnosticCapability {
diagnosticCapability: DiagnosticCapability;

constructor(context: WhileStatementContext, document: TextDocument) {
Expand All @@ -35,7 +35,7 @@ export class WhileLoopElement extends BaseContextSyntaxElement<WhileStatementCon
}


export class DuplicateOperatorElement extends BaseContextSyntaxElement<AnyOperatorContext> implements HasDiagnosticCapability {
export class DuplicateOperatorElement extends BaseRuleSyntaxElement<AnyOperatorContext> implements HasDiagnosticCapability {
diagnosticCapability: DiagnosticCapability;

constructor(context: AnyOperatorContext, document: TextDocument) {
Expand Down
10 changes: 6 additions & 4 deletions server/src/project/elements/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
import { TextDocument } from 'vscode-languageserver-textdocument';

// Antlr
import { ErrorNode, ParserRuleContext } from 'antlr4ng';
import { ErrorNode, ParserRuleContext, TerminalNode } from 'antlr4ng';

// Project
import { BaseContextSyntaxElement, BaseSyntaxElement } from './base';
import { BaseRuleSyntaxElement, BaseSyntaxElement, Context } from './base';
import { DiagnosticCapability } from '../../capabilities/capabilities';
import { ParserErrorDiagnostic } from '../../capabilities/diagnostics';


export class ErrorRuleElement extends BaseContextSyntaxElement<ParserRuleContext> {
export class ErrorRuleElement extends BaseSyntaxElement {
context: Context<TerminalNode>;
constructor(node: ErrorNode, doc: TextDocument) {
super(node.parent as ParserRuleContext, doc);
super();
this.context = new Context(node, doc);
this.diagnosticCapability = new DiagnosticCapability(this);
this.diagnosticCapability.diagnostics.push(
new ParserErrorDiagnostic(this.context.range, node.getText())
Expand Down
4 changes: 2 additions & 2 deletions server/src/project/elements/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '../../antlr/out/vbaParser';

// Project
import { BaseContextSyntaxElement, BaseIdentifyableSyntaxElement, HasDiagnosticCapability } from './base';
import { BaseRuleSyntaxElement, BaseIdentifyableSyntaxElement, HasDiagnosticCapability } from './base';
import { DiagnosticCapability, FoldingRangeCapability, IdentifierCapability, ItemType, ScopeItemCapability, SymbolInformationCapability } from '../../capabilities/capabilities';
import { DuplicateAttributeDiagnostic, IgnoredAttributeDiagnostic, MissingAttributeDiagnostic, MissingOptionExplicitDiagnostic } from '../../capabilities/diagnostics';

Expand Down Expand Up @@ -185,7 +185,7 @@ export class ClassElement extends BaseModuleElement<ClassModuleContext> {
}


export class ModuleIgnoredAttributeElement extends BaseContextSyntaxElement<ParserRuleContext> implements HasDiagnosticCapability {
export class ModuleIgnoredAttributeElement extends BaseRuleSyntaxElement<ParserRuleContext> implements HasDiagnosticCapability {
diagnosticCapability: DiagnosticCapability;

constructor(ctx: IgnoredClassAttrContext | IgnoredProceduralAttrContext, doc: TextDocument) {
Expand Down
6 changes: 3 additions & 3 deletions server/src/project/elements/precompiled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { CompilerConditionalBlockContext, CompilerDefaultBlockContext, CompilerI

// Project
import { DiagnosticCapability, FoldingRangeCapability } from '../../capabilities/capabilities';
import { BaseContextSyntaxElement } from '../elements/base';
import { BaseRuleSyntaxElement } from '../elements/base';
import { UnreachableCodeDiagnostic } from '../../capabilities/diagnostics';


export class CompilerLogicalBlock extends BaseContextSyntaxElement<CompilerIfBlockContext> {
export class CompilerLogicalBlock extends BaseRuleSyntaxElement<CompilerIfBlockContext> {
conditionalBlocks: CompilerConditionBlock[] = [];
inactiveBlocks: CompilerConditionBlock[] = [];

Expand Down Expand Up @@ -38,7 +38,7 @@ export class CompilerLogicalBlock extends BaseContextSyntaxElement<CompilerIfBlo
}


class CompilerConditionBlock extends BaseContextSyntaxElement<CompilerConditionalBlockContext | CompilerDefaultBlockContext> {
class CompilerConditionBlock extends BaseRuleSyntaxElement<CompilerConditionalBlockContext | CompilerDefaultBlockContext> {
readonly documentSettings: { environment: { os: string, version: string } };

constructor(ctx: CompilerConditionalBlockContext | CompilerDefaultBlockContext, doc: TextDocument, env: { environment: { os: string, version: string } }) {
Expand Down
4 changes: 2 additions & 2 deletions server/src/project/elements/procedure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import {
} from '../../antlr/out/vbaParser';

// Project
import { BaseContextSyntaxElement, HasDiagnosticCapability, HasSymbolInformationCapability } from './base';
import { BaseRuleSyntaxElement, HasDiagnosticCapability, HasSymbolInformationCapability } from './base';
import { AssignmentType, DiagnosticCapability, FoldingRangeCapability, IdentifierCapability, ItemType, ScopeItemCapability, SymbolInformationCapability } from '../../capabilities/capabilities';

interface HasProcedureScope {
procedureScope(): ProcedureScopeContext | null
}

abstract class BaseProcedureElement<T extends ParserRuleContext & HasProcedureScope> extends BaseContextSyntaxElement<T> implements HasDiagnosticCapability, HasSymbolInformationCapability {
abstract class BaseProcedureElement<T extends ParserRuleContext & HasProcedureScope> extends BaseRuleSyntaxElement<T> implements HasDiagnosticCapability, HasSymbolInformationCapability {
diagnosticCapability: DiagnosticCapability;
foldingRangeCapability: FoldingRangeCapability;
symbolInformationCapability: SymbolInformationCapability;
Expand Down
Loading