Skip to content

Commit

Permalink
semanticToken request wait until validate finishes
Browse files Browse the repository at this point in the history
  • Loading branch information
TwitchBronBron committed Oct 24, 2022
1 parent 4f29020 commit bcd9e2f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
51 changes: 51 additions & 0 deletions src/LanguageServer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { expectZeroDiagnostics, trim } from './testHelpers.spec';
import { isBrsFile, isLiteralString } from './astUtils/reflection';
import { createVisitor, WalkMode } from './astUtils/visitors';
import { tempDir, rootDir } from './testHelpers.spec';
import { URI } from 'vscode-uri';

const sinon = createSandbox();

Expand Down Expand Up @@ -1103,6 +1104,56 @@ describe('LanguageServer', () => {
});
});
});

it('semantic tokens request waits until after validation has finished', async () => {
fsExtra.outputFileSync(s`${rootDir}/source/main.bs`, `
sub main()
print \`hello world\`
end sub
`);
let spaceCount = 0;
const getContents = () => {
return `
namespace sgnode
sub speak(message)
print message
end sub
sub sayHello()
sgnode.speak("Hello")${' '.repeat(spaceCount++)}
end sub
end namespace
`;
};

const uri = URI.file(s`${rootDir}/source/sgnode.bs`).toString();

fsExtra.outputFileSync(s`${rootDir}/source/sgnode.bs`, getContents());
server.run();
await server['syncProjects']();
expectZeroDiagnostics(server.projects[0].builder.program);

fsExtra.outputFileSync(s`${rootDir}/source/sgnode.bs`, getContents());
const changeWatchedFilesPromise = server['onDidChangeWatchedFiles']({
changes: [{
type: FileChangeType.Changed,
uri: uri
}]
});
const document = {
getText: () => getContents(),
uri: uri
} as TextDocument;

const semanticTokensPromise = server['onFullSemanticTokens']({
textDocument: document
});
await Promise.all([
changeWatchedFilesPromise,
semanticTokensPromise
]);
expectZeroDiagnostics(server.projects[0].builder.program);
});
});

export function getFileProtocolPath(fullPath: string) {
Expand Down
10 changes: 8 additions & 2 deletions src/LanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ export class LanguageServer {
// validate all projects
await this.validateAllThrottled();
} catch (e: any) {
this.sendCriticalFailure(`Critical error parsing / validating ${filePath}: ${e.message}`);
this.sendCriticalFailure(`Critical error parsing/validating ${filePath}: ${e.message}`);
}
}

Expand Down Expand Up @@ -1206,7 +1206,13 @@ export class LanguageServer {
@AddStackToErrorMessage
private async onFullSemanticTokens(params: SemanticTokensParams) {
await this.waitAllProjectFirstRuns();
await this.keyedThrottler.onIdleOnce(util.uriToPath(params.textDocument.uri), true);
await Promise.all([
//wait for the file to settle (in case there are multiple file changes in quick succession
this.keyedThrottler.onIdleOnce(util.uriToPath(params.textDocument.uri), true),
// wait for the validation to finish before providing semantic tokens. program.validate() populates and then caches AstNode.parent properties.
// If we don't wait, then fetching semantic tokens can cause some invalid cache
this.validateThrottler.onIdleOnce(false)
]);

const srcPath = util.uriToPath(params.textDocument.uri);
for (const project of this.projects) {
Expand Down

0 comments on commit bcd9e2f

Please sign in to comment.