From f13cef19dd9ca0113a61cbbaeedd3c9b15461d72 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 22 Sep 2016 14:34:08 -0700 Subject: [PATCH] Add fallback for npm location if not running under node.exe --- .../unittests/tsserverProjectSystem.ts | 2 +- src/harness/unittests/typingsInstaller.ts | 92 +++++++++++++++++++ .../typingsInstaller/nodeTypingsInstaller.ts | 12 ++- .../typingsInstaller/typingsInstaller.ts | 2 +- src/server/utilities.ts | 2 +- src/services/jsTyping.ts | 2 +- 6 files changed, 107 insertions(+), 5 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index f34dfa31fc0..e70b97f7ef5 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1939,7 +1939,7 @@ namespace ts.projectSystem { content: JSON.stringify({ compilerOptions: { allowJs: true }, exclude: ["node_modules"] }) }; const host = createServerHost([f1, barjs, barTypings, config]); - const projectService = createProjectService(host, { typingsInstaller: new TestTypingsInstaller(typingsCacheLocation, host) }); + const projectService = createProjectService(host, { typingsInstaller: new TestTypingsInstaller(typingsCacheLocation, 5, host) }); projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 9dd1247c897..117ca65cb64 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -627,5 +627,97 @@ namespace ts.projectSystem { checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path, commander.path, jquery.path, lodash.path, cordova.path]); checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path ]); }); + + it("configured projects discover from node_modules", () => { + const app = { + path: "/app.js", + content: "" + }; + const jsconfig = { + path: "/jsconfig.json", + content: JSON.stringify({}) + }; + const jquery = { + path: "/node_modules/jquery/index.js", + content: "" + }; + const jqueryPackage = { + path: "/node_modules/jquery/package.json", + content: JSON.stringify({ name: "jquery" }) + }; + const jqueryDTS = { + path: "/tmp/node_modules/@types/jquery/index.d.ts", + content: "" + }; + const host = createServerHost([app, jsconfig, jquery, jqueryPackage]); + const installer = new (class extends Installer { + constructor() { + super(host, { globalTypingsCacheLocation: "/tmp" }); + } + runCommand(requestKind: TI.RequestKind, requestId: number, command: string, cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + const installedTypings = ["@types/jquery"]; + const typingFiles = [jqueryDTS]; + executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + } + })(); + + const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer }); + projectService.openClientFile(app.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const p = projectService.configuredProjects[0]; + checkProjectActualFiles(p, [app.path]); + + installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(p, [app.path, jqueryDTS.path]); + }); + + it("configured projects discover from bower.josn", () => { + const app = { + path: "/app.js", + content: "" + }; + const jsconfig = { + path: "/jsconfig.json", + content: JSON.stringify({}) + }; + const bowerJson = { + path: "/bower.json", + content: JSON.stringify({ + "dependencies": { + "jquery": "^3.1.0" + } + }) + }; + const jqueryDTS = { + path: "/tmp/node_modules/@types/jquery/index.d.ts", + content: "" + }; + const host = createServerHost([app, jsconfig, bowerJson]); + const installer = new (class extends Installer { + constructor() { + super(host, { globalTypingsCacheLocation: "/tmp" }); + } + runCommand(requestKind: TI.RequestKind, requestId: number, command: string, cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + const installedTypings = ["@types/jquery"]; + const typingFiles = [jqueryDTS]; + executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + } + })(); + + const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer }); + projectService.openClientFile(app.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const p = projectService.configuredProjects[0]; + checkProjectActualFiles(p, [app.path]); + + installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(p, [app.path, jqueryDTS.path]); + }); }); } \ No newline at end of file diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 7df1e9a7877..b73a8e4e79d 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -9,6 +9,7 @@ namespace ts.server.typingsInstaller { const path: { join(...parts: string[]): string; dirname(path: string): string; + basename(path: string, extension?: string): string; } = require("path"); class FileLog implements Log { @@ -23,6 +24,15 @@ namespace ts.server.typingsInstaller { } } + function getNPMLocation(processName: string) { + if (path.basename(processName).indexOf("node") == 0) { + return `"${path.join(path.dirname(process.argv[0]), "npm")}"`; + } + else { + return "npm"; + } + } + export class NodeTypingsInstaller extends TypingsInstaller { private readonly exec: { (command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any }; @@ -31,7 +41,7 @@ namespace ts.server.typingsInstaller { constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) { super( globalTypingsCacheLocation, - /*npmPath*/ `"${path.join(path.dirname(process.argv[0]), "npm")}"`, + /*npmPath*/ getNPMLocation(process.argv[0]), toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), throttleLimit, log); diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 1113e6e2701..5437328b581 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -150,7 +150,7 @@ namespace ts.server.typingsInstaller { if (this.installTypingHost.fileExists(packageJson)) { const npmConfig = JSON.parse(this.installTypingHost.readFile(packageJson)); if (this.log.isEnabled()) { - this.log.writeLine(`Loaded content of '${npmConfig}': ${JSON.stringify(npmConfig)}`); + this.log.writeLine(`Loaded content of '${packageJson}': ${JSON.stringify(npmConfig)}`); } if (npmConfig.devDependencies) { for (const key in npmConfig.devDependencies) { diff --git a/src/server/utilities.ts b/src/server/utilities.ts index a7a0160ea62..69962fa186e 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -35,7 +35,7 @@ namespace ts.server { function getProjectRootPath(project: Project): Path { switch (project.projectKind) { case ProjectKind.Configured: - return project.getProjectName(); + return getDirectoryPath(project.getProjectName()); case ProjectKind.Inferred: // TODO: fixme return ""; diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 32670c738fa..d50e26c6194 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -187,7 +187,7 @@ namespace ts.JsTyping { } const typingNames: string[] = []; - const fileNames = host.readDirectory(nodeModulesPath, ["*.json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); + const fileNames = host.readDirectory(nodeModulesPath, [".json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); for (const fileName of fileNames) { const normalizedFileName = normalizePath(fileName); if (getBaseFileName(normalizedFileName) !== "package.json") {