Skip to content

Commit 785c281

Browse files
committed
Allow plugins to provide a list of external files.
The list of the plugin's external files and request made to a file in the list will be routed to an instance of the plugin.
1 parent a1a2006 commit 785c281

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/server/project.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ namespace ts.server {
112112
private rootFiles: ScriptInfo[] = [];
113113
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
114114
private program: ts.Program;
115+
private externalFiles: SortedReadonlyArray<string>;
115116

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

270-
getExternalFiles(): string[] {
271-
return [];
271+
getExternalFiles(): SortedReadonlyArray<string> {
272+
return emptyArray as SortedReadonlyArray<string>;
272273
}
273274

274275
getSourceFile(path: Path) {
@@ -567,6 +568,24 @@ namespace ts.server {
567568
}
568569
}
569570
}
571+
572+
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
573+
this.externalFiles = this.getExternalFiles();
574+
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles,
575+
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
576+
// by the LSHost for files in the program when the program is retrieved above but
577+
// the program doesn't contain external files so this must be done explicitly.
578+
inserted => {
579+
const scriptInfo = this.projectService.getOrCreateScriptInfo(inserted, /*openedByClient*/ false);
580+
scriptInfo.attachToProject(this);
581+
},
582+
removed => {
583+
const scriptInfoToDetach = this.projectService.getScriptInfo(removed);
584+
if (scriptInfoToDetach) {
585+
scriptInfoToDetach.detachFromProject(this);
586+
}
587+
});
588+
570589
return hasChanges;
571590
}
572591

@@ -947,7 +966,7 @@ namespace ts.server {
947966
return this.typeAcquisition;
948967
}
949968

950-
getExternalFiles(): string[] {
969+
getExternalFiles(): SortedReadonlyArray<string> {
951970
const items: string[] = [];
952971
for (const plugin of this.plugins) {
953972
if (typeof plugin.getExternalFiles === "function") {
@@ -959,7 +978,7 @@ namespace ts.server {
959978
}
960979
}
961980
}
962-
return items;
981+
return toSortedReadonlyArray(items);
963982
}
964983

965984
watchConfigFile(callback: (project: ConfiguredProject) => void) {

src/server/utilities.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,37 @@ namespace ts.server {
192192
return <any>arr;
193193
}
194194

195+
export function enumerateInsertsAndDeletes<T>(a: SortedReadonlyArray<T>, b: SortedReadonlyArray<T>, inserted: (item: T) => void, deleted: (item: T) => void, compare?: (a: T, b: T) => Comparison) {
196+
compare = compare || ts.compareValues;
197+
let aIndex = 0;
198+
let bIndex = 0;
199+
const aLen = a.length;
200+
const bLen = b.length;
201+
while (aIndex < aLen && bIndex < bLen) {
202+
const aItem = a[aIndex];
203+
const bItem = b[bIndex];
204+
const compareResult = compare(aItem, bItem);
205+
if (compareResult === Comparison.LessThan) {
206+
inserted(aItem);
207+
aIndex++;
208+
}
209+
else if (compareResult === Comparison.GreaterThan) {
210+
deleted(bItem);
211+
bIndex++;
212+
}
213+
else {
214+
aIndex++;
215+
bIndex++;
216+
}
217+
}
218+
while (aIndex < aLen) {
219+
inserted(a[aIndex++]);
220+
}
221+
while (bIndex < bLen) {
222+
deleted(b[bIndex++]);
223+
}
224+
}
225+
195226
export class ThrottledOperations {
196227
private pendingTimeouts: Map<any> = createMap<any>();
197228
constructor(private readonly host: ServerHost) {

0 commit comments

Comments
 (0)