Merge pull request #8700 from Microsoft/Fix8692
Fix #8692: fix "tsserver as a library" (lssl) build target
This commit is contained in:
commit
b637d76b49
74
Jakefile.js
74
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, "tsserverlibrary.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");
|
||||
|
@ -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, 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;
|
||||
|
@ -765,8 +765,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");
|
||||
|
@ -778,7 +778,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;
|
||||
|
@ -792,13 +792,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.");
|
||||
}
|
||||
|
@ -827,11 +827,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);
|
||||
|
@ -910,14 +910,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");
|
||||
});
|
||||
|
@ -942,7 +942,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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -533,7 +533,7 @@ namespace ts.server {
|
|||
// number becomes 0 for a watcher, then we should close it.
|
||||
directoryWatchersRefCount: ts.Map<number> = {};
|
||||
hostConfiguration: HostConfiguration;
|
||||
timerForDetectingProjectFileListChanges: Map<NodeJS.Timer> = {};
|
||||
timerForDetectingProjectFileListChanges: Map<any> = {};
|
||||
|
||||
constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) {
|
||||
// ts.disableIncrementalParsing = true;
|
||||
|
@ -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"
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -1382,23 +1382,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 {
|
||||
|
|
|
@ -266,16 +266,21 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
const sys = <ServerHost>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");
|
||||
});
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Node> {
|
||||
|
@ -629,7 +629,7 @@ namespace ts {
|
|||
// [a,b,c] from:
|
||||
// [a, b, c] = someExpression;
|
||||
if (node.parent.kind === SyntaxKind.BinaryExpression &&
|
||||
(<BinaryExpression>node.parent).left === node &&
|
||||
(<BinaryExpression>node.parent).left === node &&
|
||||
(<BinaryExpression>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);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
interface File {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
|
||||
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
|
||||
let existingDirectories: Map<boolean> = {};
|
||||
forEachValue(fileMap, v => {
|
||||
let dir = getDirectoryPath(v.name);
|
||||
|
@ -54,13 +54,15 @@ module ts {
|
|||
watchFile: (path, callback) => {
|
||||
return {
|
||||
close: () => { }
|
||||
}
|
||||
};
|
||||
},
|
||||
watchDirectory: (path, callback, recursive?) => {
|
||||
return {
|
||||
close: () => { }
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
setTimeout,
|
||||
clearTimeout
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -79,8 +81,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
|
||||
};
|
||||
|
@ -97,22 +99,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);
|
||||
|
@ -128,21 +130,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);
|
||||
}
|
||||
{
|
||||
|
@ -150,45 +151,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<File> = { [root.name]: root };
|
||||
let serverHost = createDefaultServerHost(fileMap);
|
||||
let originalFileExists = serverHost.fileExists;
|
||||
|
||||
|
||||
let fileExistsCalledForBar = false;
|
||||
serverHost.fileExists = fileName => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
|
@ -197,25 +198,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" && ((<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);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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 {},
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
/// <reference path="..\..\..\src\server\editorServices.ts" />
|
||||
|
||||
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 = `/// <reference path="z.ts" />
|
||||
var x = 10;
|
||||
|
@ -32,9 +32,9 @@ class Point {
|
|||
}
|
||||
k=y;
|
||||
var p:Point=new Point();
|
||||
var q:Point=<Point>p;`
|
||||
var q:Point=<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=<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();
|
||||
|
@ -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(<server.ServerHost>ts.sys, testContent);
|
||||
let checkText = testContent;
|
||||
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
|
@ -316,4 +316,4 @@ and grew 1cm per day`;
|
|||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue