From 0b445ad21d4fd543f8ace69f74a3f3e4b29684ce Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Wed, 24 Apr 2024 16:30:58 -0300 Subject: [PATCH 1/3] Fixes CompletionItemKinds for typed variables --- .../completions/CompletionsProcessor.spec.ts | 80 +++++++++++++++++++ .../completions/CompletionsProcessor.ts | 23 ++++-- src/parser/Statement.ts | 2 +- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/src/bscPlugin/completions/CompletionsProcessor.spec.ts b/src/bscPlugin/completions/CompletionsProcessor.spec.ts index 975629e6a..36f2548e5 100644 --- a/src/bscPlugin/completions/CompletionsProcessor.spec.ts +++ b/src/bscPlugin/completions/CompletionsProcessor.spec.ts @@ -1898,6 +1898,86 @@ describe('CompletionsProcessor', () => { }); + describe('typed variables', () => { + it('shows variables of type interface as CompletionItemKind.Variable', () => { + program.setFile('source/main.bs', ` + sub foo(thing as SomeInterface) + print thi| + end sub + + interface SomeInterface + optional name as string + optional data + optional function doStuff() + end interface + `); + program.validate(); + // print thi| + const completions = program.getCompletions('source/main.bs', util.createPosition(2, 33)); + expectCompletionsIncludes(completions, [{ + label: 'thing', + kind: CompletionItemKind.Variable + }]); + }); + + it('shows variables of type class as CompletionItemKind.Variable', () => { + program.setFile('source/main.bs', ` + sub foo(thing as SomeKlass) + print thi| + end sub + + class SomeKlass + name as string + data + function doStuff() + end function + end class + `); + program.validate(); + // print thi| + const completions = program.getCompletions('source/main.bs', util.createPosition(2, 33)); + expectCompletionsIncludes(completions, [{ + label: 'thing', + kind: CompletionItemKind.Variable + }]); + }); + + it('shows variables of type enum as CompletionItemKind.Variable', () => { + program.setFile('source/main.bs', ` + sub foo(thing as SomeEnum) + print thi| + end sub + + enum SomeEnum + up + down + end end + `); + program.validate(); + // print thi| + const completions = program.getCompletions('source/main.bs', util.createPosition(2, 33)); + expectCompletionsIncludes(completions, [{ + label: 'thing', + kind: CompletionItemKind.Variable + }]); + }); + + it('shows variables of type function as CompletionItemKind.Variable', () => { + program.setFile('source/main.bs', ` + sub foo(thing as function) + print thi| + end sub + `); + program.validate(); + // print thi| + const completions = program.getCompletions('source/main.bs', util.createPosition(2, 33)); + expectCompletionsIncludes(completions, [{ + label: 'thing', + kind: CompletionItemKind.Variable + }]); + }); + + }); describe('brighterscript vs brightscript', () => { it('should not include transpiled versions of symbols in brighterscript code', () => { diff --git a/src/bscPlugin/completions/CompletionsProcessor.ts b/src/bscPlugin/completions/CompletionsProcessor.ts index f444d0d0a..255dd33c1 100644 --- a/src/bscPlugin/completions/CompletionsProcessor.ts +++ b/src/bscPlugin/completions/CompletionsProcessor.ts @@ -1,4 +1,4 @@ -import { isBlock, isBrsFile, isCallableType, isClassStatement, isClassType, isComponentType, isConstStatement, isEnumMemberType, isEnumType, isFunctionExpression, isInterfaceType, isMethodStatement, isNamespaceStatement, isNamespaceType, isNativeType, isXmlFile, isXmlScope } from '../../astUtils/reflection'; +import { isBlock, isBrsFile, isCallableType, isClassStatement, isClassType, isComponentType, isConstStatement, isEnumMemberType, isEnumType, isFunctionExpression, isInterfaceType, isMethodStatement, isNamespaceStatement, isNamespaceType, isNativeType, isTypedFunctionType, isXmlFile, isXmlScope } from '../../astUtils/reflection'; import type { FileReference, ProvideCompletionsEvent } from '../../interfaces'; import type { BscFile } from '../../files/BscFile'; import { AllowedTriviaTokens, DeclarableTypes, Keywords, TokenKind } from '../../lexer/TokenKind'; @@ -371,21 +371,32 @@ export class CompletionsProcessor { private getCompletionKindFromSymbol(symbol: BscSymbol, areMembers = false) { const type = symbol?.type; const extraData = symbol?.data; + // eslint-disable-next-line no-bitwise + const finalTypeNameLower = type?.toString().split('.').pop().toLowerCase(); + const symbolNameLower = symbol?.name.toLowerCase(); + let nameMatchesType = symbolNameLower === finalTypeNameLower; if (isConstStatement(extraData?.definingNode)) { return CompletionItemKind.Constant; - } else if (isClassType(type)) { + } else if (isClassType(type) && nameMatchesType) { return CompletionItemKind.Class; } else if (isCallableType(type)) { - return areMembers ? CompletionItemKind.Method : CompletionItemKind.Function; - } else if (isInterfaceType(type)) { + if (isTypedFunctionType(type) && !nameMatchesType) { + if (symbolNameLower === type.name.replaceAll('.', '_').toLowerCase()) { + nameMatchesType = true; + } + } + if (nameMatchesType) { + return areMembers ? CompletionItemKind.Method : CompletionItemKind.Function; + } + } else if (isInterfaceType(type) && nameMatchesType) { return CompletionItemKind.Interface; - } else if (isEnumType(type)) { + } else if (isEnumType(type) && nameMatchesType) { return CompletionItemKind.Enum; } else if (isEnumMemberType(type)) { return CompletionItemKind.EnumMember; } else if (isNamespaceType(type)) { return CompletionItemKind.Module; - } else if (isComponentType(type)) { + } else if (isComponentType(type) && (nameMatchesType || symbolNameLower === 'rosgnode')) { return CompletionItemKind.Interface; } if (areMembers) { diff --git a/src/parser/Statement.ts b/src/parser/Statement.ts index 58e4194a7..b44a4e854 100644 --- a/src/parser/Statement.ts +++ b/src/parser/Statement.ts @@ -434,7 +434,7 @@ export class FunctionStatement extends Statement implements TypedefProvider { getType(options: GetTypeOptions) { const funcExprType = this.func.getType(options); - funcExprType.setName(this.tokens.name?.text); + funcExprType.setName(this.getName(ParseMode.BrighterScript)); return funcExprType; } } From eab85390196514546eee8ffab32be38175cdff45 Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Wed, 24 Apr 2024 16:36:59 -0300 Subject: [PATCH 2/3] removed comment --- src/bscPlugin/completions/CompletionsProcessor.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bscPlugin/completions/CompletionsProcessor.ts b/src/bscPlugin/completions/CompletionsProcessor.ts index 255dd33c1..e5619940f 100644 --- a/src/bscPlugin/completions/CompletionsProcessor.ts +++ b/src/bscPlugin/completions/CompletionsProcessor.ts @@ -371,7 +371,6 @@ export class CompletionsProcessor { private getCompletionKindFromSymbol(symbol: BscSymbol, areMembers = false) { const type = symbol?.type; const extraData = symbol?.data; - // eslint-disable-next-line no-bitwise const finalTypeNameLower = type?.toString().split('.').pop().toLowerCase(); const symbolNameLower = symbol?.name.toLowerCase(); let nameMatchesType = symbolNameLower === finalTypeNameLower; From dcc503b063aa6848dafdb73a3da3024f5a04a074 Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Wed, 24 Apr 2024 16:43:53 -0300 Subject: [PATCH 3/3] No replaceAll() on github test runner --- src/bscPlugin/completions/CompletionsProcessor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bscPlugin/completions/CompletionsProcessor.ts b/src/bscPlugin/completions/CompletionsProcessor.ts index e5619940f..d030158e1 100644 --- a/src/bscPlugin/completions/CompletionsProcessor.ts +++ b/src/bscPlugin/completions/CompletionsProcessor.ts @@ -380,7 +380,7 @@ export class CompletionsProcessor { return CompletionItemKind.Class; } else if (isCallableType(type)) { if (isTypedFunctionType(type) && !nameMatchesType) { - if (symbolNameLower === type.name.replaceAll('.', '_').toLowerCase()) { + if (symbolNameLower === type.name.replace(/\./gi, '_').toLowerCase()) { nameMatchesType = true; } }