Skip to content

Commit 1f9f20f

Browse files
committed
Swap out TSD for Types 2.0
1 parent 5e37a31 commit 1f9f20f

6 files changed

Lines changed: 52 additions & 105 deletions

File tree

src/server/editorServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ namespace ts.server {
213213
}
214214
switch (response.kind) {
215215
case "set":
216-
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings, response.files);
216+
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
217217
project.updateGraph();
218218
break;
219219
case "invalidate":

src/server/project.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ namespace ts.server {
355355
removed.push(id);
356356
}
357357
}
358+
if (added.length > 0 || removed.length > 0) {
359+
this.projectService.typingsCache.invalidateCachedTypingsForProject(this);
360+
}
358361
this.lastReportedFileNames = currentFiles;
359362

360363
this.lastReportedFileNames = currentFiles;

src/server/types.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ declare namespace ts.server {
4545
readonly typingOptions: ts.TypingOptions;
4646
readonly compilerOptions: ts.CompilerOptions;
4747
readonly typings: string[];
48-
readonly files: string[];
4948
readonly kind: "set";
5049
}
5150

src/server/typingsCache.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ namespace ts.server {
1717
readonly typingOptions: TypingOptions;
1818
readonly compilerOptions: CompilerOptions;
1919
readonly typings: TypingsArray;
20-
readonly files: string[];
2120
poisoned: boolean;
2221
}
2322

2423
const emptyArray: any[] = [];
25-
const jsOrDts = [".js", ".d.ts"];
24+
const jsOrDts = [".js", ".jsx", ".d.ts"];
2625

2726
function getTypingOptionsForProjects(proj: Project): TypingOptions {
2827
if (proj.projectKind === ProjectKind.Configured) {
@@ -74,10 +73,6 @@ namespace ts.server {
7473
return opt1.allowJs != opt2.allowJs;
7574
}
7675

77-
function filesChanged(before: string[], after: string[]): boolean {
78-
return !setIsEqualTo(before, after);
79-
}
80-
8176
export interface TypingsArray extends ReadonlyArray<string> {
8277
" __typingsArrayBrand": any;
8378
}
@@ -102,18 +97,17 @@ namespace ts.server {
10297

10398
const entry = this.perProjectCache[project.getProjectName()];
10499
const result: TypingsArray = entry ? entry.typings : <any>emptyArray;
105-
if (!entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions) || filesChanged(project.getFileNames(), entry.files)) {
106-
// something has been changed, issue a request to update typings
107-
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
100+
if (!entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions)) {
108101
// Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
109102
// instead it acts as a placeholder to prevent issuing multiple requests
110103
this.perProjectCache[project.getProjectName()] = {
111104
compilerOptions: project.getCompilerOptions(),
112105
typingOptions,
113106
typings: result,
114-
files: project.getFileNames(),
115107
poisoned: true
116108
};
109+
// something has been changed, issue a request to update typings
110+
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
117111
}
118112
return result;
119113
}
@@ -126,12 +120,11 @@ namespace ts.server {
126120
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
127121
}
128122

129-
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, newTypings: string[], files: string[]) {
123+
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, newTypings: string[]) {
130124
this.perProjectCache[projectName] = {
131125
compilerOptions,
132126
typingOptions,
133127
typings: toTypingsArray(newTypings),
134-
files: files,
135128
poisoned: false
136129
};
137130
}

src/server/typingsInstaller/nodeTypingsInstaller.ts

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace ts.server.typingsInstaller {
4646
private exec: { (command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any };
4747
private npmBinPath: string;
4848

49-
private tsdRunCount = 1;
49+
private installRunCount = 1;
5050
readonly installTypingHost: InstallTypingHost = sys;
5151

5252
constructor(log?: Log) {
@@ -101,23 +101,6 @@ namespace ts.server.typingsInstaller {
101101
}
102102
}
103103

104-
protected installPackage(packageName: string) {
105-
try {
106-
const output = this.execSync(`npm install --silent --global ${packageName}`, { stdio: "pipe" }).toString();
107-
if (this.log.isEnabled()) {
108-
this.log.writeLine(`installPackage::stdout '${output}'`);
109-
}
110-
return true;
111-
}
112-
catch (e) {
113-
if (this.log.isEnabled()) {
114-
this.log.writeLine(`installPackage::err::stdout '${e.stdout && e.stdout.toString()}'`);
115-
this.log.writeLine(`installPackage::err::stderr '${e.stdout && e.stderr.toString()}'`);
116-
}
117-
return false;
118-
}
119-
}
120-
121104
protected sendResponse(response: SetTypings | InvalidateCachedTypings) {
122105
if (this.log.isEnabled()) {
123106
this.log.writeLine(`Sending response: ${JSON.stringify(response)}`);
@@ -128,30 +111,23 @@ namespace ts.server.typingsInstaller {
128111
}
129112
}
130113

131-
protected runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void {
132-
const id = this.tsdRunCount;
133-
this.tsdRunCount++;
134-
const tsdPath = combinePaths(this.npmBinPath, "tsd");
135-
const command = `${tsdPath} install ${typingsToInstall.join(" ")} -ros`;
114+
protected runInstall(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void {
115+
const id = this.installRunCount;
116+
this.installRunCount++;
117+
const command = `npm install @types/${typingsToInstall.join(" @types/")} --save-dev`;
136118
if (this.log.isEnabled()) {
137-
this.log.writeLine(`Running tsd ${id}, command '${command}'. cache path '${cachePath}'`);
119+
this.log.writeLine(`Running npm install @types ${id}, command '${command}'. cache path '${cachePath}'`);
138120
}
139121
this.exec(command, { cwd: cachePath }, (err, stdout, stderr) => {
140122
if (this.log.isEnabled()) {
141-
this.log.writeLine(`TSD ${id} stdout: ${stdout}`);
142-
this.log.writeLine(`TSD ${id} stderr: ${stderr}`);
143-
}
144-
const i = stdout.indexOf("running install");
145-
if (i < 0) {
146-
return;
123+
this.log.writeLine(`npm install @types ${id} stdout: ${stdout}`);
124+
this.log.writeLine(`npm install @types ${id} stderr: ${stderr}`);
147125
}
148126
const installedTypings: string[] = [];
149-
150-
const expr = /^\s*-\s*(\S+)\s*$/gm;
151-
expr.lastIndex = i;
127+
const expr = /^.*(node_modules)\\(@types)\\(\S+)\s*$/gm;
152128
let match: RegExpExecArray;
153129
while (match = expr.exec(stdout)) {
154-
installedTypings.push(match[1]);
130+
installedTypings.push(`${match[1]}/${match[2]}/${match[3]}`);
155131
}
156132
postInstallAction(installedTypings);
157133
});

src/server/typingsInstaller/typingsInstaller.ts

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1+
/// <reference path="../../compiler/core.ts" />
12
/// <reference path="../../services/jsTyping.ts"/>
23
/// <reference path="../types.d.ts"/>
34

45
namespace ts.server.typingsInstaller {
5-
const DefaultTsdSettings = JSON.stringify({
6-
version: "v4",
7-
repo: "DefinitelyTyped/DefinitelyTyped",
8-
ref: "master",
9-
path: "typings"
10-
}, /*replacer*/undefined, /*space*/4);
11-
12-
interface TsdConfig {
13-
installed: MapLike<any>;
6+
interface NpmConfig {
7+
devDependencies: MapLike<any>;
148
}
159

1610
export interface Log {
@@ -23,18 +17,17 @@ namespace ts.server.typingsInstaller {
2317
writeLine: () => {}
2418
};
2519

26-
function tsdTypingToFileName(cachePath: string, tsdTypingFile: string) {
27-
return combinePaths(cachePath, `typings/${tsdTypingFile}`);
20+
function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost): string {
21+
const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost);
22+
return result.resolvedModule ? result.resolvedModule.resolvedFileName : null;
2823
}
2924

30-
function getPackageName(tsdTypingFile: string) {
31-
const idx = tsdTypingFile.indexOf("/");
32-
return idx > 0 ? tsdTypingFile.substr(0, idx) : undefined;
25+
function getPackageName(typingFile: string) {
26+
const idx = typingFile.lastIndexOf("/");
27+
return idx > 0 ? typingFile.substr(idx + 1) : undefined;
3328
}
3429

3530
export abstract class TypingsInstaller {
36-
private isTsdInstalled: boolean;
37-
3831
private packageNameToTypingLocation: Map<string> = createMap<string>();
3932
private missingTypingsSet: Map<true> = createMap<true>();
4033
private knownCachesSet: Map<true> = createMap<true>();
@@ -50,20 +43,6 @@ namespace ts.server.typingsInstaller {
5043
}
5144

5245
init() {
53-
this.isTsdInstalled = this.isPackageInstalled("tsd");
54-
if (this.log.isEnabled()) {
55-
this.log.writeLine(`isTsdInstalled: ${this.isTsdInstalled}`);
56-
}
57-
58-
if (!this.isTsdInstalled) {
59-
if (this.log.isEnabled()) {
60-
this.log.writeLine(`tsd is not installed, installing tsd...`);
61-
}
62-
this.isTsdInstalled = this.installPackage("tsd");
63-
if (this.log.isEnabled()) {
64-
this.log.writeLine(`isTsdInstalled: ${this.isTsdInstalled}`);
65-
}
66-
}
6746
this.processCacheLocation(this.globalCachePath);
6847
}
6948

@@ -94,13 +73,6 @@ namespace ts.server.typingsInstaller {
9473
}
9574

9675
install(req: DiscoverTypings) {
97-
if (!this.isTsdInstalled) {
98-
if (this.log.isEnabled()) {
99-
this.log.writeLine(`tsd is not installed, ignoring request...`);
100-
}
101-
return;
102-
}
103-
10476
if (this.log.isEnabled()) {
10577
this.log.writeLine(`Got install request ${JSON.stringify(req)}`);
10678
}
@@ -153,23 +125,26 @@ namespace ts.server.typingsInstaller {
153125
}
154126
return;
155127
}
156-
const tsdJson = combinePaths(cacheLocation, "tsd.json");
128+
const packageJson = combinePaths(cacheLocation, "package.json");
157129
if (this.log.isEnabled()) {
158-
this.log.writeLine(`Trying to find '${tsdJson}'...`);
130+
this.log.writeLine(`Trying to find '${packageJson}'...`);
159131
}
160-
if (this.installTypingHost.fileExists(tsdJson)) {
161-
const tsdConfig = <TsdConfig>JSON.parse(this.installTypingHost.readFile(tsdJson));
132+
if (this.installTypingHost.fileExists(packageJson)) {
133+
const npmConfig = <NpmConfig>JSON.parse(this.installTypingHost.readFile(packageJson));
162134
if (this.log.isEnabled()) {
163-
this.log.writeLine(`Loaded content of '${tsdJson}': ${JSON.stringify(tsdConfig)}`);
135+
this.log.writeLine(`Loaded content of '${npmConfig}': ${JSON.stringify(npmConfig)}`);
164136
}
165-
if (tsdConfig.installed) {
166-
for (const key in tsdConfig.installed) {
167-
// key is <package name>/<typing file>
137+
if (npmConfig.devDependencies) {
138+
for (const key in npmConfig.devDependencies) {
139+
// key is @types/<package name>
168140
const packageName = getPackageName(key);
169141
if (!packageName) {
170142
continue;
171143
}
172-
const typingFile = tsdTypingToFileName(cacheLocation, key);
144+
var typingFile = typingToFileName(cacheLocation, packageName, this.installTypingHost);
145+
if (!typingFile) {
146+
continue;
147+
}
173148
const existingTypingFile = this.packageNameToTypingLocation[packageName];
174149
if (existingTypingFile === typingFile) {
175150
continue;
@@ -204,20 +179,19 @@ namespace ts.server.typingsInstaller {
204179
return;
205180
}
206181

207-
// TODO: install typings and send response when they are ready
208-
const tsdPath = combinePaths(cachePath, "tsd.json");
182+
const npmConfigPath = combinePaths(cachePath, "package.json");
209183
if (this.log.isEnabled()) {
210-
this.log.writeLine(`Tsd config file: ${tsdPath}`);
184+
this.log.writeLine(`Npm config file: ${npmConfigPath}`);
211185
}
212-
if (!this.installTypingHost.fileExists(tsdPath)) {
186+
if (!this.installTypingHost.fileExists(npmConfigPath)) {
213187
if (this.log.isEnabled()) {
214-
this.log.writeLine(`Tsd config file '${tsdPath}' is missing, creating new one...`);
188+
this.log.writeLine(`Npm config file: '${npmConfigPath}' is missing, creating new one...`);
215189
}
216190
this.ensureDirectoryExists(cachePath, this.installTypingHost);
217-
this.installTypingHost.writeFile(tsdPath, DefaultTsdSettings);
191+
this.installTypingHost.writeFile(npmConfigPath, "{}");
218192
}
219193

220-
this.runTsd(cachePath, typingsToInstall, installedTypings => {
194+
this.runInstall(cachePath, typingsToInstall, installedTypings => {
221195
// TODO: watch project directory
222196
if (this.log.isEnabled()) {
223197
this.log.writeLine(`Requested to install typings ${JSON.stringify(typingsToInstall)}, installed typings ${JSON.stringify(installedTypings)}`);
@@ -230,7 +204,11 @@ namespace ts.server.typingsInstaller {
230204
continue;
231205
}
232206
installedPackages[packageName] = true;
233-
installedTypingFiles.push(tsdTypingToFileName(cachePath, t));
207+
var typingFile = typingToFileName(cachePath, packageName, this.installTypingHost);
208+
if (!typingFile) {
209+
continue;
210+
}
211+
installedTypingFiles.push(typingFile);
234212
}
235213
if (this.log.isEnabled()) {
236214
this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`);
@@ -287,14 +265,12 @@ namespace ts.server.typingsInstaller {
287265
typingOptions: request.typingOptions,
288266
compilerOptions: request.compilerOptions,
289267
typings,
290-
files: request.fileNames,
291268
kind: "set"
292269
};
293270
}
294271

295272
protected abstract isPackageInstalled(packageName: string): boolean;
296-
protected abstract installPackage(packageName: string): boolean;
297273
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings): void;
298-
protected abstract runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void;
274+
protected abstract runInstall(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void;
299275
}
300276
}

0 commit comments

Comments
 (0)