Skip to content

Commit

Permalink
rebuildPathFilterer now retains project-specific patterns on rebuild (#…
Browse files Browse the repository at this point in the history
…1327)

* rebuildPathFilterer now retains project-specific patterns on rebuild

* Add test to verify removed project includeLists get unregistered
  • Loading branch information
TwitchBronBron authored Oct 15, 2024
1 parent 1519a87 commit e789422
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 17 deletions.
64 changes: 64 additions & 0 deletions src/LanguageServer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,70 @@ describe('LanguageServer', () => {
s`${workspaceConfigs[1].workspaceFolder}/src/source/file.brs`
]);
});

it('does not erase project-specific filters', async () => {
let filterer = await server['rebuildPathFilterer']();
const files = [
s`${rootDir}/node_modules/one/file.xml`,
s`${rootDir}/node_modules/two.bs`,
s`${rootDir}/node_modules/three/dist/lib.bs`
];

//all node_modules files are filtered out by default, unless included in an includeList
expect(filterer.filter(files)).to.eql([]);

//register two specific node_module folders to include
filterer.registerIncludeList(rootDir, ['node_modules/one/**/*', 'node_modules/two.bs']);

//unless included in an includeList
expect(filterer.filter(files)).to.eql([
s`${rootDir}/node_modules/one/file.xml`,
s`${rootDir}/node_modules/two.bs`
//three should still be excluded
]);

//rebuild the path filterer, make sure the project's includeList is still retained
filterer = await server['rebuildPathFilterer']();

expect(filterer.filter(files)).to.eql([
//one and two should still make it through the filter unscathed
s`${rootDir}/node_modules/one/file.xml`,
s`${rootDir}/node_modules/two.bs`
//three should still be excluded
]);
});

it('a removed project includeList gets unregistered', async () => {
let filterer = await server['rebuildPathFilterer']();
const files = [
s`${rootDir}/project1/node_modules/one/file.xml`,
s`${rootDir}/project1/node_modules/two.bs`,
s`${rootDir}/project1/node_modules/three/dist/lib.bs`
];

//all node_modules files are filtered out by default, unless included in an includeList
expect(filterer.filter(files)).to.eql([]);

//register a new project that references a file from node_modules
fsExtra.outputFileSync(s`${rootDir}/project1/bsconfig.json`, JSON.stringify({
files: ['node_modules/one/file.xml']
}));

await server['syncProjects']();

//one should be included because the project references it
expect(filterer.filter(files)).to.eql([
s`${rootDir}/project1/node_modules/one/file.xml`
]);

//delete the project's bsconfig.json and sync again (thus destroying the project)
fsExtra.removeSync(s`${rootDir}/project1/bsconfig.json`);

await server['syncProjects']();

//the project's pathFilterer pattern has been unregistered
expect(filterer.filter(files)).to.eql([]);
});
});

describe('onDidChangeWatchedFiles', () => {
Expand Down
46 changes: 29 additions & 17 deletions src/LanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,41 +588,53 @@ export class LanguageServer {
}
private busyStatusIndex = -1;

private pathFiltererDisposables: Array<() => void> = [];

/**
* Populate the path filterer with the client's include/exclude lists and the projects include lists
* @returns the instance of the path filterer
*/
private async rebuildPathFilterer() {
this.pathFilterer.clear();
//dispose of any previous pathFilterer disposables
this.pathFiltererDisposables?.forEach(dispose => dispose());
//keep track of all the pathFilterer disposables so we can dispose them later
this.pathFiltererDisposables = [];

const workspaceConfigs = await this.getWorkspaceConfigs();
await Promise.all(workspaceConfigs.map(async (workspaceConfig) => {
const rootDir = util.uriToPath(workspaceConfig.workspaceFolder);

//always exclude everything from these common folders
this.pathFilterer.registerExcludeList(rootDir, [
'**/node_modules/**/*',
'**/.git/**/*',
'out/**/*',
'**/.roku-deploy-staging/**/*'
]);
this.pathFiltererDisposables.push(
this.pathFilterer.registerExcludeList(rootDir, [
'**/node_modules/**/*',
'**/.git/**/*',
'out/**/*',
'**/.roku-deploy-staging/**/*'
])
);
//get any `files.exclude` patterns from the client from this workspace
this.pathFilterer.registerExcludeList(rootDir, workspaceConfig.excludePatterns);
this.pathFiltererDisposables.push(
this.pathFilterer.registerExcludeList(rootDir, workspaceConfig.excludePatterns)
);

//get any .gitignore patterns from the client from this workspace
const gitignorePath = path.resolve(rootDir, '.gitignore');
if (await fsExtra.pathExists(gitignorePath)) {
const matcher = ignore({ ignoreCase: true }).add(
fsExtra.readFileSync(gitignorePath).toString()
);
this.pathFilterer.registerExcludeMatcher((p: string) => {
const relPath = path.relative(rootDir, p);
if (ignore.isPathValid(relPath)) {
return matcher.test(relPath).ignored;
} else {
//we do not have a valid relative path, so we cannot determine if it is ignored...thus it is NOT ignored
return false;
}
});
this.pathFiltererDisposables.push(
this.pathFilterer.registerExcludeMatcher((p: string) => {
const relPath = path.relative(rootDir, p);
if (ignore.isPathValid(relPath)) {
return matcher.test(relPath).ignored;
} else {
//we do not have a valid relative path, so we cannot determine if it is ignored...thus it is NOT ignored
return false;
}
})
);
}
}));
this.logger.log('pathFilterer successfully reconstructed');
Expand Down

0 comments on commit e789422

Please sign in to comment.