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

Allow plugins to provide a list of external files. #15308

Merged
merged 1 commit into from
Jun 5, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 23 additions & 4 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ namespace ts.server {
private rootFiles: ScriptInfo[] = [];
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
private program: ts.Program;
private externalFiles: SortedReadonlyArray<string>;

private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap();
private lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
Expand Down Expand Up @@ -267,8 +268,8 @@ namespace ts.server {
abstract getProjectRootPath(): string | undefined;
abstract getTypeAcquisition(): TypeAcquisition;

getExternalFiles(): string[] {
return [];
getExternalFiles(): SortedReadonlyArray<string> {
return emptyArray as SortedReadonlyArray<string>;
}

getSourceFile(path: Path) {
Expand Down Expand Up @@ -567,6 +568,24 @@ namespace ts.server {
}
}
}

const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
this.externalFiles = this.getExternalFiles();
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles,
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
// by the LSHost for files in the program when the program is retrieved above but
// the program doesn't contain external files so this must be done explicitly.
inserted => {
const scriptInfo = this.projectService.getOrCreateScriptInfo(inserted, /*openedByClient*/ false);
scriptInfo.attachToProject(this);
},
removed => {
const scriptInfoToDetach = this.projectService.getScriptInfo(removed);
if (scriptInfoToDetach) {
scriptInfoToDetach.detachFromProject(this);
}
});

return hasChanges;
}

Expand Down Expand Up @@ -947,7 +966,7 @@ namespace ts.server {
return this.typeAcquisition;
}

getExternalFiles(): string[] {
getExternalFiles(): SortedReadonlyArray<string> {
const items: string[] = [];
for (const plugin of this.plugins) {
if (typeof plugin.getExternalFiles === "function") {
Expand All @@ -959,7 +978,7 @@ namespace ts.server {
}
}
}
return items;
return toSortedReadonlyArray(items);
}

watchConfigFile(callback: (project: ConfiguredProject) => void) {
Expand Down
31 changes: 31 additions & 0 deletions src/server/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,37 @@ namespace ts.server {
return <any>arr;
}

export function enumerateInsertsAndDeletes<T>(a: SortedReadonlyArray<T>, b: SortedReadonlyArray<T>, inserted: (item: T) => void, deleted: (item: T) => void, compare?: (a: T, b: T) => Comparison) {
compare = compare || ts.compareValues;
let aIndex = 0;
let bIndex = 0;
const aLen = a.length;
const bLen = b.length;
while (aIndex < aLen && bIndex < bLen) {
const aItem = a[aIndex];
const bItem = b[bIndex];
const compareResult = compare(aItem, bItem);
if (compareResult === Comparison.LessThan) {
inserted(aItem);
aIndex++;
}
else if (compareResult === Comparison.GreaterThan) {
deleted(bItem);
bIndex++;
}
else {
aIndex++;
bIndex++;
}
}
while (aIndex < aLen) {
inserted(a[aIndex++]);
}
while (bIndex < bLen) {
deleted(b[bIndex++]);
}
}

export class ThrottledOperations {
private pendingTimeouts: Map<any> = createMap<any>();
constructor(private readonly host: ServerHost) {
Expand Down