Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completion for pkg path inside strings #340

Merged
merged 8 commits into from
Feb 27, 2021
39 changes: 39 additions & 0 deletions src/files/BrsFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,45 @@ describe('BrsFile', () => {
});

describe('getCompletions', () => {
it('suggests pkg paths in strings that match that criteria', () => {
program.addOrReplaceFile('source/main.brs', `
sub main()
print "pkg:"
end sub
`);
const result = program.getCompletions(`${rootDir}/source/main.brs`, Position.create(2, 31));
const names = result.map(x => x.label);
expect(names.sort()).to.eql([
'pkg:/source/main.brs'
]);
});

it('suggests libpkg paths in strings that match that criteria', () => {
program.addOrReplaceFile('source/main.brs', `
sub main()
print "libpkg:"
end sub
`);
const result = program.getCompletions(`${rootDir}/source/main.brs`, Position.create(2, 31));
const names = result.map(x => x.label);
expect(names.sort()).to.eql([
'libpkg:/source/main.brs'
]);
});

it('suggests pkg paths in template strings', () => {
program.addOrReplaceFile('source/main.brs', `
sub main()
print \`pkg:\`
end sub
`);
const result = program.getCompletions(`${rootDir}/source/main.brs`, Position.create(2, 31));
const names = result.map(x => x.label);
expect(names.sort()).to.eql([
'pkg:/source/main.brs'
]);
});

it('waits for the file to be processed before collecting completions', () => {
//eslint-disable-next-line @typescript-eslint/no-floating-promises
program.addOrReplaceFile('source/main.brs', `
Expand Down
33 changes: 31 additions & 2 deletions src/files/BrsFile.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { CodeWithSourceMap } from 'source-map';
import { SourceNode } from 'source-map';
import type { CompletionItem, Hover, Range, Position, CodeAction } from 'vscode-languageserver';
import { CompletionItemKind, SymbolKind, Location, SignatureInformation, ParameterInformation, DocumentSymbol, SymbolInformation } from 'vscode-languageserver';
import { CompletionItemKind, SymbolKind, Location, SignatureInformation, ParameterInformation, DocumentSymbol, SymbolInformation, TextEdit } from 'vscode-languageserver';
import chalk from 'chalk';
import * as path from 'path';
import type { Scope } from '../Scope';
Expand Down Expand Up @@ -767,8 +767,37 @@ export class BrsFile {

//if cursor is within a comment, disable completions
let currentToken = this.getTokenAt(position);
if (currentToken && currentToken.kind === TokenKind.Comment) {
const tokenKind = currentToken?.kind;
if (tokenKind === TokenKind.Comment) {
return [];
} else if (tokenKind === TokenKind.StringLiteral || tokenKind === TokenKind.TemplateStringQuasi) {
const match = /^("?)(pkg|libpkg):/.exec(currentToken.text);
if (match) {
const [, openingQuote, fileProtocol] = match;
//include every absolute file path from this scope
for (const file of scope.getAllFiles()) {
const pkgPath = `${fileProtocol}:/${file.pkgPath.replace(/\\/g, '/')}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pkgPath is supposed to be normalised already no? Seems like a waste.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until #329 merges, pkgPath uses windows separators on windows, and unix separators everywhere else. So this is absolutely necessary right now.

result.push({
label: pkgPath,
textEdit: TextEdit.replace(
util.createRange(
currentToken.range.start.line,
//+1 to step past the opening quote
currentToken.range.start.character + (openingQuote ? 1 : 0),
currentToken.range.end.line,
//-1 to exclude the closing quotemark (or the end character if there is no closing quotemark)
currentToken.range.end.character + (currentToken.text.endsWith('"') ? -1 : 0)
),
pkgPath
),
kind: CompletionItemKind.File
});
}
return result;
} else {
//do nothing. we don't want to show completions inside of strings...
return [];
}
}

let namespaceCompletions = this.getNamespaceCompletions(currentToken, this.parseMode, scope);
Expand Down