Skip to content

Commit 3ce74ee

Browse files
committed
pass in an optional fallback servicesHost from tests
1 parent 04386cc commit 3ce74ee

File tree

4 files changed

+85
-68
lines changed

4 files changed

+85
-68
lines changed

packages/mongodb-ts-autocomplete/src/autocompleter.spec.ts

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as ts from 'typescript';
12
import { MongoDBAutocompleter } from './index';
23
import type { AutocompletionContext } from './autocompletion-context';
34
import { analyzeDocuments } from 'mongodb-schema';
@@ -14,17 +15,67 @@ const connectionId = 'connection-1';
1415
const databaseName = "my-'\ndatabaseName";
1516
const collectionName = "my-'\ncollectionName";
1617

18+
type EncounteredPaths = {
19+
getScriptSnapshot: string[];
20+
fileExists: string[];
21+
readFile: string[];
22+
};
23+
1724
describe('MongoDBAutocompleter', function () {
25+
let fallbackServiceHost: ts.LanguageServiceHost;
1826
let autocompleterContext: AutocompletionContext;
1927
let autocompleter: MongoDBAutocompleter;
20-
21-
before(function () {
22-
// make sure that we fall back to the default ts.sys file methods so that
23-
// encounteredPaths will be filled
24-
process.env.CI = 'true';
25-
});
28+
let encounteredPaths: EncounteredPaths;
2629

2730
beforeEach(function () {
31+
encounteredPaths = {
32+
getScriptSnapshot: [],
33+
fileExists: [],
34+
readFile: [],
35+
};
36+
37+
fallbackServiceHost = {
38+
// most of these are required by the type, but we won't be using them
39+
getDefaultLibFileName: (options) => {
40+
return ts.getDefaultLibFilePath(options);
41+
},
42+
getScriptFileNames: () => [],
43+
getScriptVersion: () => '1',
44+
getCurrentDirectory: () => process.cwd(),
45+
getCompilationSettings: () => ({}),
46+
47+
// these we'll call as fallbacks
48+
getScriptSnapshot: (fileName) => {
49+
const result = ts.ScriptSnapshot.fromString(
50+
// NOTE: some files do not exist. A good example is "typescript/lib/es2023.ts"
51+
ts.sys.readFile(fileName) || '',
52+
);
53+
54+
encounteredPaths.getScriptSnapshot.push(fileName);
55+
return result;
56+
},
57+
fileExists: (fileName: string) => {
58+
const result = ts.sys.fileExists(fileName);
59+
if (result) {
60+
encounteredPaths.fileExists.push(fileName);
61+
}
62+
return result;
63+
},
64+
readFile: (fileName: string) => {
65+
const result = ts.sys.readFile(fileName);
66+
encounteredPaths.readFile.push(fileName);
67+
return result;
68+
},
69+
readDirectory: (...args) => {
70+
return ts.sys.readDirectory(...args);
71+
},
72+
directoryExists: (...args) => {
73+
return ts.sys.directoryExists(...args);
74+
},
75+
getDirectories: (...args) => {
76+
return ts.sys.getDirectories(...args);
77+
},
78+
};
2879
autocompleterContext = {
2980
currentDatabaseAndConnection: () => ({
3081
connectionId,
@@ -75,12 +126,12 @@ describe('MongoDBAutocompleter', function () {
75126

76127
autocompleter = new MongoDBAutocompleter({
77128
context: autocompleterContext,
129+
fallbackServiceHost,
78130
});
79131
});
80132

81133
afterEach(function () {
82134
// this is what tells us what we're missing in extract-types.ts
83-
const encounteredPaths = autocompleter.listEncounteredPaths();
84135
expect(encounteredPaths).to.deep.equal({
85136
fileExists: [],
86137
getScriptSnapshot: [],

packages/mongodb-ts-autocomplete/src/autocompleter.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import createDebug from 'debug';
22
import _ from 'lodash';
3+
import type { LanguageServiceHost } from 'typescript';
34
import Autocompleter from '@mongodb-js/ts-autocomplete';
45
import type { AutoCompletion } from '@mongodb-js/ts-autocomplete';
56
import autocompleteTypes from './fixtures/autocomplete-types';
@@ -21,6 +22,7 @@ const debug = createDebug('mongodb-ts-autocomplete');
2122

2223
type MongoDBAutocompleterOptions = {
2324
context: AutocompletionContext;
25+
fallbackServiceHost?: LanguageServiceHost;
2426
};
2527

2628
class DatabaseSchema {
@@ -175,9 +177,12 @@ export class MongoDBAutocompleter {
175177
| undefined;
176178
private previousCollectionName: string | undefined;
177179

178-
constructor({ context }: MongoDBAutocompleterOptions) {
180+
constructor({ context, fallbackServiceHost }: MongoDBAutocompleterOptions) {
179181
this.context = CachingAutocompletionContext.caching(context);
180-
this.autocompleter = new Autocompleter({ filter: filterStartingWith });
182+
this.autocompleter = new Autocompleter({
183+
filter: filterStartingWith,
184+
fallbackServiceHost,
185+
});
181186

182187
this.connectionSchemas = Object.create(null);
183188

@@ -333,10 +338,6 @@ declare global {
333338

334339
return this.autocompleter.autocomplete(code);
335340
}
336-
337-
listEncounteredPaths() {
338-
return this.autocompleter.listEncounteredPaths();
339-
}
340341
}
341342

342343
function adjustShellApiForConnection(ShellApiText: string): string {

packages/ts-autocomplete/src/index.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ describe('Autocompleter', function () {
2121
let CODE_TS: string;
2222

2323
before(async function () {
24-
// make sure that we fall back to the default ts.sys file methods so that ts
25-
// will load the lib files from disk
26-
process.env.CI = 'true';
27-
2824
CODE_TS = await fs.readFile(
2925
path.resolve(__dirname, '..', 'test', 'fixtures', 'code.ts'),
3026
'utf8',

packages/ts-autocomplete/src/index.ts

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,12 @@ function relativeNodePath(fileName: string): string {
2323
return parts[parts.length - 1];
2424
}
2525

26-
type EncounteredPaths = {
27-
getScriptSnapshot: string[];
28-
fileExists: string[];
29-
readFile: string[];
30-
};
31-
32-
function getVirtualLanguageService(): {
26+
function getVirtualLanguageService(
27+
fallbackServiceHost?: ts.LanguageServiceHost,
28+
): {
3329
languageService: ts.LanguageService;
3430
updateCode: UpdateDefinitionFunction;
3531
listFiles: () => string[];
36-
listEncounteredPaths: () => EncounteredPaths;
3732
} {
3833
// as an optimization, the contents of a file can be string or true. This is
3934
// because some files are only checked for existence during module resolution,
@@ -61,19 +56,7 @@ function getVirtualLanguageService(): {
6156
return Object.keys(codeHolder);
6257
};
6358

64-
const encounteredPaths: EncounteredPaths = {
65-
getScriptSnapshot: [],
66-
fileExists: [],
67-
readFile: [],
68-
};
69-
const listEncounteredPaths = (): EncounteredPaths => {
70-
encounteredPaths.getScriptSnapshot.sort();
71-
encounteredPaths.fileExists.sort();
72-
encounteredPaths.readFile.sort();
73-
return encounteredPaths;
74-
};
75-
76-
const servicesHost: ts.LanguageServiceHost = {
59+
const serviceHost: ts.LanguageServiceHost = {
7760
getScriptFileNames: () => {
7861
return Object.keys(codeHolder);
7962
},
@@ -87,14 +70,8 @@ function getVirtualLanguageService(): {
8770
return ts.ScriptSnapshot.fromString(codeHolder[fileName].toString());
8871
}
8972

90-
if (process.env.CI) {
91-
const result = ts.ScriptSnapshot.fromString(
92-
// NOTE: some files do not exist. A good example is "typescript/lib/es2023.ts"
93-
ts.sys.readFile(fileName) || '',
94-
);
95-
96-
encounteredPaths.getScriptSnapshot.push(relativeNodePath(fileName));
97-
return result;
73+
if (fallbackServiceHost) {
74+
return fallbackServiceHost.getScriptSnapshot(fileName);
9875
}
9976
},
10077
getCurrentDirectory: () => process.cwd(),
@@ -108,12 +85,8 @@ function getVirtualLanguageService(): {
10885
return true;
10986
}
11087

111-
if (process.env.CI) {
112-
const result = ts.sys.fileExists(fileName);
113-
if (result) {
114-
encounteredPaths.fileExists.push(relativeNodePath(fileName));
115-
}
116-
return result;
88+
if (fallbackServiceHost) {
89+
return fallbackServiceHost.fileExists(fileName);
11790
}
11891

11992
return false;
@@ -124,27 +97,25 @@ function getVirtualLanguageService(): {
12497
return codeHolder[fileName].toString();
12598
}
12699

127-
if (process.env.CI) {
128-
const result = ts.sys.readFile(fileName);
129-
encounteredPaths.readFile.push(relativeNodePath(fileName));
130-
return result;
100+
if (fallbackServiceHost) {
101+
return fallbackServiceHost.readFile(fileName);
131102
}
132103
},
133104
readDirectory: (...args) => {
134-
if (process.env.CI) {
135-
return ts.sys.readDirectory(...args);
105+
if (fallbackServiceHost && fallbackServiceHost.readDirectory) {
106+
return fallbackServiceHost.readDirectory(...args);
136107
}
137108
return [];
138109
},
139110
directoryExists: (...args) => {
140-
if (process.env.CI) {
141-
return ts.sys.directoryExists(...args);
111+
if (fallbackServiceHost && fallbackServiceHost.directoryExists) {
112+
return fallbackServiceHost.directoryExists(...args);
142113
}
143114
return false;
144115
},
145116
getDirectories: (...args) => {
146-
if (process.env.CI) {
147-
return ts.sys.getDirectories(...args);
117+
if (fallbackServiceHost && fallbackServiceHost.getDirectories) {
118+
return fallbackServiceHost.getDirectories(...args);
148119
}
149120
return [];
150121
},
@@ -155,12 +126,11 @@ function getVirtualLanguageService(): {
155126

156127
return {
157128
languageService: ts.createLanguageService(
158-
servicesHost,
129+
serviceHost,
159130
ts.createDocumentRegistry(),
160131
),
161132
updateCode,
162133
listFiles,
163-
listEncounteredPaths,
164134
};
165135
}
166136

@@ -233,6 +203,7 @@ type AutocompleteFilterFunction = (
233203

234204
export type AutocompleterOptions = {
235205
filter?: AutocompleteFilterFunction;
206+
fallbackServiceHost?: ts.LanguageServiceHost;
236207
};
237208

238209
function filterDiagnostics(diagnostics: ts.Diagnostic[]): {
@@ -259,16 +230,14 @@ export default class Autocompleter {
259230
private readonly languageService: ts.LanguageService;
260231
readonly updateCode: UpdateDefinitionFunction;
261232
readonly listFiles: () => string[];
262-
readonly listEncounteredPaths: () => EncounteredPaths;
263233

264-
constructor({ filter }: AutocompleterOptions = {}) {
234+
constructor({ filter, fallbackServiceHost }: AutocompleterOptions = {}) {
265235
this.filter = filter ?? (() => true);
266236
({
267237
languageService: this.languageService,
268238
updateCode: this.updateCode,
269239
listFiles: this.listFiles,
270-
listEncounteredPaths: this.listEncounteredPaths,
271-
} = getVirtualLanguageService());
240+
} = getVirtualLanguageService(fallbackServiceHost));
272241
}
273242

274243
autocomplete(code: string): AutoCompletion[] {

0 commit comments

Comments
 (0)