Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
4 changes: 3 additions & 1 deletion src/LanguageServer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ describe('LanguageServer', () => {
});
});

describe('sendDiagnostics', () => {
describe.skip('sendDiagnostics', () => {
it('waits for program to finish loading before sending diagnostics', async () => {
server.onInitialize({
capabilities: {
Expand Down Expand Up @@ -851,6 +851,7 @@ describe('LanguageServer', () => {
end function
end namespace
`, 'bs');
program.validate();

// We run the check twice as the first time is with it not cached and second time is with it cached
for (let i = 0; i < 2; i++) {
Expand Down Expand Up @@ -965,6 +966,7 @@ describe('LanguageServer', () => {
end class
end namespace
`, 'bs');
program.validate();

// We run the check twice as the first time is with it not cached and second time is with it cached
for (let i = 0; i < 2; i++) {
Expand Down
12 changes: 9 additions & 3 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2332,7 +2332,8 @@ describe('Program', () => {
<interface>
<function name="sayHello"/>
</interface>
</component>`);
</component>
`);
program.validate();

let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(3, 36)));
Expand All @@ -2352,6 +2353,7 @@ describe('Program', () => {
end function
end class
`);
program.validate();
let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(2, 34)));
expectZeroDiagnostics(program);
expect(signatureHelp[0].signature.label).to.equal('Person(arg1, arg2)');
Expand All @@ -2370,6 +2372,7 @@ describe('Program', () => {
class Roger extends Person
end class
`);
program.validate();
let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(2, 34)));
expectZeroDiagnostics(program);
expect(signatureHelp[0].signature.label).to.equal('Roger(arg1, arg2)');
Expand All @@ -2386,6 +2389,7 @@ describe('Program', () => {
end function
end class
`);
program.validate();
let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(2, 34)));
expectZeroDiagnostics(program);
expect(signatureHelp[0].index).to.equal(0);
Expand All @@ -2398,15 +2402,16 @@ describe('Program', () => {
it('gets signature help for namespaced constructor with args', () => {
program.setFile('source/main.bs', `
function main()
p = new people.coders.Person(arg1, arg2)
p = new people.coders.Person(1, 2)
end function
namespace people.coders
class Person
function new(arg1, arg2)
end function
end class
end namespace
`);
`);
program.validate();
let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(2, 47)));
expectZeroDiagnostics(program);
expect(signatureHelp[0].signature.label).to.equal('people.coders.Person(arg1, arg2)');
Expand Down Expand Up @@ -2486,6 +2491,7 @@ describe('Program', () => {
function test(arg1, arg2, arg3)
end function
`);
program.validate();
for (let col = 21; col < 27; col++) {
let signatureHelp = (program.getSignatureHelp(`${rootDir}/source/main.bs`, Position.create(2, col)));
expect(signatureHelp, `failed on col ${col}`).to.have.lengthOf(1);
Expand Down
6 changes: 3 additions & 3 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { globalFile } from './globalCallables';
import { parseManifest } from './preprocessor/Manifest';
import { URI } from 'vscode-uri';
import PluginInterface from './PluginInterface';
import { isBrsFile, isXmlFile, isMethodStatement, isXmlScope } from './astUtils/reflection';
import type { FunctionStatement } from './parser/Statement';
import { isBrsFile, isXmlFile, isMethodStatement, isXmlScope, isNamespaceStatement } from './astUtils/reflection';
import type { FunctionStatement, NamespaceStatement } from './parser/Statement';
import { ParseMode } from './parser/Parser';
import { TokenKind } from './lexer/TokenKind';
import { BscPlugin } from './bscPlugin/BscPlugin';
Expand Down Expand Up @@ -825,7 +825,7 @@ export class Program {
filesSearched.add(file);

for (const statement of [...file.parser.references.functionStatements, ...file.parser.references.classStatements.flatMap((cs) => cs.methods)]) {
let parentNamespaceName = statement.namespaceName?.getName(originFile.parseMode)?.toLowerCase();
let parentNamespaceName = statement.findAncestor<NamespaceStatement>(isNamespaceStatement)?.getName(originFile.parseMode)?.toLowerCase();
if (statement.name.text.toLowerCase() === lowerName && (!parentNamespaceName || parentNamespaceName === lowerNamespaceName)) {
if (!results.has(statement)) {
results.set(statement, { item: statement, file: file });
Expand Down
9 changes: 5 additions & 4 deletions src/Scope.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ describe('Scope', () => {
program.validate();
const scope = program.getScopesForFile('source/alpha.bs')[0];
scope.linkSymbolTable();
const symbolTable = file.parser.references.namespaceStatements[1].symbolTable;
//the symbol table should contain the relative names for all items in this namespace across files
const symbolTable = file.parser.references.namespaceStatements[1].getSymbolTable();
//the symbol table should contain the relative names for all items in this namespace across the entire scope
expect(
symbolTable.hasSymbol('Beta')
).to.be.true;
Expand Down Expand Up @@ -277,7 +277,7 @@ describe('Scope', () => {
]);
});

it('accepts namespace names in their transpiled form on .brs files', () => {
it('accepts namespace names in their transpiled form in .brs files', () => {
program.setFile('source/ns.bs', `
namespace MyNamespace
sub foo()
Expand Down Expand Up @@ -1386,6 +1386,7 @@ describe('Scope', () => {
end namespace
`);
delete ((file.ast.statements[0] as NamespaceStatement).body.statements[0] as FunctionStatement).name;
program.validate();
program['scopes']['source'].buildNamespaceLookup();
});
});
Expand Down Expand Up @@ -1418,7 +1419,7 @@ describe('Scope', () => {
bar3_2
end enum
`);
// program.validate();
program.validate();

expect(
[...sourceScope.getEnumMap().keys()]
Expand Down
12 changes: 6 additions & 6 deletions src/Scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { URI } from 'vscode-uri';
import { LogLevel } from './Logger';
import type { BrsFile } from './files/BrsFile';
import type { DependencyGraph, DependencyChangedEvent } from './DependencyGraph';
import { isBrsFile, isClassMethodStatement, isClassStatement, isConstStatement, isCustomType, isEnumStatement, isFunctionStatement, isFunctionType, isXmlFile } from './astUtils/reflection';
import { isBrsFile, isClassMethodStatement, isClassStatement, isConstStatement, isCustomType, isEnumStatement, isFunctionStatement, isFunctionType, isNamespaceStatement, isXmlFile } from './astUtils/reflection';
import { SymbolTable } from './SymbolTable';
import type { Statement } from './parser/AstNode';

Expand Down Expand Up @@ -559,7 +559,7 @@ export class Scope {
}
// Merges all the symbol tables of the namespace statements into the new symbol table created above.
// Set those symbol tables to have this new merged table as a parent
ns.symbolTable.mergeSymbolTable(namespaceStatement.symbolTable);
ns.symbolTable.mergeSymbolTable(namespaceStatement.getSymbolTable());
}

//associate child namespaces with their parents
Expand Down Expand Up @@ -711,7 +711,7 @@ export class Scope {
for (const namespace of file.parser.references.namespaceStatements) {
const namespaceNameLower = namespace.nameExpression.getName(ParseMode.BrighterScript).toLowerCase();
const namespaceSymbolTable = this.namespaceLookup.get(namespaceNameLower).symbolTable;
namespace.symbolTable.pushParent(namespaceSymbolTable);
namespace.getSymbolTable().pushParent(namespaceSymbolTable);
}
}
}
Expand All @@ -723,7 +723,7 @@ export class Scope {
file.parser?.symbolTable.popParent();

for (const namespace of file.parser.references.namespaceStatements) {
namespace.symbolTable.popParent();
namespace.getSymbolTable().popParent();
}
}
}
Expand Down Expand Up @@ -812,7 +812,7 @@ export class Scope {
if (isCustomType(func.returnType) && func.returnTypeToken) {
// check if this custom type is in our class map
const returnTypeName = func.returnType.name;
const currentNamespaceName = func.namespaceName?.getName(ParseMode.BrighterScript);
const currentNamespaceName = func.findAncestor<NamespaceStatement>(isNamespaceStatement)?.getName(ParseMode.BrighterScript);
if (!this.hasClass(returnTypeName, currentNamespaceName) && !this.hasInterface(returnTypeName) && !this.hasEnum(returnTypeName)) {
this.diagnostics.push({
...DiagnosticMessages.invalidFunctionReturnType(returnTypeName),
Expand All @@ -825,7 +825,7 @@ export class Scope {
for (let param of func.parameters) {
if (isCustomType(param.type) && param.typeToken) {
const paramTypeName = param.type.name;
const currentNamespaceName = func.namespaceName?.getName(ParseMode.BrighterScript);
const currentNamespaceName = func.findAncestor<NamespaceStatement>(isNamespaceStatement)?.getName(ParseMode.BrighterScript);
if (!this.hasClass(paramTypeName, currentNamespaceName) && !this.hasInterface(paramTypeName) && !this.hasEnum(paramTypeName)) {
this.diagnostics.push({
...DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName),
Expand Down
6 changes: 4 additions & 2 deletions src/SymbolTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ export class SymbolTable {
private parentStack: SymbolTable[] = [];

public pushParent(parent?: SymbolTable) {
this.parentStack.unshift(parent);
return parent;
if (parent) {
this.parentStack.unshift(parent);
}
return this.parentStack[this.parentStack.length - 1];
}

/**
Expand Down
14 changes: 6 additions & 8 deletions src/astUtils/creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Range } from 'vscode-languageserver';
import type { Identifier, Token } from '../lexer/Token';
import { TokenKind } from '../lexer/TokenKind';
import type { Expression } from '../parser/AstNode';
import type { NamespacedVariableNameExpression } from '../parser/Expression';
import { LiteralExpression, CallExpression, DottedGetExpression, VariableExpression, FunctionExpression } from '../parser/Expression';
import type { SGAttribute } from '../parser/SGTypes';
import { Block, MethodStatement } from '../parser/Statement';
Expand Down Expand Up @@ -104,13 +103,13 @@ export function createIdentifier(name: string, range?: Range): Identifier {
};
}

export function createVariableExpression(ident: string, range?: Range, namespaceName?: NamespacedVariableNameExpression): VariableExpression {
return new VariableExpression(createToken(TokenKind.Identifier, ident, range), namespaceName);
export function createVariableExpression(ident: string, range?: Range): VariableExpression {
return new VariableExpression(createToken(TokenKind.Identifier, ident, range));
}

export function createDottedIdentifier(path: string[], range?: Range, namespaceName?: NamespacedVariableNameExpression): DottedGetExpression {
export function createDottedIdentifier(path: string[], range?: Range): DottedGetExpression {
const ident = path.pop();
const obj = path.length > 1 ? createDottedIdentifier(path, range, namespaceName) : createVariableExpression(path[0], range, namespaceName);
const obj = path.length > 1 ? createDottedIdentifier(path, range) : createVariableExpression(path[0], range);
return new DottedGetExpression(obj, createToken(TokenKind.Identifier, ident, range), createToken(TokenKind.Dot, '.', range));
}

Expand Down Expand Up @@ -165,13 +164,12 @@ export function createClassMethodStatement(name: string, kind: TokenKind.Sub | T
return createMethodStatement(name, kind, [accessModifier]);
}

export function createCall(callee: Expression, args?: Expression[], namespaceName?: NamespacedVariableNameExpression) {
export function createCall(callee: Expression, args?: Expression[]) {
return new CallExpression(
callee,
createToken(TokenKind.LeftParen, '('),
createToken(TokenKind.RightParen, ')'),
args || [],
namespaceName
args || []
);
}

Expand Down
6 changes: 3 additions & 3 deletions src/astUtils/reflection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('reflection', () => {
const comment = new CommentStatement([token]);
const exitFor = new ExitForStatement({ exitFor: token });
const exitWhile = new ExitWhileStatement({ exitWhile: token });
const funs = new FunctionStatement(ident, new FunctionExpression([], block, token, token, token, token), undefined);
const funs = new FunctionStatement(ident, new FunctionExpression([], block, token, token, token, token));
const ifs = new IfStatement({ if: token }, expr, block);
const increment = new IncrementStatement(expr, token);
const print = new PrintStatement({ print: token }, []);
Expand Down Expand Up @@ -192,7 +192,7 @@ describe('reflection', () => {
};
const nsVar = new NamespacedVariableNameExpression(createVariableExpression('a', range));
const binary = new BinaryExpression(expr, token, expr);
const call = new CallExpression(expr, token, token, [], undefined);
const call = new CallExpression(expr, token, token, []);
const fun = new FunctionExpression([], block, token, token, token, token);
const dottedGet = new DottedGetExpression(expr, ident, token);
const xmlAttrGet = new XmlAttributeGetExpression(expr, ident, token);
Expand All @@ -203,7 +203,7 @@ describe('reflection', () => {
const arrayLit = new ArrayLiteralExpression([], token, token);
const aaLit = new AALiteralExpression([], token, token);
const unary = new UnaryExpression(token, expr);
const variable = new VariableExpression(ident, undefined);
const variable = new VariableExpression(ident);
const sourceLit = new SourceLiteralExpression(token);
const newx = new NewExpression(token, call);
const callfunc = new CallfuncExpression(expr, token, ident, token, [], token);
Expand Down
6 changes: 6 additions & 0 deletions src/bscPlugin/hover/HoverProcessor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ describe('HoverProcessor', () => {

end sub
`);
program.validate();

let hover = program.getHover(mainFile.pathAbsolute, util.createPosition(2, 25))[0];
expect(hover?.range).to.eql(util.createRange(2, 20, 2, 29));
Expand All @@ -148,6 +149,7 @@ describe('HoverProcessor', () => {
end sub
const SOME_VALUE = true
`);
program.validate();
// print SOM|E_VALUE
let hover = program.getHover('source/main.bs', util.createPosition(2, 29))[0];
expect(hover?.range).to.eql(util.createRange(2, 26, 2, 36));
Expand All @@ -162,6 +164,7 @@ describe('HoverProcessor', () => {
end sub
const SOME_VALUE = "value"
`);
program.validate();
// value += SOME|_VALUE
let hover = program.getHover('source/main.bs', util.createPosition(3, 33))[0];
expect(hover?.range).to.eql(util.createRange(3, 29, 3, 39));
Expand All @@ -178,6 +181,7 @@ describe('HoverProcessor', () => {
const SOME_VALUE = "value"
end namespace
`);
program.validate();
// value += SOME|_VALUE
let hover = program.getHover('source/main.bs', util.createPosition(3, 47))[0];
expect(hover?.range).to.eql(util.createRange(3, 43, 3, 53));
Expand All @@ -193,6 +197,7 @@ describe('HoverProcessor', () => {
const SOME_VALUE = true
end namespace
`);
program.validate();
// print name.SOM|E_VALUE
let hover = program.getHover('source/main.bs', util.createPosition(2, 34))[0];
expect(hover?.range).to.eql(util.createRange(2, 31, 2, 41));
Expand All @@ -208,6 +213,7 @@ describe('HoverProcessor', () => {
const SOME_VALUE = true
end namespace
`);
program.validate();
// print name.sp.a.c.e.SOM|E_VALUE
let hover = program.getHover('source/main.bs', util.createPosition(2, 43))[0];
expect(hover?.range).to.eql(util.createRange(2, 40, 2, 50));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Range } from 'vscode-languageserver-protocol';
import { SemanticTokenModifiers } from 'vscode-languageserver-protocol';
import { SemanticTokenTypes } from 'vscode-languageserver-protocol';
import { isCallExpression, isCustomType, isNewExpression } from '../../astUtils/reflection';
import { isCallExpression, isCustomType, isNamespaceStatement, isNewExpression } from '../../astUtils/reflection';
import type { BrsFile } from '../../files/BrsFile';
import type { OnGetSemanticTokensEvent } from '../../interfaces';
import type { Locatable } from '../../lexer/Token';
import { ParseMode } from '../../parser/Parser';
import type { NamespaceStatement } from '../../parser/Statement';
import util from '../../util';

export class BrsFileSemanticTokensProcessor {
Expand Down Expand Up @@ -35,9 +36,10 @@ export class BrsFileSemanticTokensProcessor {
for (const func of this.event.file.parser.references.functionExpressions) {
for (const parm of func.parameters) {
if (isCustomType(parm.type)) {
const namespace = parm.findAncestor<NamespaceStatement>(isNamespaceStatement);
classes.push({
className: parm.typeToken.text,
namespaceName: parm.namespaceName?.getName(ParseMode.BrighterScript),
namespaceName: namespace?.getName(ParseMode.BrighterScript),
range: parm.typeToken.range
});
}
Expand Down
Loading