From c884fee3eb5bb66d7c661dd241033546b7198bfc Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 13:16:20 -0700 Subject: [PATCH 1/6] Remove dependncy on NodeJs from editor services --- src/harness/harnessLanguageService.ts | 8 ++++++++ src/server/editorServices.ts | 6 +++--- src/server/server.ts | 11 ++++++++--- src/server/session.ts | 2 ++ tests/cases/unittests/cachingInServerLSHost.ts | 6 ++++++ tests/cases/unittests/session.ts | 4 +++- tests/cases/unittests/versionCache.ts | 2 +- 7 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 8aaff65febc..96f516632c7 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -641,6 +641,14 @@ namespace Harness.LanguageService { startGroup(): void { } + + setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any { + return setTimeout(callback, ms, args); + } + + clearTimeout(timeoutId: any): void { + clearTimeout(timeoutId); + } } export class ServerLanguageServiceAdapter implements LanguageServiceAdapter { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 77908779d9f..793e17d52e7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -533,7 +533,7 @@ namespace ts.server { // number becomes 0 for a watcher, then we should close it. directoryWatchersRefCount: ts.Map = {}; hostConfiguration: HostConfiguration; - timerForDetectingProjectFileListChanges: Map = {}; + timerForDetectingProjectFileListChanges: Map = {}; constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) { // ts.disableIncrementalParsing = true; @@ -593,9 +593,9 @@ namespace ts.server { startTimerForDetectingProjectFileListChanges(project: Project) { if (this.timerForDetectingProjectFileListChanges[project.projectFilename]) { - clearTimeout(this.timerForDetectingProjectFileListChanges[project.projectFilename]); + this.host.clearTimeout(this.timerForDetectingProjectFileListChanges[project.projectFilename]); } - this.timerForDetectingProjectFileListChanges[project.projectFilename] = setTimeout( + this.timerForDetectingProjectFileListChanges[project.projectFilename] = this.host.setTimeout( () => this.handleProjectFileListChanges(project), 250 ); diff --git a/src/server/server.ts b/src/server/server.ts index ec83f8cc716..767793024c2 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -266,16 +266,21 @@ namespace ts.server { } } + const sys = ts.sys; + // Override sys.write because fs.writeSync is not reliable on Node 4 - ts.sys.write = (s: string) => writeMessage(s); - ts.sys.watchFile = (fileName, callback) => { + sys.write = (s: string) => writeMessage(s); + sys.watchFile = (fileName, callback) => { const watchedFile = pollingWatchedFileSet.addFile(fileName, callback); return { close: () => pollingWatchedFileSet.removeFile(watchedFile) }; }; - const ioSession = new IOSession(ts.sys, logger); + sys.setTimeout = setTimeout; + sys.clearTimeout = clearTimeout; + + const ioSession = new IOSession(sys, logger); process.on("uncaughtException", function(err: Error) { ioSession.logError(err, "unknown"); }); diff --git a/src/server/session.ts b/src/server/session.ts index 8c6525a70e6..09b86da48cc 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -133,6 +133,8 @@ namespace ts.server { } export interface ServerHost extends ts.System { + setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + clearTimeout(timeoutId: any): void; } export class Session { diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 58bcd76e246..0d14113942c 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -60,6 +60,12 @@ module ts { return { close: () => { } } + }, + setTimeout: (callback, ms, ...args) => { + return setTimeout(callback, ms, args); + }, + clearTimeout: (timeoutId) => { + clearTimeout(timeoutId); } }; } diff --git a/tests/cases/unittests/session.ts b/tests/cases/unittests/session.ts index ee9742482cd..a90f7d2ec84 100644 --- a/tests/cases/unittests/session.ts +++ b/tests/cases/unittests/session.ts @@ -18,7 +18,9 @@ namespace ts.server { getExecutingFilePath(): string { return void 0; }, getCurrentDirectory(): string { return void 0; }, readDirectory(): string[] { return []; }, - exit(): void {} + exit(): void { }, + setTimeout(callback, ms, ...args) { return 0; }, + clearTimeout(timeoutId) { } }; const mockLogger: Logger = { close(): void {}, diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index c1d283ca8cd..4c2b21224c8 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -271,7 +271,7 @@ and grew 1cm per day`; }); it("Edit ScriptVersionCache ", () => { - let svc = server.ScriptVersionCache.fromString(ts.sys, testContent); + let svc = server.ScriptVersionCache.fromString(ts.sys, testContent); let checkText = testContent; for (let i = 0; i < iterationCount; i++) { From b672487fa92e268f4059e3d711efe446a69fd6f3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 13:16:24 -0700 Subject: [PATCH 2/6] Add lssl to LKG build --- Jakefile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index f39fcba0705..1b51cf0358d 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -595,8 +595,8 @@ task("generate-spec", [specMd]); // Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory desc("Makes a new LKG out of the built js files"); -task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() { - var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile].concat(libraryTargets); +task("LKG", ["clean", "release", "local", "lssl"].concat(libraryTargets), function() { + var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, lsslFile].concat(libraryTargets); var missingFiles = expectedFiles.filter(function (f) { return !fs.existsSync(f); }); From f573b1031b46bdeb16c1b617603e6783e6111412 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 13:31:21 -0700 Subject: [PATCH 3/6] lint fixes --- Jakefile.js | 72 ++++++++-------- src/services/utilities.ts | 14 ++-- .../cases/unittests/cachingInServerLSHost.ts | 67 ++++++++------- tests/cases/unittests/versionCache.ts | 84 +++++++++---------- 4 files changed, 118 insertions(+), 119 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 1b51cf0358d..2424c414389 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -160,7 +160,7 @@ var harnessSources = harnessCoreSources.concat([ "protocol.d.ts", "session.ts", "client.ts", - "editorServices.ts", + "editorServices.ts" ].map(function (f) { return path.join(serverDirectory, f); })); @@ -174,7 +174,7 @@ var es2015LibrarySources = [ "es2015.proxy.d.ts", "es2015.reflect.d.ts", "es2015.symbol.d.ts", - "es2015.symbol.wellknown.d.ts", + "es2015.symbol.wellknown.d.ts" ]; var es2015LibrarySourceMap = es2015LibrarySources.map(function(source) { @@ -183,25 +183,25 @@ var es2015LibrarySourceMap = es2015LibrarySources.map(function(source) { var es2016LibrarySource = [ "es2016.array.include.d.ts" ]; -var es2016LibrarySourceMap = es2016LibrarySource.map(function(source) { +var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) { return { target: "lib." + source, sources: ["header.d.ts", source] }; -}) +}); var es2017LibrarySource = ["es2017.object.d.ts"]; -var es2017LibrarySourceMap = es2017LibrarySource.map(function(source) { +var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) { return { target: "lib." + source, sources: ["header.d.ts", source] }; -}) +}); -var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"] +var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"]; var librarySourceMap = [ // Host library - { target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"], }, - { target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"], }, - { target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"], }, - { target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"], }, - + { target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] }, + { target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] }, + { target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] }, + { target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] }, + // JavaScript library { target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] }, { target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] }, @@ -209,8 +209,8 @@ var librarySourceMap = [ { target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] }, // JavaScript + all host library - { target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources), }, - { target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts"), }, + { target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) }, + { target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") } ].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap); var libraryTargets = librarySourceMap.map(function (f) { @@ -251,7 +251,7 @@ function concatenateFiles(destinationFile, sourceFiles) { } var useDebugMode = true; -var host = (process.env.TYPESCRIPT_HOST || process.env.host || "node"); +var host = process.env.TYPESCRIPT_HOST || process.env.host || "node"; var compilerFilename = "tsc.js"; var LKGCompiler = path.join(LKGDirectory, compilerFilename); var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename); @@ -300,7 +300,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts options += " --out " + outFile; } else { - options += " --module commonjs" + options += " --module commonjs"; } if(opts.noResolve) { @@ -315,7 +315,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts } if (opts.stripInternal) { - options += " --stripInternal" + options += " --stripInternal"; } var cmd = host + " " + compilerPath + " " + options + " "; @@ -453,9 +453,9 @@ file(scriptsTsdJson); task("tsd-scripts", [scriptsTsdJson], function () { var cmd = "tsd --config " + scriptsTsdJson + " install"; - console.log(cmd) + console.log(cmd); exec(cmd); -}, { async: true }) +}, { async: true }); var importDefinitelyTypedTestsDirectory = path.join(scriptsDirectory, "importDefinitelyTypedTests"); var importDefinitelyTypedTestsJs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.js"); @@ -525,9 +525,9 @@ compileFile(servicesFileInBrowserTest, servicesSources,[builtLocalDirectory, cop var serverFile = path.join(builtLocalDirectory, "tsserver.js"); compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true); -var lsslFile = path.join(builtLocalDirectory, "tslssl.js"); +var tsserverLibraryFile = path.join(builtLocalDirectory, "tslssl.js"); compileFile( - lsslFile, + tsserverLibraryFile, languageServiceLibrarySources, [builtLocalDirectory, copyright].concat(languageServiceLibrarySources), /*prefixes*/ [copyright], @@ -536,7 +536,7 @@ compileFile( // Local target to build the language service server library desc("Builds language service server library"); -task("lssl", [lsslFile]); +task("lssl", [tsserverLibraryFile]); // Local target to build the compiler and services desc("Builds the full compiler and services"); @@ -596,7 +596,7 @@ task("generate-spec", [specMd]); // Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory desc("Makes a new LKG out of the built js files"); task("LKG", ["clean", "release", "local", "lssl"].concat(libraryTargets), function() { - var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, lsslFile].concat(libraryTargets); + var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile].concat(libraryTargets); var missingFiles = expectedFiles.filter(function (f) { return !fs.existsSync(f); }); @@ -622,7 +622,7 @@ directory(builtLocalDirectory); var run = path.join(builtLocalDirectory, "run.js"); compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [], /*useBuiltCompiler:*/ true); -var internalTests = "internal/" +var internalTests = "internal/"; var localBaseline = "tests/baselines/local/"; var refBaseline = "tests/baselines/reference/"; @@ -709,7 +709,7 @@ function runConsoleTests(defaultReporter, defaultSubsets) { testTimeout = 100000; } - colors = process.env.colors || process.env.color + colors = process.env.colors || process.env.color; colors = colors ? ' --no-colors ' : ' --colors '; reporter = process.env.reporter || process.env.r || defaultReporter; var lintFlag = process.env.lint !== 'false'; @@ -718,7 +718,7 @@ function runConsoleTests(defaultReporter, defaultSubsets) { // default timeout is 2sec which really should be enough, but maybe we just need a small amount longer var subsetRegexes; if(defaultSubsets.length === 0) { - subsetRegexes = [tests] + subsetRegexes = [tests]; } else { var subsets = tests ? tests.split("|") : defaultSubsets; @@ -764,8 +764,8 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () { }, { async: true }); // Browser tests -var nodeServerOutFile = 'tests/webTestServer.js' -var nodeServerInFile = 'tests/webTestServer.ts' +var nodeServerOutFile = "tests/webTestServer.js"; +var nodeServerInFile = "tests/webTestServer.ts"; compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true }); desc("Runs browserify on run.js to produce a file suitable for running tests in the browser"); @@ -777,7 +777,7 @@ task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], port=, browser=[chrome|IE]"); task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function() { cleanTestDirs(); - host = "node" + host = "node"; port = process.env.port || process.env.p || '8888'; browser = process.env.browser || process.env.b || "IE"; tests = process.env.test || process.env.tests || process.env.t; @@ -791,13 +791,13 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi } tests = tests ? tests : ''; - var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests + var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests; console.log(cmd); exec(cmd); }, {async: true}); function getDiffTool() { - var program = process.env['DIFF'] + var program = process.env['DIFF']; if (!program) { fail("Add the 'DIFF' environment variable to the path of the program you want to use."); } @@ -826,11 +826,11 @@ task("tests-debug", ["setDebugMode", "tests"]); // Makes the test results the new baseline desc("Makes the most recent test results the new baseline, overwriting the old baseline"); task("baseline-accept", function(hardOrSoft) { - if (!hardOrSoft || hardOrSoft == "hard") { + if (!hardOrSoft || hardOrSoft === "hard") { jake.rmRf(refBaseline); fs.renameSync(localBaseline, refBaseline); } - else if (hardOrSoft == "soft") { + else if (hardOrSoft === "soft") { var files = jake.readdirR(localBaseline); for (var i in files) { jake.cpR(files[i], refBaseline); @@ -909,14 +909,14 @@ task("update-sublime", ["local", serverFile], function() { }); var tslintRuleDir = "scripts/tslint"; -var tslintRules = ([ +var tslintRules = [ "nextLineRule", "preferConstRule", "booleanTriviaRule", "typeOperatorSpacingRule", "noInOperatorRule", "noIncrementDecrementRule" -]); +]; var tslintRulesFiles = tslintRules.map(function(p) { return path.join(tslintRuleDir, p + ".ts"); }); @@ -941,7 +941,7 @@ function getLinterOptions() { function lintFileContents(options, path, contents) { var ll = new Linter(path, contents, options); - console.log("Linting '" + path + "'.") + console.log("Linting '" + path + "'."); return ll.lint(); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5a676a6692d..404fdf92d4d 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -370,7 +370,7 @@ namespace ts { if (lookInPreviousChild) { // actual start of the node is past the position - previous token should be at the end of previous child let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i); - return candidate && findRightmostToken(candidate) + return candidate && findRightmostToken(candidate); } else { // candidate should be in this node @@ -490,8 +490,8 @@ namespace ts { return forEach(commentRanges, jsDocPrefix); function jsDocPrefix(c: CommentRange): boolean { - var text = sourceFile.text; - return text.length >= c.pos + 3 && text[c.pos] === '/' && text[c.pos + 1] === '*' && text[c.pos + 2] === '*'; + const text = sourceFile.text; + return text.length >= c.pos + 3 && text[c.pos] === "/" && text[c.pos + 1] === "*" && text[c.pos + 2] === "*"; } } @@ -546,7 +546,7 @@ namespace ts { if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier); - return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none; + return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none; } export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray { @@ -629,7 +629,7 @@ namespace ts { // [a,b,c] from: // [a, b, c] = someExpression; if (node.parent.kind === SyntaxKind.BinaryExpression && - (node.parent).left === node && + (node.parent).left === node && (node.parent).operatorToken.kind === SyntaxKind.EqualsToken) { return true; } @@ -711,7 +711,7 @@ namespace ts { } function resetWriter() { - displayParts = [] + displayParts = []; lineStart = true; indent = 0; } @@ -768,7 +768,7 @@ namespace ts { } export function textOrKeywordPart(text: string) { - var kind = stringToToken(text); + const kind = stringToToken(text); return kind === undefined ? textPart(text) : keywordPart(kind); diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 0d14113942c..c8e7aa834cc 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -1,12 +1,12 @@ /// -module ts { +namespace ts { interface File { name: string; content: string; } - function createDefaultServerHost(fileMap: Map): server.ServerHost { + function createDefaultServerHost(fileMap: Map): server.ServerHost { let existingDirectories: Map = {}; forEachValue(fileMap, v => { let dir = getDirectoryPath(v.name); @@ -54,12 +54,12 @@ module ts { watchFile: (path, callback) => { return { close: () => { } - } + }; }, watchDirectory: (path, callback, recursive?) => { return { close: () => { } - } + }; }, setTimeout: (callback, ms, ...args) => { return setTimeout(callback, ms, args); @@ -85,8 +85,8 @@ module ts { let projectService = new server.ProjectService(serverHost, logger); let rootScriptInfo = projectService.openFile(rootFile, /* openedByClient */true); let project = projectService.createInferredProject(rootScriptInfo); - project.setProjectOptions( {files: [rootScriptInfo.fileName], compilerOptions: {module: ts.ModuleKind.AMD} } ); - return { + project.setProjectOptions({ files: [rootScriptInfo.fileName], compilerOptions: { module: ts.ModuleKind.AMD } }); + return { project, rootScriptInfo }; @@ -103,22 +103,22 @@ module ts { name: "c:/f1.ts", content: `foo()` }; - + let serverHost = createDefaultServerHost({ [root.name]: root, [imported.name]: imported }); let { project, rootScriptInfo } = createProject(root.name, serverHost); // ensure that imported file was found let diags = project.compilerService.languageService.getSemanticDiagnostics(imported.name); assert.equal(diags.length, 1); - + let originalFileExists = serverHost.fileExists; { // patch fileExists to make sure that disk is not touched serverHost.fileExists = (fileName): boolean => { - assert.isTrue(false, "fileExists should not be called"); + assert.isTrue(false, "fileExists should not be called"); return false; }; - + let newContent = `import {x} from "f1" var x: string = 1;`; rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent); @@ -134,21 +134,20 @@ module ts { return false; } fileExistsIsCalled = true; - assert.isTrue(fileName.indexOf('/f2.') !== -1); + assert.isTrue(fileName.indexOf("/f2.") !== -1); return originalFileExists.call(serverHost, fileName); }; let newContent = `import {x} from "f2"`; rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent); - + try { // trigger synchronization to make sure that LSHost will try to find 'f2' module on disk project.compilerService.languageService.getSemanticDiagnostics(imported.name); - assert.isTrue(false, `should not find file '${imported.name}'`) + assert.isTrue(false, `should not find file '${imported.name}'`); } - catch(e) { + catch (e) { assert.isTrue(e.message.indexOf(`Could not find file: '${imported.name}'.`) === 0); } - assert.isTrue(fileExistsIsCalled); } { @@ -156,45 +155,45 @@ module ts { serverHost.fileExists = (fileName): boolean => { if (fileName === "lib.d.ts") { return false; - } + } fileExistsCalled = true; - assert.isTrue(fileName.indexOf('/f1.') !== -1); + assert.isTrue(fileName.indexOf("/f1.") !== -1); return originalFileExists.call(serverHost, fileName); }; - + let newContent = `import {x} from "f1"`; rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent); project.compilerService.languageService.getSemanticDiagnostics(imported.name); assert.isTrue(fileExistsCalled); - + // setting compiler options discards module resolution cache fileExistsCalled = false; - + let opts = ts.clone(project.projectOptions); opts.compilerOptions = ts.clone(opts.compilerOptions); opts.compilerOptions.target = ts.ScriptTarget.ES5; project.setProjectOptions(opts); - + project.compilerService.languageService.getSemanticDiagnostics(imported.name); assert.isTrue(fileExistsCalled); } }); - + it("loads missing files from disk", () => { let root: File = { - name: 'c:/foo.ts', + name: `c:/foo.ts`, content: `import {x} from "bar"` }; - + let imported: File = { - name: 'c:/bar.d.ts', + name: `c:/bar.d.ts`, content: `export var y = 1` - }; - + }; + let fileMap: Map = { [root.name]: root }; let serverHost = createDefaultServerHost(fileMap); let originalFileExists = serverHost.fileExists; - + let fileExistsCalledForBar = false; serverHost.fileExists = fileName => { if (fileName === "lib.d.ts") { @@ -203,25 +202,25 @@ module ts { if (!fileExistsCalledForBar) { fileExistsCalledForBar = fileName.indexOf("/bar.") !== -1; } - + return originalFileExists.call(serverHost, fileName); }; - + let { project, rootScriptInfo } = createProject(root.name, serverHost); let diags = project.compilerService.languageService.getSemanticDiagnostics(root.name); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); assert.isTrue(diags.length === 1, "one diagnostic expected"); assert.isTrue(typeof diags[0].messageText === "string" && ((diags[0].messageText).indexOf("Cannot find module") === 0), "should be 'cannot find module' message"); - + // assert that import will success once file appear on disk fileMap[imported.name] = imported; fileExistsCalledForBar = false; - rootScriptInfo.editContent(0, rootScriptInfo.content.length, `import {y} from "bar"`) - + rootScriptInfo.editContent(0, rootScriptInfo.content.length, `import {y} from "bar"`); + diags = project.compilerService.languageService.getSemanticDiagnostics(root.name); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); assert.isTrue(diags.length === 0); - }) + }); }); } \ No newline at end of file diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index 4c2b21224c8..131b40278a7 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -1,13 +1,13 @@ /// /// -module ts { +namespace ts { function editFlat(position: number, deletedLength: number, newText: string, source: string) { return source.substring(0, position) + newText + source.substring(position + deletedLength, source.length); } function lineColToPosition(lineIndex: server.LineIndex, line: number, col: number) { - var lineInfo = lineIndex.lineNumberToInfo(line); + const lineInfo = lineIndex.lineNumberToInfo(line); return (lineInfo.offset + col - 1); } @@ -19,9 +19,9 @@ module ts { assert.equal(editedText, checkText); } - describe('VersionCache TS code', () => { + describe(`VersionCache TS code`, () => { let validateEditAtLineCharIndex: (line: number, char: number, deleteLength: number, insertString: string) => void; - + before(() => { let testContent = `/// var x = 10; @@ -32,9 +32,9 @@ class Point { } k=y; var p:Point=new Point(); -var q:Point=p;` +var q:Point=p;`; - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); + let { lines } = server.LineIndex.linesFromText(testContent); assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); let lineIndex = new server.LineIndex(); @@ -48,34 +48,34 @@ var q:Point=p;` after(() => { validateEditAtLineCharIndex = undefined; - }) + }); - it('change 9 1 0 1 {"y"}', () => { + it(`change 9 1 0 1 {"y"}`, () => { validateEditAtLineCharIndex(9, 1, 0, "y"); }); - it('change 9 2 0 1 {"."}', () => { + it(`change 9 2 0 1 {"."}`, () => { validateEditAtLineCharIndex(9, 2, 0, "."); }); - it('change 9 3 0 1 {"\\n"}', () => { + it(`change 9 3 0 1 {"\\n"}`, () => { validateEditAtLineCharIndex(9, 3, 0, "\n"); }); - it('change 10 1 0 10 {"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"}', () => { + it(`change 10 1 0 10 {"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"}`, () => { validateEditAtLineCharIndex(10, 1, 0, "\n\n\n\n\n\n\n\n\n\n"); }); - it('change 19 1 1 0', () => { + it(`change 19 1 1 0`, () => { validateEditAtLineCharIndex(19, 1, 1, ""); }); - it('change 18 1 1 0', () => { + it(`change 18 1 1 0`, () => { validateEditAtLineCharIndex(18, 1, 1, ""); }); }); - describe('VersionCache simple text', () => { + describe(`VersionCache simple text`, () => { let validateEditAtPosition: (position: number, deleteLength: number, insertString: string) => void; let testContent: string; let lines: string[]; @@ -88,7 +88,7 @@ that ate the grass that was purple at the tips and grew 1cm per day`; - ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + ({ lines, lineMap } = server.LineIndex.linesFromText(testContent)); assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); let lineIndex = new server.LineIndex(); @@ -96,90 +96,90 @@ and grew 1cm per day`; validateEditAtPosition = (position: number, deleteLength: number, insertString: string) => { validateEdit(lineIndex, testContent, position, deleteLength, insertString); - } + }; }); after(() => { - validateEditAtPosition = undefined; - testContent = undefined; - lines = undefined; - lineMap = undefined; + validateEditAtPosition = undefined; + testContent = undefined; + lines = undefined; + lineMap = undefined; }); - it('Insert at end of file', () => { + it(`Insert at end of file`, () => { validateEditAtPosition(testContent.length, 0, "hmmmm...\r\n"); }); - it('Unusual line endings merge', () => { + it(`Unusual line endings merge`, () => { validateEditAtPosition(lines[0].length - 1, lines[1].length, ""); }); - it('Delete whole line and nothing but line (last line)', () => { + it(`Delete whole line and nothing but line (last line)`, () => { validateEditAtPosition(lineMap[lineMap.length - 2], lines[lines.length - 1].length, ""); }); - it('Delete whole line and nothing but line (first line)', () => { + it(`Delete whole line and nothing but line (first line)`, () => { validateEditAtPosition(0, lines[0].length, ""); }); - it('Delete whole line (first line) and insert with no line breaks', () => { + it(`Delete whole line (first line) and insert with no line breaks`, () => { validateEditAtPosition(0, lines[0].length, "moo, moo, moo! "); }); - it('Delete whole line (first line) and insert with multiple line breaks', () => { + it(`Delete whole line (first line) and insert with multiple line breaks`, () => { validateEditAtPosition(0, lines[0].length, "moo, \r\nmoo, \r\nmoo! "); }); - it('Delete multiple lines and nothing but lines (first and second lines)', () => { + it(`Delete multiple lines and nothing but lines (first and second lines)`, () => { validateEditAtPosition(0, lines[0].length + lines[1].length, ""); }); - it('Delete multiple lines and nothing but lines (second and third lines)', () => { + it(`Delete multiple lines and nothing but lines (second and third lines)`, () => { validateEditAtPosition(lines[0].length, lines[1].length + lines[2].length, ""); }); - it('Insert multiple line breaks', () => { + it(`Insert multiple line breaks`, () => { validateEditAtPosition(21, 1, "cr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr"); }); - it('Insert multiple line breaks', () => { + it(`Insert multiple line breaks`, () => { validateEditAtPosition(21, 1, "cr...\r\ncr...\r\ncr"); }); - it('Insert multiple line breaks with leading \\n', () => { + it(`Insert multiple line breaks with leading \\n`, () => { validateEditAtPosition(21, 1, "\ncr...\r\ncr...\r\ncr"); }); - it('Single line no line breaks deleted or inserted, delete 1 char', () => { + it(`Single line no line breaks deleted or inserted, delete 1 char`, () => { validateEditAtPosition(21, 1, ""); }); - it('Single line no line breaks deleted or inserted, insert 1 char', () => { + it(`Single line no line breaks deleted or inserted, insert 1 char`, () => { validateEditAtPosition(21, 0, "b"); }); - it('Single line no line breaks deleted or inserted, delete 1, insert 2 chars', () => { + it(`Single line no line breaks deleted or inserted, delete 1, insert 2 chars`, () => { validateEditAtPosition(21, 1, "cr"); }); - it('Delete across line break (just the line break)', () => { + it(`Delete across line break (just the line break)`, () => { validateEditAtPosition(21, 22, ""); }); - it('Delete across line break', () => { + it(`Delete across line break`, () => { validateEditAtPosition(21, 32, ""); }); - it('Delete across multiple line breaks and insert no line breaks', () => { + it(`Delete across multiple line breaks and insert no line breaks`, () => { validateEditAtPosition(21, 42, ""); }); - it('Delete across multiple line breaks and insert text', () => { + it(`Delete across multiple line breaks and insert text`, () => { validateEditAtPosition(21, 42, "slithery "); }); }); - describe('VersionCache stress test', () => { + describe(`VersionCache stress test`, () => { let rsa: number[] = []; let la: number[] = []; let las: number[] = []; @@ -187,7 +187,7 @@ and grew 1cm per day`; let ersa: number[] = []; let ela: number[] = []; const iterationCount = 20; - //const iterationCount = 20000; // uncomment for testing + // const iterationCount = 20000; // uncomment for testing let lines: string[]; let lineMap: number[]; let lineIndex: server.LineIndex; @@ -200,7 +200,7 @@ and grew 1cm per day`; let totalChars = testContent.length; assert.isTrue(totalChars > 0, "Failed to read test file."); - ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + ({ lines, lineMap } = server.LineIndex.linesFromText(testContent)); assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); lineIndex = new server.LineIndex(); @@ -316,4 +316,4 @@ and grew 1cm per day`; } }); }); -} +} \ No newline at end of file From 1f88cd6f06f6b8e4c59de028ed83c3ce118459f0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 13:32:27 -0700 Subject: [PATCH 4/6] Change name of the output file --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 2424c414389..eb427107010 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -525,7 +525,7 @@ compileFile(servicesFileInBrowserTest, servicesSources,[builtLocalDirectory, cop var serverFile = path.join(builtLocalDirectory, "tsserver.js"); compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true); -var tsserverLibraryFile = path.join(builtLocalDirectory, "tslssl.js"); +var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js"); compileFile( tsserverLibraryFile, languageServiceLibrarySources, From 75fa7b174c93de7b3e59634979fd2446737023ab Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 15:55:18 -0700 Subject: [PATCH 5/6] Code review comments --- tests/cases/unittests/cachingInServerLSHost.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index c8e7aa834cc..17de3c6de02 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -61,12 +61,8 @@ namespace ts { close: () => { } }; }, - setTimeout: (callback, ms, ...args) => { - return setTimeout(callback, ms, args); - }, - clearTimeout: (timeoutId) => { - clearTimeout(timeoutId); - } + setTimeout, + clearTimeout }; } From c9b5145ed9e4ab6ca42db6e416fcf6a6323c4c7b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 19 May 2016 15:55:42 -0700 Subject: [PATCH 6/6] Remove use of ts.sys in editor services --- src/server/editorServices.ts | 40 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 793e17d52e7..948a2982a5f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -32,7 +32,7 @@ namespace ts.server { children: ScriptInfo[] = []; // files referenced by this file defaultProject: Project; // project to use by default for file fileWatcher: FileWatcher; - formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions); + formatCodeOptions = ts.clone(CompilerService.getDefaultFormatCodeOptions(this.host)); path: Path; scriptKind: ScriptKind; @@ -542,7 +542,7 @@ namespace ts.server { addDefaultHostConfiguration() { this.hostConfiguration = { - formatCodeOptions: ts.clone(CompilerService.defaultFormatCodeOptions), + formatCodeOptions: ts.clone(CompilerService.getDefaultFormatCodeOptions(this.host)), hostInfo: "Unknown host" }; } @@ -1377,23 +1377,25 @@ namespace ts.server { return ts.isExternalModule(sourceFile); } - static defaultFormatCodeOptions: ts.FormatCodeOptions = { - IndentSize: 4, - TabSize: 4, - NewLineCharacter: ts.sys ? ts.sys.newLine : "\n", - ConvertTabsToSpaces: true, - IndentStyle: ts.IndentStyle.Smart, - InsertSpaceAfterCommaDelimiter: true, - InsertSpaceAfterSemicolonInForStatements: true, - InsertSpaceBeforeAndAfterBinaryOperators: true, - InsertSpaceAfterKeywordsInControlFlowStatements: true, - InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, - InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, - InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, - InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, - PlaceOpenBraceOnNewLineForFunctions: false, - PlaceOpenBraceOnNewLineForControlBlocks: false, - }; + static getDefaultFormatCodeOptions(host: ServerHost): ts.FormatCodeOptions { + return ts.clone({ + IndentSize: 4, + TabSize: 4, + NewLineCharacter: host.newLine || "\n", + ConvertTabsToSpaces: true, + IndentStyle: ts.IndentStyle.Smart, + InsertSpaceAfterCommaDelimiter: true, + InsertSpaceAfterSemicolonInForStatements: true, + InsertSpaceBeforeAndAfterBinaryOperators: true, + InsertSpaceAfterKeywordsInControlFlowStatements: true, + InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, + InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, + PlaceOpenBraceOnNewLineForFunctions: false, + PlaceOpenBraceOnNewLineForControlBlocks: false, + }); + } } export interface LineCollection {