From 94b4f8b79e370020cb31995e8fb0b78f9ba94349 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 22 Sep 2017 12:55:18 -0700 Subject: [PATCH] Update LKG --- lib/tsc.js | 15 ++-- lib/tsserver.js | 174 +++++++++++++++++++++++++------------- lib/tsserverlibrary.js | 170 +++++++++++++++++++++++++------------ lib/typescript.js | 158 +++++++++++++++++++++------------- lib/typescriptServices.js | 158 +++++++++++++++++++++------------- lib/typingsInstaller.js | 15 ++-- 6 files changed, 450 insertions(+), 240 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 2a142736d66..5e76fb39a4d 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -2199,6 +2199,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); var ts; (function (ts) { @@ -18064,17 +18066,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache); diff --git a/lib/tsserver.js b/lib/tsserver.js index 75b0c16a3a3..07dff6dd32d 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -3232,6 +3232,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); var ts; (function (ts) { @@ -5232,17 +5234,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache); @@ -74601,7 +74606,7 @@ var ts; Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); Messages.TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); Messages.FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); - Messages.InsufficientSelection = createMessage("Select more than a single token."); + Messages.InsufficientSelection = createMessage("Select more than a single identifier."); Messages.CannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); Messages.CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns"); Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); @@ -74618,6 +74623,9 @@ var ts; })(RangeFacts || (RangeFacts = {})); function getRangeToExtract(sourceFile, span) { var length = span.length || 0; + if (length === 0) { + return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] }; + } var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span); var end = getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span); var declarations = []; @@ -74666,7 +74674,7 @@ var ts; return { errors: [ts.createFileDiagnostic(sourceFile, start, length, message)] }; } function checkRootNode(node) { - if (ts.isToken(ts.isExpressionStatement(node) ? node.expression : node)) { + if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) { return [ts.createDiagnosticForNode(node, Messages.InsufficientSelection)]; } return undefined; @@ -74759,39 +74767,26 @@ var ts; return false; } var savedPermittedJumps = permittedJumps; - if (node.parent) { - switch (node.parent.kind) { - case 211: - if (node.parent.thenStatement === node || node.parent.elseStatement === node) { - permittedJumps = 0; - } - break; - case 224: - if (node.parent.tryBlock === node) { - permittedJumps = 0; - } - else if (node.parent.finallyBlock === node) { - permittedJumps = 4; - } - break; - case 260: - if (node.parent.block === node) { - permittedJumps = 0; - } - break; - case 257: - if (node.expression !== node) { - permittedJumps |= 1; - } - break; - default: - if (ts.isIterationStatement(node.parent, false)) { - if (node.parent.statement === node) { - permittedJumps |= 1 | 2; - } - } - break; - } + switch (node.kind) { + case 211: + permittedJumps = 0; + break; + case 224: + permittedJumps = 0; + break; + case 207: + if (node.parent && node.parent.kind === 224 && node.finallyBlock === node) { + permittedJumps = 4; + } + break; + case 257: + permittedJumps |= 1; + break; + default: + if (ts.isIterationStatement(node, false)) { + permittedJumps |= 1 | 2; + } + break; } switch (node.kind) { case 169: @@ -74816,7 +74811,7 @@ var ts; } } else { - if (!(permittedJumps & (218 ? 1 : 2))) { + if (!(permittedJumps & (node.kind === 218 ? 1 : 2))) { (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } @@ -74934,7 +74929,7 @@ var ts; else if (ts.isClassLike(scope)) { return scope.kind === 229 ? "class '" + scope.name.text + "'" - : scope.name.text + : scope.name && scope.name.text ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } @@ -74991,13 +74986,20 @@ var ts; if (range.facts & RangeFacts.IsAsyncFunction) { modifiers.push(ts.createToken(120)); } - newFunction = ts.createMethod(undefined, modifiers, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, undefined, parameters, returnType, body); + newFunction = ts.createMethod(undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, undefined, parameters, returnType, body); } else { newFunction = ts.createFunctionDeclaration(undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context); - changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + var minInsertionPos = (isReadonlyArray(range.range) ? ts.lastOrUndefined(range.range) : range.range).end; + var nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope); + if (nodeToInsertBefore) { + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + else { + changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + } var newNodes = []; var called = getCalledExpression(scope, range, functionNameText); var call = ts.createCall(called, undefined, callArguments); @@ -75021,6 +75023,9 @@ var ts; } else { newNodes.push(ts.createStatement(ts.createBinary(assignments[0].name, 58, call))); + if (range.facts & RangeFacts.HasReturn) { + newNodes.push(ts.createReturn()); + } } } else { @@ -75055,6 +75060,33 @@ var ts; var renameFilename = renameRange.getSourceFile().fileName; var renameLocation = getRenameLocation(edits, renameFilename, functionNameText); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; + function getStatementsOrClassElements(scope) { + if (ts.isFunctionLike(scope)) { + var body_1 = scope.body; + if (ts.isBlock(body_1)) { + return body_1.statements; + } + } + else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) { + return scope.statements; + } + else if (ts.isClassLike(scope)) { + return scope.members; + } + else { + ts.assertTypeIsNever(scope); + } + return ts.emptyArray; + } + function getNodeToInsertBefore(minPos, scope) { + var children = getStatementsOrClassElements(scope); + for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { + var child = children_3[_i]; + if (child.pos >= minPos && ts.isFunctionLike(child) && !ts.isConstructorDeclaration(child)) { + return child; + } + } + } } function getRenameLocation(edits, renameFilename, functionNameText) { var delta = 0; @@ -75088,6 +75120,7 @@ var ts; return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined }; } var returnValueProperty; + var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); if (writes || substitutions.size) { var rewrittenStatements = ts.visitNodes(statements, visitor).slice(); @@ -75106,7 +75139,7 @@ var ts; return { body: ts.createBlock(statements, true), returnValueProperty: undefined }; } function visitor(node) { - if (node.kind === 219 && writes) { + if (!ignoreReturns && node.kind === 219 && writes) { var assignments = getPropertyAssignmentsForWrites(writes); if (node.expression) { if (!returnValueProperty) { @@ -75122,8 +75155,12 @@ var ts; } } else { + var oldIgnoreReturns = ignoreReturns; + ignoreReturns = ignoreReturns || ts.isFunctionLike(node) || ts.isClassLike(node); var substitution = substitutions.get(ts.getNodeId(node).toString()); - return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + var result = substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + ignoreReturns = oldIgnoreReturns; + return result; } } } @@ -75228,7 +75265,9 @@ var ts; } } function recordUsagebySymbol(identifier, usage, isTypeName) { - var symbol = checker.getSymbolAtLocation(identifier); + var symbol = identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); if (!symbol) { return undefined; } @@ -75252,7 +75291,7 @@ var ts; if (!declInFile) { return undefined; } - if (ts.rangeContainsRange(enclosingTextRange, declInFile)) { + if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { return undefined; } if (targetRange.facts & RangeFacts.IsGenerator && usage === 2) { @@ -75447,9 +75486,9 @@ var ts; return; } if (ts.isJSDocCommentContainingNode(this)) { - var children_3 = []; - this.forEachChild(function (child) { children_3.push(child); }); - this._children = children_3; + var children_4 = []; + this.forEachChild(function (child) { children_4.push(child); }); + this._children = children_4; return; } var children = []; @@ -79377,7 +79416,8 @@ var ts; return { info: info, projectErrors: this.getGlobalProjectErrors() }; } var lastReportedFileNames_1 = this.lastReportedFileNames; - var currentFiles_1 = ts.arrayToSet(this.getFileNames()); + var externalFiles = this.getExternalFiles().map(function (f) { return server.toNormalizedPath(f); }); + var currentFiles_1 = ts.arrayToSet(this.getFileNames().concat(externalFiles)); var added_1 = []; var removed_1 = []; var updated = updatedFileNames ? ts.arrayFrom(updatedFileNames.keys()) : []; @@ -79397,9 +79437,11 @@ var ts; } else { var projectFileNames = this.getFileNames(); - this.lastReportedFileNames = ts.arrayToSet(projectFileNames); + var externalFiles = this.getExternalFiles().map(function (f) { return server.toNormalizedPath(f); }); + var allFiles = projectFileNames.concat(externalFiles); + this.lastReportedFileNames = ts.arrayToSet(allFiles); this.lastReportedVersion = this.projectStructureVersion; - return { info: info, files: projectFileNames, projectErrors: this.getGlobalProjectErrors() }; + return { info: info, files: allFiles, projectErrors: this.getGlobalProjectErrors() }; } }; Project.prototype.getReferencedFiles = function (path) { @@ -79565,8 +79607,11 @@ var ts; } if (this.projectService.globalPlugins) { var _loop_10 = function (globalPluginName) { + if (!globalPluginName) + return "continue"; if (options.plugins && options.plugins.some(function (p) { return p.name === globalPluginName; })) return "continue"; + this_2.projectService.logger.info("Loading global plugin " + globalPluginName); this_2.enablePlugin({ name: globalPluginName, global: true }, searchPaths); }; var this_2 = this; @@ -79578,6 +79623,7 @@ var ts; }; ConfiguredProject.prototype.enablePlugin = function (pluginConfigEntry, searchPaths) { var _this = this; + this.projectService.logger.info("Enabling plugin " + pluginConfigEntry.name + " from candidate paths: " + searchPaths.join(",")); var log = function (message) { _this.projectService.logger.info(message); }; @@ -79589,7 +79635,7 @@ var ts; return; } } - this.projectService.logger.info("Couldn't find " + pluginConfigEntry.name + " anywhere in paths: " + searchPaths.join(",")); + this.projectService.logger.info("Couldn't find " + pluginConfigEntry.name); }; ConfiguredProject.prototype.enableProxy = function (pluginModuleFactory, configEntry) { try { @@ -79605,7 +79651,16 @@ var ts; serverHost: this.projectService.host }; var pluginModule = pluginModuleFactory({ typescript: ts }); - this.languageService = pluginModule.create(info); + var newLS = pluginModule.create(info); + for (var _i = 0, _a = Object.keys(this.languageService); _i < _a.length; _i++) { + var k = _a[_i]; + if (!(k in newLS)) { + this.projectService.logger.info("Plugin activation warning: Missing proxied method " + k + " in created LS. Patching."); + newLS[k] = this.languageService[k]; + } + } + this.projectService.logger.info("Plugin validation succeded"); + this.languageService = newLS; this.plugins.push(pluginModule); } catch (e) { @@ -79634,6 +79689,9 @@ var ts; } catch (e) { _this.projectService.logger.info("A plugin threw an exception in getExternalFiles: " + e); + if (e.stack) { + _this.projectService.logger.info(e.stack); + } } })); }; @@ -83796,7 +83854,7 @@ var ts; return; } if (this.telemetryEnabled) { - var body_1 = { + var body_2 = { telemetryEventName: "typingsInstalled", payload: { installedPackages: response.packagesToInstall.join(","), @@ -83805,7 +83863,7 @@ var ts; } }; var eventName_1 = "telemetry"; - this.eventSender.event(body_1, eventName_1); + this.eventSender.event(body_2, eventName_1); } var body = { eventId: response.eventId, diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index d015bf7a597..9401638a260 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -3232,6 +3232,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); var ts; (function (ts) { @@ -18256,17 +18258,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache); @@ -74601,7 +74606,7 @@ var ts; Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); Messages.TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); Messages.FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); - Messages.InsufficientSelection = createMessage("Select more than a single token."); + Messages.InsufficientSelection = createMessage("Select more than a single identifier."); Messages.CannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); Messages.CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns"); Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); @@ -74618,6 +74623,9 @@ var ts; })(RangeFacts || (RangeFacts = {})); function getRangeToExtract(sourceFile, span) { var length = span.length || 0; + if (length === 0) { + return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] }; + } var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span); var end = getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span); var declarations = []; @@ -74666,7 +74674,7 @@ var ts; return { errors: [ts.createFileDiagnostic(sourceFile, start, length, message)] }; } function checkRootNode(node) { - if (ts.isToken(ts.isExpressionStatement(node) ? node.expression : node)) { + if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) { return [ts.createDiagnosticForNode(node, Messages.InsufficientSelection)]; } return undefined; @@ -74759,39 +74767,26 @@ var ts; return false; } var savedPermittedJumps = permittedJumps; - if (node.parent) { - switch (node.parent.kind) { - case 211: - if (node.parent.thenStatement === node || node.parent.elseStatement === node) { - permittedJumps = 0; - } - break; - case 224: - if (node.parent.tryBlock === node) { - permittedJumps = 0; - } - else if (node.parent.finallyBlock === node) { - permittedJumps = 4; - } - break; - case 260: - if (node.parent.block === node) { - permittedJumps = 0; - } - break; - case 257: - if (node.expression !== node) { - permittedJumps |= 1; - } - break; - default: - if (ts.isIterationStatement(node.parent, false)) { - if (node.parent.statement === node) { - permittedJumps |= 1 | 2; - } - } - break; - } + switch (node.kind) { + case 211: + permittedJumps = 0; + break; + case 224: + permittedJumps = 0; + break; + case 207: + if (node.parent && node.parent.kind === 224 && node.finallyBlock === node) { + permittedJumps = 4; + } + break; + case 257: + permittedJumps |= 1; + break; + default: + if (ts.isIterationStatement(node, false)) { + permittedJumps |= 1 | 2; + } + break; } switch (node.kind) { case 169: @@ -74816,7 +74811,7 @@ var ts; } } else { - if (!(permittedJumps & (218 ? 1 : 2))) { + if (!(permittedJumps & (node.kind === 218 ? 1 : 2))) { (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } @@ -74934,7 +74929,7 @@ var ts; else if (ts.isClassLike(scope)) { return scope.kind === 229 ? "class '" + scope.name.text + "'" - : scope.name.text + : scope.name && scope.name.text ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } @@ -74991,13 +74986,20 @@ var ts; if (range.facts & RangeFacts.IsAsyncFunction) { modifiers.push(ts.createToken(120)); } - newFunction = ts.createMethod(undefined, modifiers, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, undefined, parameters, returnType, body); + newFunction = ts.createMethod(undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, undefined, parameters, returnType, body); } else { newFunction = ts.createFunctionDeclaration(undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context); - changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + var minInsertionPos = (isReadonlyArray(range.range) ? ts.lastOrUndefined(range.range) : range.range).end; + var nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope); + if (nodeToInsertBefore) { + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + else { + changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + } var newNodes = []; var called = getCalledExpression(scope, range, functionNameText); var call = ts.createCall(called, undefined, callArguments); @@ -75021,6 +75023,9 @@ var ts; } else { newNodes.push(ts.createStatement(ts.createBinary(assignments[0].name, 58, call))); + if (range.facts & RangeFacts.HasReturn) { + newNodes.push(ts.createReturn()); + } } } else { @@ -75055,6 +75060,33 @@ var ts; var renameFilename = renameRange.getSourceFile().fileName; var renameLocation = getRenameLocation(edits, renameFilename, functionNameText); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; + function getStatementsOrClassElements(scope) { + if (ts.isFunctionLike(scope)) { + var body_1 = scope.body; + if (ts.isBlock(body_1)) { + return body_1.statements; + } + } + else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) { + return scope.statements; + } + else if (ts.isClassLike(scope)) { + return scope.members; + } + else { + ts.assertTypeIsNever(scope); + } + return ts.emptyArray; + } + function getNodeToInsertBefore(minPos, scope) { + var children = getStatementsOrClassElements(scope); + for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { + var child = children_3[_i]; + if (child.pos >= minPos && ts.isFunctionLike(child) && !ts.isConstructorDeclaration(child)) { + return child; + } + } + } } function getRenameLocation(edits, renameFilename, functionNameText) { var delta = 0; @@ -75088,6 +75120,7 @@ var ts; return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined }; } var returnValueProperty; + var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); if (writes || substitutions.size) { var rewrittenStatements = ts.visitNodes(statements, visitor).slice(); @@ -75106,7 +75139,7 @@ var ts; return { body: ts.createBlock(statements, true), returnValueProperty: undefined }; } function visitor(node) { - if (node.kind === 219 && writes) { + if (!ignoreReturns && node.kind === 219 && writes) { var assignments = getPropertyAssignmentsForWrites(writes); if (node.expression) { if (!returnValueProperty) { @@ -75122,8 +75155,12 @@ var ts; } } else { + var oldIgnoreReturns = ignoreReturns; + ignoreReturns = ignoreReturns || ts.isFunctionLike(node) || ts.isClassLike(node); var substitution = substitutions.get(ts.getNodeId(node).toString()); - return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + var result = substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + ignoreReturns = oldIgnoreReturns; + return result; } } } @@ -75228,7 +75265,9 @@ var ts; } } function recordUsagebySymbol(identifier, usage, isTypeName) { - var symbol = checker.getSymbolAtLocation(identifier); + var symbol = identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); if (!symbol) { return undefined; } @@ -75252,7 +75291,7 @@ var ts; if (!declInFile) { return undefined; } - if (ts.rangeContainsRange(enclosingTextRange, declInFile)) { + if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { return undefined; } if (targetRange.facts & RangeFacts.IsGenerator && usage === 2) { @@ -75447,9 +75486,9 @@ var ts; return; } if (ts.isJSDocCommentContainingNode(this)) { - var children_3 = []; - this.forEachChild(function (child) { children_3.push(child); }); - this._children = children_3; + var children_4 = []; + this.forEachChild(function (child) { children_4.push(child); }); + this._children = children_4; return; } var children = []; @@ -81115,7 +81154,8 @@ var ts; return { info: info, projectErrors: this.getGlobalProjectErrors() }; } var lastReportedFileNames_1 = this.lastReportedFileNames; - var currentFiles_1 = ts.arrayToSet(this.getFileNames()); + var externalFiles = this.getExternalFiles().map(function (f) { return server.toNormalizedPath(f); }); + var currentFiles_1 = ts.arrayToSet(this.getFileNames().concat(externalFiles)); var added_1 = []; var removed_1 = []; var updated = updatedFileNames ? ts.arrayFrom(updatedFileNames.keys()) : []; @@ -81135,9 +81175,11 @@ var ts; } else { var projectFileNames = this.getFileNames(); - this.lastReportedFileNames = ts.arrayToSet(projectFileNames); + var externalFiles = this.getExternalFiles().map(function (f) { return server.toNormalizedPath(f); }); + var allFiles = projectFileNames.concat(externalFiles); + this.lastReportedFileNames = ts.arrayToSet(allFiles); this.lastReportedVersion = this.projectStructureVersion; - return { info: info, files: projectFileNames, projectErrors: this.getGlobalProjectErrors() }; + return { info: info, files: allFiles, projectErrors: this.getGlobalProjectErrors() }; } }; Project.prototype.getReferencedFiles = function (path) { @@ -81303,8 +81345,11 @@ var ts; } if (this.projectService.globalPlugins) { var _loop_10 = function (globalPluginName) { + if (!globalPluginName) + return "continue"; if (options.plugins && options.plugins.some(function (p) { return p.name === globalPluginName; })) return "continue"; + this_2.projectService.logger.info("Loading global plugin " + globalPluginName); this_2.enablePlugin({ name: globalPluginName, global: true }, searchPaths); }; var this_2 = this; @@ -81316,6 +81361,7 @@ var ts; }; ConfiguredProject.prototype.enablePlugin = function (pluginConfigEntry, searchPaths) { var _this = this; + this.projectService.logger.info("Enabling plugin " + pluginConfigEntry.name + " from candidate paths: " + searchPaths.join(",")); var log = function (message) { _this.projectService.logger.info(message); }; @@ -81327,7 +81373,7 @@ var ts; return; } } - this.projectService.logger.info("Couldn't find " + pluginConfigEntry.name + " anywhere in paths: " + searchPaths.join(",")); + this.projectService.logger.info("Couldn't find " + pluginConfigEntry.name); }; ConfiguredProject.prototype.enableProxy = function (pluginModuleFactory, configEntry) { try { @@ -81343,7 +81389,16 @@ var ts; serverHost: this.projectService.host }; var pluginModule = pluginModuleFactory({ typescript: ts }); - this.languageService = pluginModule.create(info); + var newLS = pluginModule.create(info); + for (var _i = 0, _a = Object.keys(this.languageService); _i < _a.length; _i++) { + var k = _a[_i]; + if (!(k in newLS)) { + this.projectService.logger.info("Plugin activation warning: Missing proxied method " + k + " in created LS. Patching."); + newLS[k] = this.languageService[k]; + } + } + this.projectService.logger.info("Plugin validation succeded"); + this.languageService = newLS; this.plugins.push(pluginModule); } catch (e) { @@ -81372,6 +81427,9 @@ var ts; } catch (e) { _this.projectService.logger.info("A plugin threw an exception in getExternalFiles: " + e); + if (e.stack) { + _this.projectService.logger.info(e.stack); + } } })); }; diff --git a/lib/typescript.js b/lib/typescript.js index 44aae64f310..90b6c8036ab 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -3718,6 +3718,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); /// var ts; @@ -22430,17 +22432,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); @@ -89584,7 +89589,7 @@ var ts; Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); Messages.TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); Messages.FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); - Messages.InsufficientSelection = createMessage("Select more than a single token."); + Messages.InsufficientSelection = createMessage("Select more than a single identifier."); Messages.CannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); Messages.CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns"); Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); @@ -89611,6 +89616,9 @@ var ts; // exported only for tests function getRangeToExtract(sourceFile, span) { var length = span.length || 0; + if (length === 0) { + return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] }; + } // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. // This may fail (e.g. you select two statements in the root of a source file) var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span); @@ -89683,7 +89691,7 @@ var ts; return { errors: [ts.createFileDiagnostic(sourceFile, start, length, message)] }; } function checkRootNode(node) { - if (ts.isToken(ts.isExpressionStatement(node) ? node.expression : node)) { + if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) { return [ts.createDiagnosticForNode(node, Messages.InsufficientSelection)]; } return undefined; @@ -89785,45 +89793,30 @@ var ts; return false; } var savedPermittedJumps = permittedJumps; - if (node.parent) { - switch (node.parent.kind) { - case 211 /* IfStatement */: - if (node.parent.thenStatement === node || node.parent.elseStatement === node) { - // forbid all jumps inside thenStatement or elseStatement - permittedJumps = 0 /* None */; - } - break; - case 224 /* TryStatement */: - if (node.parent.tryBlock === node) { - // forbid all jumps inside try blocks - permittedJumps = 0 /* None */; - } - else if (node.parent.finallyBlock === node) { - // allow unconditional returns from finally blocks - permittedJumps = 4 /* Return */; - } - break; - case 260 /* CatchClause */: - if (node.parent.block === node) { - // forbid all jumps inside the block of catch clause - permittedJumps = 0 /* None */; - } - break; - case 257 /* CaseClause */: - if (node.expression !== node) { - // allow unlabeled break inside case clauses - permittedJumps |= 1 /* Break */; - } - break; - default: - if (ts.isIterationStatement(node.parent, /*lookInLabeledStatements*/ false)) { - if (node.parent.statement === node) { - // allow unlabeled break/continue inside loops - permittedJumps |= 1 /* Break */ | 2 /* Continue */; - } - } - break; - } + switch (node.kind) { + case 211 /* IfStatement */: + permittedJumps = 0 /* None */; + break; + case 224 /* TryStatement */: + // forbid all jumps inside try blocks + permittedJumps = 0 /* None */; + break; + case 207 /* Block */: + if (node.parent && node.parent.kind === 224 /* TryStatement */ && node.finallyBlock === node) { + // allow unconditional returns from finally blocks + permittedJumps = 4 /* Return */; + } + break; + case 257 /* CaseClause */: + // allow unlabeled break inside case clauses + permittedJumps |= 1 /* Break */; + break; + default: + if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { + // allow unlabeled break/continue inside loops + permittedJumps |= 1 /* Break */ | 2 /* Continue */; + } + break; } switch (node.kind) { case 169 /* ThisType */: @@ -89849,7 +89842,7 @@ var ts; } } else { - if (!(permittedJumps & (218 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { + if (!(permittedJumps & (node.kind === 218 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { // attempt to break or continue in a forbidden context (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements)); } @@ -89994,7 +89987,7 @@ var ts; else if (ts.isClassLike(scope)) { return scope.kind === 229 /* ClassDeclaration */ ? "class '" + scope.name.text + "'" - : scope.name.text + : scope.name && scope.name.text ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } @@ -90066,7 +90059,7 @@ var ts; modifiers.push(ts.createToken(120 /* AsyncKeyword */)); } newFunction = ts.createMethod( - /*decorators*/ undefined, modifiers, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, + /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, /*questionToken*/ undefined, /*typeParameters*/ undefined, parameters, returnType, body); } @@ -90076,8 +90069,14 @@ var ts; /*typeParameters*/ undefined, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context); - // insert function at the end of the scope - changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + var minInsertionPos = (isReadonlyArray(range.range) ? ts.lastOrUndefined(range.range) : range.range).end; + var nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope); + if (nodeToInsertBefore) { + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + else { + changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + } var newNodes = []; // replace range with function call var called = getCalledExpression(scope, range, functionNameText); @@ -90106,6 +90105,9 @@ var ts; } else { newNodes.push(ts.createStatement(ts.createBinary(assignments[0].name, 58 /* EqualsToken */, call))); + if (range.facts & RangeFacts.HasReturn) { + newNodes.push(ts.createReturn()); + } } } else { @@ -90143,6 +90145,37 @@ var ts; var renameFilename = renameRange.getSourceFile().fileName; var renameLocation = getRenameLocation(edits, renameFilename, functionNameText); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; + function getStatementsOrClassElements(scope) { + if (ts.isFunctionLike(scope)) { + var body_1 = scope.body; + if (ts.isBlock(body_1)) { + return body_1.statements; + } + } + else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) { + return scope.statements; + } + else if (ts.isClassLike(scope)) { + return scope.members; + } + else { + ts.assertTypeIsNever(scope); + } + return ts.emptyArray; + } + /** + * If `scope` contains a function after `minPos`, then return the first such function. + * Otherwise, return `undefined`. + */ + function getNodeToInsertBefore(minPos, scope) { + var children = getStatementsOrClassElements(scope); + for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { + var child = children_3[_i]; + if (child.pos >= minPos && ts.isFunctionLike(child) && !ts.isConstructorDeclaration(child)) { + return child; + } + } + } } function getRenameLocation(edits, renameFilename, functionNameText) { var delta = 0; @@ -90180,6 +90213,7 @@ var ts; return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } var returnValueProperty; + var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (writes || substitutions.size) { @@ -90201,7 +90235,7 @@ var ts; return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node) { - if (node.kind === 219 /* ReturnStatement */ && writes) { + if (!ignoreReturns && node.kind === 219 /* ReturnStatement */ && writes) { var assignments = getPropertyAssignmentsForWrites(writes); if (node.expression) { if (!returnValueProperty) { @@ -90217,8 +90251,12 @@ var ts; } } else { + var oldIgnoreReturns = ignoreReturns; + ignoreReturns = ignoreReturns || ts.isFunctionLike(node) || ts.isClassLike(node); var substitution = substitutions.get(ts.getNodeId(node).toString()); - return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + var result = substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + ignoreReturns = oldIgnoreReturns; + return result; } } } @@ -90340,7 +90378,11 @@ var ts; } } function recordUsagebySymbol(identifier, usage, isTypeName) { - var symbol = checker.getSymbolAtLocation(identifier); + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). + var symbol = identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; @@ -90374,7 +90416,7 @@ var ts; if (!declInFile) { return undefined; } - if (ts.rangeContainsRange(enclosingTextRange, declInFile)) { + if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { // declaration is located in range to be extracted - do nothing return undefined; } @@ -90615,9 +90657,9 @@ var ts; } if (ts.isJSDocCommentContainingNode(this)) { /** Don't add trivia for "tokens" since this is in a comment. */ - var children_3 = []; - this.forEachChild(function (child) { children_3.push(child); }); - this._children = children_3; + var children_4 = []; + this.forEachChild(function (child) { children_4.push(child); }); + this._children = children_4; return; } var children = []; diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 44aae64f310..90b6c8036ab 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -3718,6 +3718,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); /// var ts; @@ -22430,17 +22432,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); @@ -89584,7 +89589,7 @@ var ts; Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); Messages.TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); Messages.FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); - Messages.InsufficientSelection = createMessage("Select more than a single token."); + Messages.InsufficientSelection = createMessage("Select more than a single identifier."); Messages.CannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); Messages.CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns"); Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); @@ -89611,6 +89616,9 @@ var ts; // exported only for tests function getRangeToExtract(sourceFile, span) { var length = span.length || 0; + if (length === 0) { + return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] }; + } // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. // This may fail (e.g. you select two statements in the root of a source file) var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span); @@ -89683,7 +89691,7 @@ var ts; return { errors: [ts.createFileDiagnostic(sourceFile, start, length, message)] }; } function checkRootNode(node) { - if (ts.isToken(ts.isExpressionStatement(node) ? node.expression : node)) { + if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) { return [ts.createDiagnosticForNode(node, Messages.InsufficientSelection)]; } return undefined; @@ -89785,45 +89793,30 @@ var ts; return false; } var savedPermittedJumps = permittedJumps; - if (node.parent) { - switch (node.parent.kind) { - case 211 /* IfStatement */: - if (node.parent.thenStatement === node || node.parent.elseStatement === node) { - // forbid all jumps inside thenStatement or elseStatement - permittedJumps = 0 /* None */; - } - break; - case 224 /* TryStatement */: - if (node.parent.tryBlock === node) { - // forbid all jumps inside try blocks - permittedJumps = 0 /* None */; - } - else if (node.parent.finallyBlock === node) { - // allow unconditional returns from finally blocks - permittedJumps = 4 /* Return */; - } - break; - case 260 /* CatchClause */: - if (node.parent.block === node) { - // forbid all jumps inside the block of catch clause - permittedJumps = 0 /* None */; - } - break; - case 257 /* CaseClause */: - if (node.expression !== node) { - // allow unlabeled break inside case clauses - permittedJumps |= 1 /* Break */; - } - break; - default: - if (ts.isIterationStatement(node.parent, /*lookInLabeledStatements*/ false)) { - if (node.parent.statement === node) { - // allow unlabeled break/continue inside loops - permittedJumps |= 1 /* Break */ | 2 /* Continue */; - } - } - break; - } + switch (node.kind) { + case 211 /* IfStatement */: + permittedJumps = 0 /* None */; + break; + case 224 /* TryStatement */: + // forbid all jumps inside try blocks + permittedJumps = 0 /* None */; + break; + case 207 /* Block */: + if (node.parent && node.parent.kind === 224 /* TryStatement */ && node.finallyBlock === node) { + // allow unconditional returns from finally blocks + permittedJumps = 4 /* Return */; + } + break; + case 257 /* CaseClause */: + // allow unlabeled break inside case clauses + permittedJumps |= 1 /* Break */; + break; + default: + if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { + // allow unlabeled break/continue inside loops + permittedJumps |= 1 /* Break */ | 2 /* Continue */; + } + break; } switch (node.kind) { case 169 /* ThisType */: @@ -89849,7 +89842,7 @@ var ts; } } else { - if (!(permittedJumps & (218 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { + if (!(permittedJumps & (node.kind === 218 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { // attempt to break or continue in a forbidden context (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements)); } @@ -89994,7 +89987,7 @@ var ts; else if (ts.isClassLike(scope)) { return scope.kind === 229 /* ClassDeclaration */ ? "class '" + scope.name.text + "'" - : scope.name.text + : scope.name && scope.name.text ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } @@ -90066,7 +90059,7 @@ var ts; modifiers.push(ts.createToken(120 /* AsyncKeyword */)); } newFunction = ts.createMethod( - /*decorators*/ undefined, modifiers, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, + /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, /*questionToken*/ undefined, /*typeParameters*/ undefined, parameters, returnType, body); } @@ -90076,8 +90069,14 @@ var ts; /*typeParameters*/ undefined, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context); - // insert function at the end of the scope - changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + var minInsertionPos = (isReadonlyArray(range.range) ? ts.lastOrUndefined(range.range) : range.range).end; + var nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope); + if (nodeToInsertBefore) { + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter }); + } + else { + changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + } var newNodes = []; // replace range with function call var called = getCalledExpression(scope, range, functionNameText); @@ -90106,6 +90105,9 @@ var ts; } else { newNodes.push(ts.createStatement(ts.createBinary(assignments[0].name, 58 /* EqualsToken */, call))); + if (range.facts & RangeFacts.HasReturn) { + newNodes.push(ts.createReturn()); + } } } else { @@ -90143,6 +90145,37 @@ var ts; var renameFilename = renameRange.getSourceFile().fileName; var renameLocation = getRenameLocation(edits, renameFilename, functionNameText); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; + function getStatementsOrClassElements(scope) { + if (ts.isFunctionLike(scope)) { + var body_1 = scope.body; + if (ts.isBlock(body_1)) { + return body_1.statements; + } + } + else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) { + return scope.statements; + } + else if (ts.isClassLike(scope)) { + return scope.members; + } + else { + ts.assertTypeIsNever(scope); + } + return ts.emptyArray; + } + /** + * If `scope` contains a function after `minPos`, then return the first such function. + * Otherwise, return `undefined`. + */ + function getNodeToInsertBefore(minPos, scope) { + var children = getStatementsOrClassElements(scope); + for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { + var child = children_3[_i]; + if (child.pos >= minPos && ts.isFunctionLike(child) && !ts.isConstructorDeclaration(child)) { + return child; + } + } + } } function getRenameLocation(edits, renameFilename, functionNameText) { var delta = 0; @@ -90180,6 +90213,7 @@ var ts; return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } var returnValueProperty; + var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (writes || substitutions.size) { @@ -90201,7 +90235,7 @@ var ts; return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node) { - if (node.kind === 219 /* ReturnStatement */ && writes) { + if (!ignoreReturns && node.kind === 219 /* ReturnStatement */ && writes) { var assignments = getPropertyAssignmentsForWrites(writes); if (node.expression) { if (!returnValueProperty) { @@ -90217,8 +90251,12 @@ var ts; } } else { + var oldIgnoreReturns = ignoreReturns; + ignoreReturns = ignoreReturns || ts.isFunctionLike(node) || ts.isClassLike(node); var substitution = substitutions.get(ts.getNodeId(node).toString()); - return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + var result = substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext); + ignoreReturns = oldIgnoreReturns; + return result; } } } @@ -90340,7 +90378,11 @@ var ts; } } function recordUsagebySymbol(identifier, usage, isTypeName) { - var symbol = checker.getSymbolAtLocation(identifier); + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). + var symbol = identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; @@ -90374,7 +90416,7 @@ var ts; if (!declInFile) { return undefined; } - if (ts.rangeContainsRange(enclosingTextRange, declInFile)) { + if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { // declaration is located in range to be extracted - do nothing return undefined; } @@ -90615,9 +90657,9 @@ var ts; } if (ts.isJSDocCommentContainingNode(this)) { /** Don't add trivia for "tokens" since this is in a comment. */ - var children_3 = []; - this.forEachChild(function (child) { children_3.push(child); }); - this._children = children_3; + var children_4 = []; + this.forEachChild(function (child) { children_4.push(child); }); + this._children = children_4; return; } var children = []; diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 2a984c6fb72..81f54792814 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -2209,6 +2209,8 @@ var ts; return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } ts.isCheckJsEnabledForFile = isCheckJsEnabledForFile; + function assertTypeIsNever(_) { } + ts.assertTypeIsNever = assertTypeIsNever; })(ts || (ts = {})); var ts; (function (ts) { @@ -17335,17 +17337,20 @@ var ts; return ts.combinePaths(directory, "package.json"); } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { - var _a = getNameOfTopDirectory(moduleName), top = _a.top, rest = _a.rest; - var packageRootPath = ts.combinePaths(nodeModulesFolder, top); + var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; + var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); var _b = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state), packageJsonContent = _b.packageJsonContent, packageId = _b.packageId; var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); var pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } - function getNameOfTopDirectory(name) { - var idx = name.indexOf(ts.directorySeparator); - return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) }; + function getPackageName(moduleName) { + var idx = moduleName.indexOf(ts.directorySeparator); + if (moduleName[0] === "@") { + idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + } + return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache);