mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' of github.com:Microsoft/TypeScript
This commit is contained in:
+8
-1
@@ -12,6 +12,7 @@ const clone = require("gulp-clone");
|
||||
const newer = require("gulp-newer");
|
||||
const tsc = require("gulp-typescript");
|
||||
const tsc_oop = require("./scripts/build/gulp-typescript-oop");
|
||||
const getDirSize = require("./scripts/build/getDirSize");
|
||||
const insert = require("gulp-insert");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const Q = require("q");
|
||||
@@ -588,7 +589,13 @@ gulp.task("VerifyLKG", /*help*/ false, [], () => {
|
||||
gulp.task("LKGInternal", /*help*/ false, ["lib", "local"]);
|
||||
|
||||
gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUseDebugMode"], () => {
|
||||
return runSequence("LKGInternal", "VerifyLKG");
|
||||
const sizeBefore = getDirSize(lkgDirectory);
|
||||
const seq = runSequence("LKGInternal", "VerifyLKG");
|
||||
const sizeAfter = getDirSize(lkgDirectory);
|
||||
if (sizeAfter > (sizeBefore * 1.10)) {
|
||||
throw new Error("The lib folder increased by 10% or more. This likely indicates a bug.");
|
||||
}
|
||||
return seq;
|
||||
});
|
||||
|
||||
|
||||
|
||||
+9
-10
@@ -8,6 +8,7 @@ var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
var fold = require("travis-fold");
|
||||
var ts = require("./lib/typescript");
|
||||
const getDirSize = require("./scripts/build/getDirSize");
|
||||
|
||||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
@@ -642,26 +643,24 @@ 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 () {
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), () => {
|
||||
const sizeBefore = getDirSize(LKGDirectory);
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts, watchGuardFile].
|
||||
concat(libraryTargets).
|
||||
concat(localizationTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
var missingFiles = expectedFiles.filter(f => !fs.existsSync(f));
|
||||
if (missingFiles.length > 0) {
|
||||
fail(new Error("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n")));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
jake.mkdirP(LKGDirectory);
|
||||
for (i in expectedFiles) {
|
||||
jake.cpR(expectedFiles[i], LKGDirectory);
|
||||
expectedFiles.forEach(f => jake.cpR(f, LKGDirectory));
|
||||
|
||||
const sizeAfter = getDirSize(LKGDirectory);
|
||||
if (sizeAfter > (sizeBefore * 1.10)) {
|
||||
throw new Error("The lib folder increased by 10% or more. This likely indicates a bug.");
|
||||
}
|
||||
//var resourceDirectories = fs.readdirSync(builtLocalResourcesDirectory).map(function(p) { return path.join(builtLocalResourcesDirectory, p); });
|
||||
//resourceDirectories.map(function(d) {
|
||||
// jake.cpR(d, LKGResourcesDirectory);
|
||||
//});
|
||||
});
|
||||
|
||||
// Test directory
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
/*!----------------- TypeScript ThirdPartyNotices -------------------------------------------------------
|
||||
|
||||
The TypeScript software is based on or incorporates material and code from the projects listed below (collectively "Third Party Code"). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such license and notices are provided for informational purposes only. Microsoft licenses the Third Party Code to you under the terms of the Apache 2.0 License.
|
||||
All Third Party Code licensed by Microsoft under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
The TypeScript software incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions and
|
||||
limitations under the License.
|
||||
---------------------------------------------
|
||||
Third Party Code Components
|
||||
--------------------------------------------
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// @ts-check
|
||||
const { lstatSync, readdirSync } = require("fs");
|
||||
const { join } = require("path");
|
||||
|
||||
/**
|
||||
* Find the size of a directory recursively.
|
||||
* Symbolic links are counted once (same inode).
|
||||
* @param {string} root
|
||||
* @param {Set} seen
|
||||
* @returns {number} bytes
|
||||
*/
|
||||
function getDirSize(root, seen = new Set()) {
|
||||
const stats = lstatSync(root);
|
||||
|
||||
if (seen.has(stats.ino)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
seen.add(stats.ino);
|
||||
|
||||
if (!stats.isDirectory()) {
|
||||
return stats.size;
|
||||
}
|
||||
|
||||
return readdirSync(root)
|
||||
.map(file => getDirSize(join(root, file), seen))
|
||||
.reduce((acc, num) => acc + num, 0);
|
||||
}
|
||||
|
||||
module.exports = getDirSize;
|
||||
@@ -31,7 +31,7 @@ function createProject(tsConfigFileName, settings, options) {
|
||||
read() {},
|
||||
/** @param {*} file */
|
||||
write(file, encoding, callback) {
|
||||
proc.send({ method: "write", params: { path: file.path, cwd: file.cwd, base: file.base }});
|
||||
proc.send({ method: "write", params: { path: file.path, cwd: file.cwd, base: file.base, sourceMap: file.sourceMap }});
|
||||
callback();
|
||||
},
|
||||
final(callback) {
|
||||
|
||||
@@ -72,6 +72,7 @@ process.on("message", ({ method, params }) => {
|
||||
base: params.base
|
||||
});
|
||||
file.contents = fs.readFileSync(file.path);
|
||||
if (params.sourceMap) file.sourceMap = params.sourceMap;
|
||||
inputStream.push(/** @type {*} */(file));
|
||||
}
|
||||
else if (method === "final") {
|
||||
|
||||
+22
-12
@@ -282,6 +282,8 @@ namespace ts {
|
||||
createPromiseType,
|
||||
createArrayType,
|
||||
getBooleanType: () => booleanType,
|
||||
getFalseType: () => falseType,
|
||||
getTrueType: () => trueType,
|
||||
getVoidType: () => voidType,
|
||||
getUndefinedType: () => undefinedType,
|
||||
getNullType: () => nullType,
|
||||
@@ -374,9 +376,9 @@ namespace ts {
|
||||
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
|
||||
const stringType = createIntrinsicType(TypeFlags.String, "string");
|
||||
const numberType = createIntrinsicType(TypeFlags.Number, "number");
|
||||
const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true");
|
||||
const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false");
|
||||
const booleanType = createBooleanType([trueType, falseType]);
|
||||
const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true");
|
||||
const booleanType = createBooleanType([falseType, trueType]);
|
||||
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
|
||||
const voidType = createIntrinsicType(TypeFlags.Void, "void");
|
||||
const neverType = createIntrinsicType(TypeFlags.Never, "never");
|
||||
@@ -2900,7 +2902,7 @@ namespace ts {
|
||||
|
||||
function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined {
|
||||
let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined;
|
||||
if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
|
||||
if (!every(symbol.declarations, getIsDeclarationVisible)) {
|
||||
return undefined;
|
||||
}
|
||||
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
|
||||
@@ -3531,9 +3533,13 @@ namespace ts {
|
||||
context.enclosingDeclaration = undefined;
|
||||
if (getCheckFlags(propertySymbol) & CheckFlags.Late) {
|
||||
const decl = first(propertySymbol.declarations);
|
||||
const name = hasLateBindableName(decl) && resolveEntityName(decl.name.expression, SymbolFlags.Value);
|
||||
if (name && context.tracker.trackSymbol) {
|
||||
context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value);
|
||||
if (context.tracker.trackSymbol && hasLateBindableName(decl)) {
|
||||
// get symbol of the first identifier of the entityName
|
||||
const firstIdentifier = getFirstIdentifier(decl.name.expression);
|
||||
const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
|
||||
if (name) {
|
||||
context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
|
||||
@@ -5494,7 +5500,7 @@ namespace ts {
|
||||
// object types.
|
||||
function isValidBaseType(type: Type): type is BaseType {
|
||||
return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any)) && !isGenericMappedType(type) ||
|
||||
!!(type.flags & TypeFlags.Intersection) && !some((<IntersectionType>type).types, t => !isValidBaseType(t));
|
||||
!!(type.flags & TypeFlags.Intersection) && every((<IntersectionType>type).types, isValidBaseType);
|
||||
}
|
||||
|
||||
function resolveBaseTypesOfInterface(type: InterfaceType): void {
|
||||
@@ -10294,7 +10300,7 @@ namespace ts {
|
||||
return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(<ObjectType>type)) :
|
||||
type.flags & TypeFlags.NonPrimitive ? true :
|
||||
type.flags & TypeFlags.Union ? some((<UnionType>type).types, isEmptyObjectType) :
|
||||
type.flags & TypeFlags.Intersection ? !some((<UnionType>type).types, t => !isEmptyObjectType(t)) :
|
||||
type.flags & TypeFlags.Intersection ? every((<UnionType>type).types, isEmptyObjectType) :
|
||||
false;
|
||||
}
|
||||
|
||||
@@ -11955,7 +11961,7 @@ namespace ts {
|
||||
|
||||
function isLiteralType(type: Type): boolean {
|
||||
return type.flags & TypeFlags.Boolean ? true :
|
||||
type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : !forEach((<UnionType>type).types, t => !isUnitType(t)) :
|
||||
type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : every((<UnionType>type).types, isUnitType) :
|
||||
isUnitType(type);
|
||||
}
|
||||
|
||||
@@ -16165,7 +16171,7 @@ namespace ts {
|
||||
return !!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.NonPrimitive) ||
|
||||
getFalsyFlags(type) & TypeFlags.DefinitelyFalsy && isValidSpreadType(removeDefinitelyFalsyTypes(type)) ||
|
||||
type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && !forEach((<UnionOrIntersectionType>type).types, t => !isValidSpreadType(t)));
|
||||
type.flags & TypeFlags.UnionOrIntersection && every((<UnionOrIntersectionType>type).types, isValidSpreadType));
|
||||
}
|
||||
|
||||
function checkJsxSelfClosingElement(node: JsxSelfClosingElement, checkMode: CheckMode | undefined): Type {
|
||||
@@ -18618,7 +18624,7 @@ namespace ts {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const superType = checkSuperExpression(node.expression);
|
||||
if (isTypeAny(superType)) {
|
||||
forEach(node.arguments, checkExpression); // Still visit arguments so they get marked for visibility, etc
|
||||
forEach(node.arguments, checkExpresionNoReturn); // Still visit arguments so they get marked for visibility, etc
|
||||
return anySignature;
|
||||
}
|
||||
if (superType !== errorType) {
|
||||
@@ -20443,7 +20449,7 @@ namespace ts {
|
||||
if (propType.symbol && propType.symbol.flags & SymbolFlags.Class) {
|
||||
const name = prop.escapedName;
|
||||
const symbol = resolveName(prop.valueDeclaration, name, SymbolFlags.Type, undefined, name, /*isUse*/ false);
|
||||
if (symbol && symbol.declarations.some(d => d.kind === SyntaxKind.JSDocTypedefTag)) {
|
||||
if (symbol && symbol.declarations.some(isJSDocTypedefTag)) {
|
||||
grammarErrorOnNode(symbol.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name));
|
||||
return grammarErrorOnNode(prop.valueDeclaration, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name));
|
||||
}
|
||||
@@ -20779,6 +20785,10 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function checkExpresionNoReturn(node: Expression) {
|
||||
checkExpression(node);
|
||||
}
|
||||
|
||||
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
|
||||
// contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
|
||||
// expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in
|
||||
|
||||
@@ -109,6 +109,14 @@ namespace ts {
|
||||
paramType: Diagnostics.FILE_OR_DIRECTORY,
|
||||
description: Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json,
|
||||
},
|
||||
{
|
||||
name: "build",
|
||||
type: "boolean",
|
||||
shortName: "b",
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Command_line_Options,
|
||||
description: Diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date
|
||||
},
|
||||
{
|
||||
name: "pretty",
|
||||
type: "boolean",
|
||||
@@ -968,6 +976,125 @@ namespace ts {
|
||||
}
|
||||
|
||||
|
||||
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
|
||||
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
|
||||
return <string>diagnostic.messageText;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function printVersion() {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function printHelp(optionsList: CommandLineOption[], syntaxPrefix = "") {
|
||||
const output: string[] = [];
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
let marginLength = Math.max(syntaxLength, examplesLength);
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += `tsc ${syntaxPrefix}[${getDiagnosticText(Diagnostics.options)}] [${getDiagnosticText(Diagnostics.file)}...]`;
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
|
||||
output.push(sys.newLine + sys.newLine);
|
||||
|
||||
// Build up the list of examples.
|
||||
const padding = makePadding(marginLength);
|
||||
output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine);
|
||||
output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine);
|
||||
output.push(padding + "tsc @args.txt" + sys.newLine);
|
||||
output.push(padding + "tsc --build tsconfig.json" + sys.newLine);
|
||||
output.push(sys.newLine);
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
marginLength = 0;
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (const option of optionsList) {
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
if (!option.description) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let usageText = " ";
|
||||
if (option.shortName) {
|
||||
usageText += "-" + option.shortName;
|
||||
usageText += getParamType(option);
|
||||
usageText += ", ";
|
||||
}
|
||||
|
||||
usageText += "--" + option.name;
|
||||
usageText += getParamType(option);
|
||||
|
||||
usageColumn.push(usageText);
|
||||
let description: string;
|
||||
|
||||
if (option.name === "lib") {
|
||||
description = getDiagnosticText(option.description);
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
|
||||
}
|
||||
else {
|
||||
description = getDiagnosticText(option.description);
|
||||
}
|
||||
|
||||
descriptionColumn.push(description);
|
||||
|
||||
// Set the new margin for the description column if necessary.
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
}
|
||||
|
||||
// Special case that can't fit in the loop.
|
||||
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
usageColumn.push(usageText);
|
||||
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
|
||||
// Print out each row, aligning all the descriptions on the same column.
|
||||
for (let i = 0; i < usageColumn.length; i++) {
|
||||
const usage = usageColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
const kindsList = optionsDescriptionMap.get(description);
|
||||
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
|
||||
|
||||
if (kindsList) {
|
||||
output.push(makePadding(marginLength + 4));
|
||||
for (const kind of kindsList) {
|
||||
output.push(kind + " ");
|
||||
}
|
||||
output.push(sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
return;
|
||||
|
||||
function getParamType(option: CommandLineOption) {
|
||||
if (option.paramType !== undefined) {
|
||||
return " " + getDiagnosticText(option.paramType);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function makePadding(paddingLength: number): string {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
|
||||
/**
|
||||
* Reports config file diagnostics
|
||||
|
||||
@@ -3620,6 +3620,95 @@
|
||||
"category": "Error",
|
||||
"code": 6309
|
||||
},
|
||||
"Project '{0}' is out of date because oldest output '{1}' is older than newest input '{2}'": {
|
||||
"category": "Message",
|
||||
"code": 6350
|
||||
},
|
||||
"Project '{0}' is up to date because newest input '{1}' is older than oldest output '{2}'": {
|
||||
"category": "Message",
|
||||
"code": 6351
|
||||
},
|
||||
"Project '{0}' is out of date because output file '{1}' does not exist": {
|
||||
"category": "Message",
|
||||
"code": 6352
|
||||
},
|
||||
"Project '{0}' is out of date because its dependency '{1}' is out of date": {
|
||||
"category": "Message",
|
||||
"code": 6353
|
||||
},
|
||||
|
||||
"Project '{0}' is up to date with .d.ts files from its dependencies": {
|
||||
"category": "Message",
|
||||
"code": 6354
|
||||
},
|
||||
"Projects in this build: {0}": {
|
||||
"category": "Message",
|
||||
"code": 6355
|
||||
},
|
||||
"A non-dry build would delete the following files: {0}": {
|
||||
"category": "Message",
|
||||
"code": 6356
|
||||
},
|
||||
"A non-dry build would build project '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 6357
|
||||
},
|
||||
"Building project '{0}'...": {
|
||||
"category": "Message",
|
||||
"code": 6358
|
||||
},
|
||||
"Updating output timestamps of project '{0}'...": {
|
||||
"category": "Message",
|
||||
"code": 6359
|
||||
},
|
||||
"delete this - Project '{0}' is up to date because it was previously built": {
|
||||
"category": "Message",
|
||||
"code": 6360
|
||||
},
|
||||
"Project '{0}' is up to date": {
|
||||
"category": "Message",
|
||||
"code": 6361
|
||||
},
|
||||
"Skipping build of project '{0}' because its dependency '{1}' has errors": {
|
||||
"category": "Message",
|
||||
"code": 6362
|
||||
},
|
||||
"Project '{0}' can't be built because its dependency '{1}' has errors": {
|
||||
"category": "Message",
|
||||
"code": 6363
|
||||
},
|
||||
"Build one or more projects and their dependencies, if out of date": {
|
||||
"category": "Message",
|
||||
"code": 6364
|
||||
},
|
||||
"Delete the outputs of all projects": {
|
||||
"category": "Message",
|
||||
"code": 6365
|
||||
},
|
||||
"Enable verbose logging": {
|
||||
"category": "Message",
|
||||
"code": 6366
|
||||
},
|
||||
"Show what would be built (or deleted, if specified with '--clean')": {
|
||||
"category": "Message",
|
||||
"code": 6367
|
||||
},
|
||||
"Build all projects, including those that appear to be up to date": {
|
||||
"category": "Message",
|
||||
"code": 6368
|
||||
},
|
||||
"Option '--build' must be the first command line argument.": {
|
||||
"category": "Error",
|
||||
"code": 6369
|
||||
},
|
||||
"Options '{0}' and '{1}' cannot be combined.": {
|
||||
"category": "Error",
|
||||
"code": 6370
|
||||
},
|
||||
"Skipping clean because not all projects could be located": {
|
||||
"category": "Error",
|
||||
"code": 6371
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -1026,7 +1026,7 @@ namespace ts {
|
||||
|
||||
// SyntaxKind.UnparsedSource
|
||||
function emitUnparsedSource(unparsed: UnparsedSource) {
|
||||
write(unparsed.text);
|
||||
writer.rawWrite(unparsed.text);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -2587,16 +2587,19 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createUnparsedSourceFile(text: string): UnparsedSource {
|
||||
export function createUnparsedSourceFile(text: string, map?: string): UnparsedSource {
|
||||
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
|
||||
node.text = text;
|
||||
node.sourceMapText = map;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createInputFiles(javascript: string, declaration: string): InputFiles {
|
||||
export function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles {
|
||||
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
|
||||
node.javascriptText = javascript;
|
||||
node.javascriptMapText = javascriptMapText;
|
||||
node.declarationText = declaration;
|
||||
node.declarationMapText = declarationMapText;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace ts.moduleSpecifiers {
|
||||
const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
|
||||
if (mainFileRelative) {
|
||||
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
|
||||
if (mainExportFile === getCanonicalFileName(path)) {
|
||||
if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(path))) {
|
||||
return packageRootPath;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-17
@@ -189,7 +189,10 @@ namespace ts {
|
||||
getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "",
|
||||
getDirectories: (path: string) => sys.getDirectories(path),
|
||||
realpath,
|
||||
readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth)
|
||||
readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth),
|
||||
getModifiedTime: sys.getModifiedTime && (path => sys.getModifiedTime!(path)),
|
||||
setModifiedTime: sys.setModifiedTime && ((path, date) => sys.setModifiedTime!(path, date)),
|
||||
deleteFile: sys.deleteFile && (path => sys.deleteFile!(path))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -615,25 +618,27 @@ namespace ts {
|
||||
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
|
||||
const resolvedProjectReferences: (ResolvedProjectReference | undefined)[] | undefined = projectReferences ? [] : undefined;
|
||||
const projectReferenceRedirects: Map<string> = createMap();
|
||||
if (projectReferences) {
|
||||
for (const ref of projectReferences) {
|
||||
const parsedRef = parseProjectReferenceConfigFile(ref);
|
||||
resolvedProjectReferences!.push(parsedRef);
|
||||
if (parsedRef) {
|
||||
if (parsedRef.commandLine.options.outFile) {
|
||||
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
|
||||
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
|
||||
const structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
if (structuralIsReused !== StructureIsReused.Completely) {
|
||||
processingDefaultLibFiles = [];
|
||||
processingOtherFiles = [];
|
||||
|
||||
if (projectReferences) {
|
||||
for (const ref of projectReferences) {
|
||||
const parsedRef = parseProjectReferenceConfigFile(ref);
|
||||
resolvedProjectReferences!.push(parsedRef);
|
||||
if (parsedRef) {
|
||||
if (parsedRef.commandLine.options.outFile) {
|
||||
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
|
||||
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false));
|
||||
|
||||
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
|
||||
@@ -1021,7 +1026,7 @@ namespace ts {
|
||||
|
||||
for (const oldSourceFile of oldSourceFiles) {
|
||||
let newSourceFile = host.getSourceFileByPath
|
||||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
|
||||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
|
||||
: host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217
|
||||
|
||||
if (!newSourceFile) {
|
||||
@@ -1234,8 +1239,10 @@ namespace ts {
|
||||
|
||||
const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts");
|
||||
const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`;
|
||||
const jsMap = host.readFile(resolvedRefOpts.options.outFile + ".map"); // TODO: try to read sourceMappingUrl comment from the js file
|
||||
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
|
||||
const node = createInputFiles(js, dts);
|
||||
const dtsMap = host.readFile(dtsFilename + ".map");
|
||||
const node = createInputFiles(js, dts, jsMap, dtsMap);
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
@@ -2047,6 +2054,7 @@ namespace ts {
|
||||
if (file) {
|
||||
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
|
||||
file.path = path;
|
||||
file.resolvedPath = toPath(fileName);
|
||||
|
||||
if (host.useCaseSensitiveFileNames()) {
|
||||
const pathLowerCase = path.toLowerCase();
|
||||
@@ -2781,7 +2789,7 @@ namespace ts {
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
*/
|
||||
function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined {
|
||||
export function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined {
|
||||
if (!host.fileExists(ref.path)) {
|
||||
return combinePaths(ref.path, "tsconfig.json");
|
||||
}
|
||||
|
||||
@@ -349,8 +349,32 @@ namespace ts {
|
||||
return endsWith(dirPath, "/node_modules/@types");
|
||||
}
|
||||
|
||||
function isDirectoryAtleastAtLevelFromFSRoot(dirPath: Path, minLevels: number) {
|
||||
for (let searchIndex = getRootLength(dirPath); minLevels > 0; minLevels--) {
|
||||
/**
|
||||
* Filter out paths like
|
||||
* "/", "/user", "/user/username", "/user/username/folderAtRoot",
|
||||
* "c:/", "c:/users", "c:/users/username", "c:/users/username/folderAtRoot", "c:/folderAtRoot"
|
||||
* @param dirPath
|
||||
*/
|
||||
function canWatchDirectory(dirPath: Path) {
|
||||
const rootLength = getRootLength(dirPath);
|
||||
if (dirPath.length === rootLength) {
|
||||
// Ignore "/", "c:/"
|
||||
return false;
|
||||
}
|
||||
|
||||
const nextDirectorySeparator = dirPath.indexOf(directorySeparator, rootLength);
|
||||
if (nextDirectorySeparator === -1) {
|
||||
// ignore "/user", "c:/users" or "c:/folderAtRoot"
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dirPath.charCodeAt(0) !== CharacterCodes.slash &&
|
||||
dirPath.substr(rootLength, nextDirectorySeparator).search(/users/i) === -1) {
|
||||
// Paths like c:/folderAtRoot/subFolder are allowed
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) {
|
||||
searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1;
|
||||
if (searchIndex === 0) {
|
||||
// Folder isnt at expected minimun levels
|
||||
@@ -360,15 +384,6 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function canWatchDirectory(dirPath: Path) {
|
||||
return isDirectoryAtleastAtLevelFromFSRoot(dirPath,
|
||||
// When root is "/" do not watch directories like:
|
||||
// "/", "/user", "/user/username", "/user/username/folderAtRoot"
|
||||
// When root is "c:/" do not watch directories like:
|
||||
// "c:/", "c:/folderAtRoot"
|
||||
dirPath.charCodeAt(0) === CharacterCodes.slash ? 3 : 1);
|
||||
}
|
||||
|
||||
function filterFSRootDirectoriesToWatch(watchPath: DirectoryOfFailedLookupWatch, dirPath: Path): DirectoryOfFailedLookupWatch {
|
||||
if (!canWatchDirectory(dirPath)) {
|
||||
watchPath.ignore = true;
|
||||
|
||||
+107
-11
@@ -99,6 +99,10 @@ namespace ts {
|
||||
let sourceMapDataList: SourceMapData[] | undefined;
|
||||
let disabled: boolean = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap);
|
||||
|
||||
let completedSections: SourceMapSectionDefinition[];
|
||||
let sectionStartLine: number;
|
||||
let sectionStartColumn: number;
|
||||
|
||||
return {
|
||||
initialize,
|
||||
reset,
|
||||
@@ -146,6 +150,9 @@ namespace ts {
|
||||
lastEncodedNameIndex = 0;
|
||||
|
||||
// Initialize source map data
|
||||
completedSections = [];
|
||||
sectionStartLine = 1;
|
||||
sectionStartColumn = 1;
|
||||
sourceMapData = {
|
||||
sourceMapFilePath,
|
||||
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined!, // TODO: GH#18217
|
||||
@@ -214,6 +221,65 @@ namespace ts {
|
||||
lastEncodedNameIndex = undefined;
|
||||
sourceMapData = undefined!;
|
||||
sourceMapDataList = undefined!;
|
||||
completedSections = undefined!;
|
||||
sectionStartLine = undefined!;
|
||||
sectionStartColumn = undefined!;
|
||||
}
|
||||
|
||||
interface SourceMapSection {
|
||||
version: 3;
|
||||
file: string;
|
||||
sourceRoot?: string;
|
||||
sources: string[];
|
||||
names?: string[];
|
||||
mappings: string;
|
||||
sourcesContent?: string[];
|
||||
sections?: undefined;
|
||||
}
|
||||
|
||||
type SourceMapSectionDefinition =
|
||||
| { offset: { line: number, column: number }, url: string } // Included for completeness
|
||||
| { offset: { line: number, column: number }, map: SourceMap };
|
||||
|
||||
interface SectionalSourceMap {
|
||||
version: 3;
|
||||
file: string;
|
||||
sections: SourceMapSectionDefinition[];
|
||||
}
|
||||
|
||||
type SourceMap = SectionalSourceMap | SourceMapSection;
|
||||
|
||||
function captureSection(): SourceMapSection {
|
||||
return {
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
names: sourceMapData.sourceMapNames,
|
||||
mappings: sourceMapData.sourceMapMappings,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
};
|
||||
}
|
||||
|
||||
function resetSectionalData(): void {
|
||||
sourceMapData.sourceMapSources = [];
|
||||
sourceMapData.sourceMapNames = [];
|
||||
sourceMapData.sourceMapMappings = "";
|
||||
sourceMapData.sourceMapSourcesContent = compilerOptions.inlineSources ? [] : undefined;
|
||||
}
|
||||
|
||||
function generateMap(): SourceMap {
|
||||
if (completedSections.length) {
|
||||
captureSectionalSpanIfNeeded(/*reset*/ false);
|
||||
return {
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sections: completedSections
|
||||
};
|
||||
}
|
||||
else {
|
||||
return captureSection();
|
||||
}
|
||||
}
|
||||
|
||||
// Encoding for sourcemap span
|
||||
@@ -284,8 +350,8 @@ namespace ts {
|
||||
sourceLinePos.line++;
|
||||
sourceLinePos.character++;
|
||||
|
||||
const emittedLine = writer.getLine();
|
||||
const emittedColumn = writer.getColumn();
|
||||
const emittedLine = writer.getLine() - sectionStartLine + 1;
|
||||
const emittedColumn = emittedLine === 0 ? (writer.getColumn() - sectionStartColumn + 1) : writer.getColumn();
|
||||
|
||||
// If this location wasn't recorded or the location in source is going backwards, record the span
|
||||
if (!lastRecordedSourceMapSpan ||
|
||||
@@ -320,6 +386,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function captureSectionalSpanIfNeeded(reset: boolean) {
|
||||
if (lastRecordedSourceMapSpan && lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { // If we've recorded some spans, save them
|
||||
completedSections.push({ offset: { line: sectionStartLine - 1, column: sectionStartColumn - 1 }, map: captureSection() });
|
||||
if (reset) {
|
||||
resetSectionalData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with possible leading and trailing source maps.
|
||||
*
|
||||
@@ -333,6 +408,35 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (node) {
|
||||
if (isUnparsedSource(node) && node.sourceMapText !== undefined) {
|
||||
captureSectionalSpanIfNeeded(/*reset*/ true);
|
||||
const text = node.sourceMapText;
|
||||
let parsed: {} | undefined;
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
}
|
||||
catch {
|
||||
// empty
|
||||
}
|
||||
const offset = { line: writer.getLine() - 1, column: writer.getColumn() - 1 };
|
||||
completedSections.push(parsed
|
||||
? {
|
||||
offset,
|
||||
map: parsed as SourceMap
|
||||
}
|
||||
: {
|
||||
offset,
|
||||
// This is just passes the buck on sourcemaps we don't really understand, instead of issuing an error (which would be difficult this late)
|
||||
url: `data:application/json;charset=utf-8;base64,${base64encode(sys, text)}`
|
||||
}
|
||||
);
|
||||
const emitResult = emitCallback(hint, node);
|
||||
sectionStartLine = writer.getLine();
|
||||
sectionStartColumn = writer.getColumn();
|
||||
lastRecordedSourceMapSpan = undefined!;
|
||||
lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan;
|
||||
return emitResult;
|
||||
}
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags || EmitFlags.None;
|
||||
const range = emitNode && emitNode.sourceMapRange;
|
||||
@@ -460,15 +564,7 @@ namespace ts {
|
||||
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return JSON.stringify({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
names: sourceMapData.sourceMapNames,
|
||||
mappings: sourceMapData.sourceMapMappings,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
});
|
||||
return JSON.stringify(generateMap());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -433,6 +433,7 @@ namespace ts {
|
||||
readFile(path: string, encoding?: string): string | undefined;
|
||||
getFileSize?(path: string): number;
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
|
||||
/**
|
||||
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
|
||||
* use native OS file watching
|
||||
@@ -448,6 +449,8 @@ namespace ts {
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
setModifiedTime?(path: string, time: Date): void;
|
||||
deleteFile?(path: string): void;
|
||||
/**
|
||||
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
|
||||
*/
|
||||
@@ -592,6 +595,8 @@ namespace ts {
|
||||
},
|
||||
readDirectory,
|
||||
getModifiedTime,
|
||||
setModifiedTime,
|
||||
deleteFile,
|
||||
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
|
||||
createSHA256Hash: _crypto ? createSHA256Hash : undefined,
|
||||
getMemoryUsage() {
|
||||
@@ -1069,6 +1074,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function setModifiedTime(path: string, time: Date) {
|
||||
try {
|
||||
_fs.utimesSync(path, time, time);
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteFile(path: string) {
|
||||
try {
|
||||
return _fs.unlinkSync(path);
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* djb2 hashing algorithm
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace ts {
|
||||
}
|
||||
), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.declarationText);
|
||||
return createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapText);
|
||||
}
|
||||
}));
|
||||
bundle.syntheticFileReferences = [];
|
||||
|
||||
@@ -1832,6 +1832,7 @@ namespace ts {
|
||||
let statementsLocation: TextRange;
|
||||
let closeBraceLocation: TextRange | undefined;
|
||||
|
||||
const leadingStatements: Statement[] = [];
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body!;
|
||||
let statementOffset: number | undefined;
|
||||
@@ -1840,21 +1841,16 @@ namespace ts {
|
||||
if (isBlock(body)) {
|
||||
// ensureUseStrict is false because no new prologue-directive should be added.
|
||||
// addStandardPrologue will put already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addStandardPrologue(statements, body.statements, /*ensureUseStrict*/ false);
|
||||
statementOffset = addStandardPrologue(leadingStatements, body.statements, /*ensureUseStrict*/ false);
|
||||
}
|
||||
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, node);
|
||||
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
|
||||
// If we added any generated statements, this must be a multi-line block.
|
||||
if (!multiLine && statements.length > 0) {
|
||||
multiLine = true;
|
||||
}
|
||||
addCaptureThisForNodeIfNeeded(leadingStatements, node);
|
||||
addDefaultValueAssignmentsIfNeeded(leadingStatements, node);
|
||||
addRestParameterIfNeeded(leadingStatements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
|
||||
if (isBlock(body)) {
|
||||
// addCustomPrologue puts already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addCustomPrologue(statements, body.statements, statementOffset, visitor);
|
||||
statementOffset = addCustomPrologue(leadingStatements, body.statements, statementOffset, visitor);
|
||||
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
|
||||
@@ -1897,15 +1893,14 @@ namespace ts {
|
||||
|
||||
const lexicalEnvironment = context.endLexicalEnvironment();
|
||||
prependStatements(statements, lexicalEnvironment);
|
||||
|
||||
prependCaptureNewTargetIfNeeded(statements, node, /*copyOnWrite*/ false);
|
||||
|
||||
// If we added any final generated statements, this must be a multi-line block
|
||||
if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) {
|
||||
if (some(leadingStatements) || some(lexicalEnvironment)) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine);
|
||||
const block = createBlock(setTextRange(createNodeArray([...leadingStatements, ...statements]), statementsLocation), multiLine);
|
||||
setTextRange(block, node.body);
|
||||
if (!multiLine && singleLine) {
|
||||
setEmitFlags(block, EmitFlags.SingleLine);
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace ts {
|
||||
function transformBundle(node: Bundle) {
|
||||
return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.javascriptText);
|
||||
return createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapText);
|
||||
}
|
||||
return prepend;
|
||||
}));
|
||||
@@ -1912,6 +1912,7 @@ namespace ts {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.UnknownKeyword:
|
||||
case SyntaxKind.ThisType:
|
||||
case SyntaxKind.ImportType:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+26
-123
@@ -12,11 +12,6 @@ namespace ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
|
||||
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
|
||||
return <string>diagnostic.messageText;
|
||||
}
|
||||
|
||||
let reportDiagnostic = createDiagnosticReporter(sys);
|
||||
function updateReportDiagnostic(options: CompilerOptions) {
|
||||
if (shouldBePretty(options)) {
|
||||
@@ -46,9 +41,33 @@ namespace ts {
|
||||
return s;
|
||||
}
|
||||
|
||||
function getOptionsForHelp(commandLine: ParsedCommandLine) {
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
return !!commandLine.options.all ?
|
||||
sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
|
||||
filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView);
|
||||
}
|
||||
|
||||
export function executeCommandLine(args: string[]): void {
|
||||
if (args.length > 0 && ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b"))) {
|
||||
const reportDiag = createDiagnosticReporter(sys, /*pretty*/ true);
|
||||
const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args));
|
||||
const buildHost: BuildHost = {
|
||||
error: report,
|
||||
verbose: report,
|
||||
message: report,
|
||||
errorDiagnostic: d => reportDiag(d)
|
||||
};
|
||||
return performBuild(args.slice(1), createCompilerHost({}), buildHost, sys);
|
||||
}
|
||||
|
||||
const commandLine = parseCommandLine(args);
|
||||
|
||||
if (commandLine.options.build) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_build_must_be_the_first_command_line_argument));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
// Configuration file name (if any)
|
||||
let configFileName: string | undefined;
|
||||
if (commandLine.options.locale) {
|
||||
@@ -74,7 +93,7 @@ namespace ts {
|
||||
|
||||
if (commandLine.options.help || commandLine.options.all) {
|
||||
printVersion();
|
||||
printHelp(!!commandLine.options.all);
|
||||
printHelp(getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -107,7 +126,7 @@ namespace ts {
|
||||
|
||||
if (commandLine.fileNames.length === 0 && !configFileName) {
|
||||
printVersion();
|
||||
printHelp(!!commandLine.options.all);
|
||||
printHelp(getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -271,122 +290,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function printVersion() {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
}
|
||||
|
||||
function printHelp(showAllOptions: boolean) {
|
||||
const output: string[] = [];
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
let marginLength = Math.max(syntaxLength, examplesLength);
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += "tsc [" + getDiagnosticText(Diagnostics.options) + "] [" + getDiagnosticText(Diagnostics.file) + " ...]";
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
|
||||
output.push(sys.newLine + sys.newLine);
|
||||
|
||||
// Build up the list of examples.
|
||||
const padding = makePadding(marginLength);
|
||||
output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine);
|
||||
output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine);
|
||||
output.push(padding + "tsc @args.txt" + sys.newLine);
|
||||
output.push(sys.newLine);
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
const optsList = showAllOptions ?
|
||||
sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
|
||||
filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView);
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
marginLength = 0;
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (const option of optsList) {
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
if (!option.description) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let usageText = " ";
|
||||
if (option.shortName) {
|
||||
usageText += "-" + option.shortName;
|
||||
usageText += getParamType(option);
|
||||
usageText += ", ";
|
||||
}
|
||||
|
||||
usageText += "--" + option.name;
|
||||
usageText += getParamType(option);
|
||||
|
||||
usageColumn.push(usageText);
|
||||
let description: string;
|
||||
|
||||
if (option.name === "lib") {
|
||||
description = getDiagnosticText(option.description);
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
|
||||
}
|
||||
else {
|
||||
description = getDiagnosticText(option.description);
|
||||
}
|
||||
|
||||
descriptionColumn.push(description);
|
||||
|
||||
// Set the new margin for the description column if necessary.
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
}
|
||||
|
||||
// Special case that can't fit in the loop.
|
||||
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
usageColumn.push(usageText);
|
||||
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
|
||||
// Print out each row, aligning all the descriptions on the same column.
|
||||
for (let i = 0; i < usageColumn.length; i++) {
|
||||
const usage = usageColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
const kindsList = optionsDescriptionMap.get(description);
|
||||
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
|
||||
|
||||
if (kindsList) {
|
||||
output.push(makePadding(marginLength + 4));
|
||||
for (const kind of kindsList) {
|
||||
output.push(kind + " ");
|
||||
}
|
||||
output.push(sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
return;
|
||||
|
||||
function getParamType(option: CommandLineOption) {
|
||||
if (option.paramType !== undefined) {
|
||||
return " " + getDiagnosticText(option.paramType);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function makePadding(paddingLength: number): string {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"moduleSpecifiers.ts",
|
||||
"watch.ts",
|
||||
"commandLineParser.ts",
|
||||
"tsc.ts"
|
||||
"tsbuild.ts",
|
||||
"tsc.ts",
|
||||
]
|
||||
}
|
||||
|
||||
+14
-1
@@ -2558,6 +2558,7 @@ namespace ts {
|
||||
fileName: string;
|
||||
/* @internal */ path: Path;
|
||||
text: string;
|
||||
/* @internal */ resolvedPath: Path;
|
||||
|
||||
/**
|
||||
* If two source files are for the same version of the same package, one will redirect to the other.
|
||||
@@ -2658,12 +2659,15 @@ namespace ts {
|
||||
export interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
|
||||
export interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
|
||||
export interface JsonSourceFile extends SourceFile {
|
||||
@@ -3016,6 +3020,8 @@ namespace ts {
|
||||
/* @internal */ getStringType(): Type;
|
||||
/* @internal */ getNumberType(): Type;
|
||||
/* @internal */ getBooleanType(): Type;
|
||||
/* @internal */ getFalseType(): Type;
|
||||
/* @internal */ getTrueType(): Type;
|
||||
/* @internal */ getVoidType(): Type;
|
||||
/* @internal */ getUndefinedType(): Type;
|
||||
/* @internal */ getNullType(): Type;
|
||||
@@ -3054,12 +3060,12 @@ namespace ts {
|
||||
/* @internal */ getSymbolCount(): number;
|
||||
/* @internal */ getTypeCount(): number;
|
||||
|
||||
/* @internal */ isArrayLikeType(type: Type): boolean;
|
||||
/**
|
||||
* For a union, will include a property if it's defined in *any* of the member types.
|
||||
* So for `{ a } | { b }`, this will include both `a` and `b`.
|
||||
* Does not include properties of primitive types.
|
||||
*/
|
||||
/* @internal */ isArrayLikeType(type: Type): boolean;
|
||||
/* @internal */ getAllPossiblePropertiesOfTypes(type: ReadonlyArray<Type>): Symbol[];
|
||||
/* @internal */ resolveName(name: string, location: Node, meaning: SymbolFlags, excludeGlobals: boolean): Symbol | undefined;
|
||||
/* @internal */ getJsxNamespace(location?: Node): string;
|
||||
@@ -4295,6 +4301,9 @@ namespace ts {
|
||||
allowUnusedLabels?: boolean;
|
||||
alwaysStrict?: boolean; // Always combine with strict property
|
||||
baseUrl?: string;
|
||||
/** An error if set - this should only go through the -b pipeline and not actually be observed */
|
||||
/*@internal*/
|
||||
build?: boolean;
|
||||
charset?: string;
|
||||
checkJs?: boolean;
|
||||
/* @internal */ configFilePath?: string;
|
||||
@@ -4817,6 +4826,10 @@ namespace ts {
|
||||
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
|
||||
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
|
||||
createHash?(data: string): string;
|
||||
|
||||
getModifiedTime?(fileName: string): Date;
|
||||
setModifiedTime?(fileName: string, date: Date): void;
|
||||
deleteFile?(fileName: string): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
+22
-10
@@ -2861,13 +2861,26 @@ namespace ts {
|
||||
let lineCount: number;
|
||||
let linePos: number;
|
||||
|
||||
function updateLineCountAndPosFor(s: string) {
|
||||
const lineStartsOfS = computeLineStarts(s);
|
||||
if (lineStartsOfS.length > 1) {
|
||||
lineCount = lineCount + lineStartsOfS.length - 1;
|
||||
linePos = output.length - s.length + last(lineStartsOfS);
|
||||
lineStart = (linePos - output.length) === 0;
|
||||
}
|
||||
else {
|
||||
lineStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
function write(s: string) {
|
||||
if (s && s.length) {
|
||||
if (lineStart) {
|
||||
output += getIndentString(indent);
|
||||
s = getIndentString(indent) + s;
|
||||
lineStart = false;
|
||||
}
|
||||
output += s;
|
||||
updateLineCountAndPosFor(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2881,21 +2894,14 @@ namespace ts {
|
||||
|
||||
function rawWrite(s: string) {
|
||||
if (s !== undefined) {
|
||||
if (lineStart) {
|
||||
lineStart = false;
|
||||
}
|
||||
output += s;
|
||||
updateLineCountAndPosFor(s);
|
||||
}
|
||||
}
|
||||
|
||||
function writeLiteral(s: string) {
|
||||
if (s && s.length) {
|
||||
write(s);
|
||||
const lineStartsOfS = computeLineStarts(s);
|
||||
if (lineStartsOfS.length > 1) {
|
||||
lineCount = lineCount + lineStartsOfS.length - 1;
|
||||
linePos = output.length - s.length + last(lineStartsOfS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2909,7 +2915,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function writeTextOfNode(text: string, node: Node) {
|
||||
write(getTextOfNodeFromSourceText(text, node));
|
||||
const s = getTextOfNodeFromSourceText(text, node);
|
||||
write(s);
|
||||
updateLineCountAndPosFor(s);
|
||||
}
|
||||
|
||||
reset();
|
||||
@@ -5487,6 +5495,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.Bundle;
|
||||
}
|
||||
|
||||
export function isUnparsedSource(node: Node): node is UnparsedSource {
|
||||
return node.kind === SyntaxKind.UnparsedSource;
|
||||
}
|
||||
|
||||
// JSDoc
|
||||
|
||||
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
|
||||
|
||||
+21
-1
@@ -51,6 +51,10 @@ namespace fakes {
|
||||
this.vfs.writeFileSync(path, writeByteOrderMark ? utils.addUTF8ByteOrderMark(data) : data);
|
||||
}
|
||||
|
||||
public deleteFile(path: string) {
|
||||
this.vfs.unlinkSync(path);
|
||||
}
|
||||
|
||||
public fileExists(path: string) {
|
||||
const stats = this._getStats(path);
|
||||
return stats ? stats.isFile() : false;
|
||||
@@ -131,6 +135,10 @@ namespace fakes {
|
||||
return stats ? stats.mtime : undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
public setModifiedTime(path: string, time: Date) {
|
||||
this.vfs.utimesSync(path, time, time);
|
||||
}
|
||||
|
||||
public createHash(data: string): string {
|
||||
return data;
|
||||
}
|
||||
@@ -244,6 +252,10 @@ namespace fakes {
|
||||
return this.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
public deleteFile(fileName: string) {
|
||||
this.sys.deleteFile(fileName);
|
||||
}
|
||||
|
||||
public fileExists(fileName: string): boolean {
|
||||
return this.sys.fileExists(fileName);
|
||||
}
|
||||
@@ -252,6 +264,14 @@ namespace fakes {
|
||||
return this.sys.directoryExists(directoryName);
|
||||
}
|
||||
|
||||
public getModifiedTime(fileName: string) {
|
||||
return this.sys.getModifiedTime(fileName);
|
||||
}
|
||||
|
||||
public setModifiedTime(fileName: string, time: Date) {
|
||||
return this.sys.setModifiedTime(fileName, time);
|
||||
}
|
||||
|
||||
public getDirectories(path: string): string[] {
|
||||
return this.sys.getDirectories(path);
|
||||
}
|
||||
@@ -312,7 +332,7 @@ namespace fakes {
|
||||
if (cacheKey) {
|
||||
const meta = this.vfs.filemeta(canonicalFileName);
|
||||
const sourceFileFromMetadata = meta.get(cacheKey) as ts.SourceFile | undefined;
|
||||
if (sourceFileFromMetadata) {
|
||||
if (sourceFileFromMetadata && sourceFileFromMetadata.getFullText() === content) {
|
||||
this._sourceFiles.set(canonicalFileName, sourceFileFromMetadata);
|
||||
return sourceFileFromMetadata;
|
||||
}
|
||||
|
||||
@@ -2869,6 +2869,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
function replacer(key: string, value: any) {
|
||||
switch (key) {
|
||||
case "spans":
|
||||
case "nameSpan":
|
||||
return options && options.checkSpans ? value : undefined;
|
||||
case "start":
|
||||
case "length":
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"../compiler/resolutionCache.ts",
|
||||
"../compiler/moduleSpecifiers.ts",
|
||||
"../compiler/watch.ts",
|
||||
"../compiler/tsbuild.ts",
|
||||
"../compiler/commandLineParser.ts",
|
||||
|
||||
"../services/types.ts",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
describe("asyncArrowEvaluation", () => {
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
it("this capture (es5)", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
export class A {
|
||||
b = async (...args: any[]) => {
|
||||
await Promise.resolve();
|
||||
output.push({ ["a"]: () => this }); // computed property name after 'await' triggers case
|
||||
};
|
||||
}
|
||||
export const output: any[] = [];
|
||||
export async function main() {
|
||||
await new A().b();
|
||||
}`);
|
||||
await result.main();
|
||||
assert.instanceOf(result.output[0].a(), result.A);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,425 @@
|
||||
namespace ts {
|
||||
let currentTime = 100;
|
||||
let lastDiagnostics: Diagnostic[] = [];
|
||||
const reportDiagnostic: DiagnosticReporter = diagnostic => lastDiagnostics.push(diagnostic);
|
||||
const report = (message: DiagnosticMessage, ...args: string[]) => reportDiagnostic(createCompilerDiagnostic(message, ...args));
|
||||
const buildHost: BuildHost = {
|
||||
error: report,
|
||||
verbose: report,
|
||||
message: report,
|
||||
errorDiagnostic: d => reportDiagnostic(d)
|
||||
};
|
||||
|
||||
export namespace Sample1 {
|
||||
tick();
|
||||
const projFs = loadProjectFromDisk("../../tests/projects/sample1");
|
||||
|
||||
const allExpectedOutputs = ["/src/tests/index.js",
|
||||
"/src/core/index.js", "/src/core/index.d.ts",
|
||||
"/src/logic/index.js", "/src/logic/index.d.ts"];
|
||||
|
||||
describe("tsbuild - sanity check of clean build of 'sample1' project", () => {
|
||||
it("can build the sample project 'sample1' without error", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
|
||||
clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(/*empty*/);
|
||||
|
||||
// Check for outputs. Not an exhaustive list
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - dry builds", () => {
|
||||
it("doesn't write any files in a dry build", () => {
|
||||
clearDiagnostics();
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: true, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0);
|
||||
|
||||
// Check for outputs to not be written. Not an exhaustive list
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(!fs.existsSync(output), `Expect file ${output} to not exist`);
|
||||
}
|
||||
});
|
||||
|
||||
it("indicates that it would skip builds during a dry build", () => {
|
||||
clearDiagnostics();
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
|
||||
let builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
tick();
|
||||
|
||||
clearDiagnostics();
|
||||
builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: true, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - clean builds", () => {
|
||||
it("removes all files it built", () => {
|
||||
clearDiagnostics();
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
// Verify they exist
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
}
|
||||
builder.cleanAllProjects();
|
||||
// Verify they are gone
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(!fs.existsSync(output), `Expect file ${output} to not exist`);
|
||||
}
|
||||
// Subsequent clean shouldn't throw / etc
|
||||
builder.cleanAllProjects();
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - force builds", () => {
|
||||
it("always builds under --force", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: true, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
let currentTime = time();
|
||||
checkOutputTimestamps(currentTime);
|
||||
|
||||
tick();
|
||||
Debug.assert(time() !== currentTime, "Time moves on");
|
||||
currentTime = time();
|
||||
builder.buildAllProjects();
|
||||
checkOutputTimestamps(currentTime);
|
||||
|
||||
function checkOutputTimestamps(expected: number) {
|
||||
// Check timestamps
|
||||
for (const output of allExpectedOutputs) {
|
||||
const actual = fs.statSync(output).mtimeMs;
|
||||
assert(actual === expected, `File ${output} has timestamp ${actual}, expected ${expected}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - can detect when and what to rebuild", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: true });
|
||||
|
||||
it("Builds the project", () => {
|
||||
clearDiagnostics();
|
||||
builder.resetBuildContext();
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0);
|
||||
tick();
|
||||
});
|
||||
|
||||
// All three projects are up to date
|
||||
it("Detects that all projects are up to date", () => {
|
||||
clearDiagnostics();
|
||||
builder.resetBuildContext();
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2);
|
||||
tick();
|
||||
});
|
||||
|
||||
// Update a file in the leaf node (tests), only it should rebuild the last one
|
||||
it("Only builds the leaf node project", () => {
|
||||
clearDiagnostics();
|
||||
fs.writeFileSync("/src/tests/index.ts", "const m = 10;");
|
||||
builder.resetBuildContext();
|
||||
builder.buildAllProjects();
|
||||
|
||||
assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
|
||||
Diagnostics.Building_project_0);
|
||||
tick();
|
||||
});
|
||||
|
||||
// Update a file in the parent (without affecting types), should get fast downstream builds
|
||||
it("Detects type-only changes in upstream projects", () => {
|
||||
clearDiagnostics();
|
||||
replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET");
|
||||
builder.resetBuildContext();
|
||||
builder.buildAllProjects();
|
||||
|
||||
assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
|
||||
Diagnostics.Updating_output_timestamps_of_project_0,
|
||||
Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
|
||||
Diagnostics.Updating_output_timestamps_of_project_0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - downstream-blocked compilations", () => {
|
||||
it("won't build downstream projects if upstream projects have errors", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: true });
|
||||
|
||||
clearDiagnostics();
|
||||
|
||||
// Induce an error in the middle project
|
||||
replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`);
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(
|
||||
Diagnostics.Projects_in_this_build_Colon_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Property_0_does_not_exist_on_type_1,
|
||||
Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors,
|
||||
Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsbuild - project invalidation", () => {
|
||||
it("invalidates projects correctly", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
|
||||
clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(/*empty*/);
|
||||
|
||||
// Update a timestamp in the middle project
|
||||
tick();
|
||||
touch(fs, "/src/logic/index.ts");
|
||||
// Because we haven't reset the build context, the builder should assume there's nothing to do right now
|
||||
const status = builder.getUpToDateStatusOfFile(builder.resolveProjectName("/src/logic")!);
|
||||
assert.equal(status.type, UpToDateStatusType.UpToDate, "Project should be assumed to be up-to-date");
|
||||
|
||||
// Rebuild this project
|
||||
tick();
|
||||
builder.invalidateProject("/src/logic");
|
||||
builder.buildInvalidatedProjects();
|
||||
// The file should be updated
|
||||
assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt");
|
||||
assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should *not* have been rebuilt");
|
||||
|
||||
// Build downstream projects should update 'tests', but not 'core'
|
||||
tick();
|
||||
builder.buildDependentInvalidatedProjects();
|
||||
assert.equal(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt");
|
||||
assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export namespace OutFile {
|
||||
const outFileFs = loadProjectFromDisk("../../tests/projects/outfile-concat");
|
||||
|
||||
describe("tsbuild - baseline sectioned sourcemaps", () => {
|
||||
const fs = outFileFs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, buildHost, ["/src/third"], { dry: false, force: false, verbose: false });
|
||||
clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
assertDiagnosticMessages(/*none*/);
|
||||
|
||||
const files = [
|
||||
"/src/third/thirdjs/output/third-output.js",
|
||||
"/src/third/thirdjs/output/third-output.js.map"
|
||||
];
|
||||
|
||||
for (const file of files) {
|
||||
it(`Generates files matching the baseline - ${file}`, () => {
|
||||
Harness.Baseline.runBaseline(getBaseFileName(file), () => {
|
||||
return fs.readFileSync(file, "utf-8");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it(`Generates files matching the baseline - file listing for outFile-concat`, () => {
|
||||
Harness.Baseline.runBaseline("outfile-concat-fileListing.txt", () => {
|
||||
return fs.getFileListing();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe("tsbuild - graph-ordering", () => {
|
||||
const fs = new vfs.FileSystem(false);
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const deps: [string, string][] = [
|
||||
["A", "B"],
|
||||
["B", "C"],
|
||||
["A", "C"],
|
||||
["B", "D"],
|
||||
["C", "D"],
|
||||
["C", "E"],
|
||||
["F", "E"]
|
||||
];
|
||||
|
||||
writeProjects(fs, ["A", "B", "C", "D", "E", "F", "G"], deps);
|
||||
|
||||
it("orders the graph correctly - specify two roots", () => {
|
||||
checkGraphOrdering(["A", "G"], ["A", "B", "C", "D", "E", "G"]);
|
||||
});
|
||||
|
||||
it("orders the graph correctly - multiple parts of the same graph in various orders", () => {
|
||||
checkGraphOrdering(["A"], ["A", "B", "C", "D", "E"]);
|
||||
checkGraphOrdering(["A", "C", "D"], ["A", "B", "C", "D", "E"]);
|
||||
checkGraphOrdering(["D", "C", "A"], ["A", "B", "C", "D", "E"]);
|
||||
});
|
||||
|
||||
it("orders the graph correctly - other orderings", () => {
|
||||
checkGraphOrdering(["F"], ["F", "E"]);
|
||||
checkGraphOrdering(["E"], ["E"]);
|
||||
checkGraphOrdering(["F", "C", "A"], ["A", "B", "C", "D", "E", "F"]);
|
||||
});
|
||||
|
||||
function checkGraphOrdering(rootNames: string[], expectedBuildSet: string[]) {
|
||||
const builder = createSolutionBuilder(host, buildHost, rootNames, { dry: true, force: false, verbose: false });
|
||||
|
||||
const projFileNames = rootNames.map(getProjectFileName);
|
||||
const graph = builder.getBuildGraph(projFileNames);
|
||||
if (graph === undefined) throw new Error("Graph shouldn't be undefined");
|
||||
|
||||
assert.sameMembers(graph.buildQueue, expectedBuildSet.map(getProjectFileName));
|
||||
|
||||
for (const dep of deps) {
|
||||
const child = getProjectFileName(dep[0]);
|
||||
if (graph.buildQueue.indexOf(child) < 0) continue;
|
||||
const parent = getProjectFileName(dep[1]);
|
||||
assert.isAbove(graph.buildQueue.indexOf(child), graph.buildQueue.indexOf(parent), `Expecting child ${child} to be built after parent ${parent}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getProjectFileName(proj: string) {
|
||||
return `/project/${proj}/tsconfig.json` as ResolvedConfigFileName;
|
||||
}
|
||||
|
||||
function writeProjects(fileSystem: vfs.FileSystem, projectNames: string[], deps: [string, string][]): string[] {
|
||||
const projFileNames: string[] = [];
|
||||
for (const dep of deps) {
|
||||
if (projectNames.indexOf(dep[0]) < 0) throw new Error(`Invalid dependency - project ${dep[0]} does not exist`);
|
||||
if (projectNames.indexOf(dep[1]) < 0) throw new Error(`Invalid dependency - project ${dep[1]} does not exist`);
|
||||
}
|
||||
for (const proj of projectNames) {
|
||||
fileSystem.mkdirpSync(`/project/${proj}`);
|
||||
fileSystem.writeFileSync(`/project/${proj}/${proj}.ts`, "export {}");
|
||||
const configFileName = getProjectFileName(proj);
|
||||
const configContent = JSON.stringify({
|
||||
compilerOptions: { composite: true },
|
||||
files: [`./${proj}.ts`],
|
||||
references: deps.filter(d => d[0] === proj).map(d => ({ path: `../${d[1]}` }))
|
||||
}, undefined, 2);
|
||||
fileSystem.writeFileSync(configFileName, configContent);
|
||||
projFileNames.push(configFileName);
|
||||
}
|
||||
return projFileNames;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
const old = fs.readFileSync(path, "utf-8");
|
||||
if (old.indexOf(oldText) < 0) {
|
||||
throw new Error(`Text "${oldText}" does not exist in file ${path}`);
|
||||
}
|
||||
const newContent = old.replace(oldText, newText);
|
||||
fs.writeFileSync(path, newContent, "utf-8");
|
||||
}
|
||||
|
||||
function assertDiagnosticMessages(...expected: DiagnosticMessage[]) {
|
||||
const actual = lastDiagnostics.slice();
|
||||
if (actual.length !== expected.length) {
|
||||
assert.fail<any>(actual, expected, `Diagnostic arrays did not match - got\r\n${actual.map(a => " " + a.messageText).join("\r\n")}\r\nexpected\r\n${expected.map(e => " " + e.message).join("\r\n")}`);
|
||||
}
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
if (actual[i].code !== expected[i].code) {
|
||||
assert.fail(actual[i].messageText, expected[i].message, `Mismatched error code - expected diagnostic ${i} "${actual[i].messageText}" to match ${expected[i].message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearDiagnostics() {
|
||||
lastDiagnostics = [];
|
||||
}
|
||||
|
||||
export function printDiagnostics(header = "== Diagnostics ==") {
|
||||
const out = createDiagnosticReporter(sys);
|
||||
sys.write(header + "\r\n");
|
||||
for (const d of lastDiagnostics) {
|
||||
out(d);
|
||||
}
|
||||
}
|
||||
|
||||
function tick() {
|
||||
currentTime += 60_000;
|
||||
}
|
||||
|
||||
function time() {
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
function touch(fs: vfs.FileSystem, path: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
fs.utimesSync(path, new Date(time()), new Date(time()));
|
||||
}
|
||||
|
||||
function loadProjectFromDisk(root: string): vfs.FileSystem {
|
||||
const fs = new vfs.FileSystem(/*ignoreCase*/ false, { time });
|
||||
const rootPath = resolvePath(__dirname, root);
|
||||
loadFsMirror(fs, rootPath, "/src");
|
||||
fs.mkdirpSync("/lib");
|
||||
const libs = ["es5", "dom", "webworker.importscripts", "scripthost"];
|
||||
for (const lib of libs) {
|
||||
const content = Harness.IO.readFile(combinePaths(Harness.libFolder, `lib.${lib}.d.ts`));
|
||||
if (content === undefined) {
|
||||
throw new Error(`Failed to read lib ${lib}`);
|
||||
}
|
||||
fs.writeFileSync(`/lib/lib.${lib}.d.ts`, content);
|
||||
}
|
||||
fs.writeFileSync("/lib/lib.d.ts", Harness.IO.readFile(combinePaths(Harness.libFolder, "lib.d.ts"))!);
|
||||
fs.meta.set("defaultLibLocation", "/lib");
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
}
|
||||
|
||||
function loadFsMirror(vfs: vfs.FileSystem, localRoot: string, virtualRoot: string) {
|
||||
vfs.mkdirpSync(virtualRoot);
|
||||
for (const path of Harness.IO.readDirectory(localRoot)) {
|
||||
const file = getBaseFileName(path);
|
||||
vfs.writeFileSync(virtualRoot + "/" + file, Harness.IO.readFile(localRoot + "/" + file)!);
|
||||
}
|
||||
for (const dir of Harness.IO.getDirectories(localRoot)) {
|
||||
loadFsMirror(vfs, localRoot + "/" + dir, virtualRoot + "/" + dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,7 +466,7 @@ namespace ts.projectSystem {
|
||||
return newRequest;
|
||||
}
|
||||
|
||||
export function openFilesForSession(files: File[], session: server.Session) {
|
||||
export function openFilesForSession(files: ReadonlyArray<File>, session: server.Session) {
|
||||
for (const file of files) {
|
||||
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
|
||||
session.executeCommand(request);
|
||||
@@ -6192,6 +6192,69 @@ namespace ts.projectSystem {
|
||||
renameLocation: { line: 2, offset: 3 },
|
||||
});
|
||||
});
|
||||
|
||||
it("handles text changes in tsconfig.json", () => {
|
||||
const aTs = {
|
||||
path: "/a.ts",
|
||||
content: "export const a = 0;",
|
||||
};
|
||||
const tsconfig = {
|
||||
path: "/tsconfig.json",
|
||||
content: '{ "files": ["./a.ts"] }',
|
||||
};
|
||||
|
||||
const session = createSession(createServerHost([aTs, tsconfig]));
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
const response1 = session.executeCommandSeq<server.protocol.GetEditsForRefactorRequest>({
|
||||
command: server.protocol.CommandTypes.GetEditsForRefactor,
|
||||
arguments: {
|
||||
refactor: "Move to a new file",
|
||||
action: "Move to a new file",
|
||||
file: "/a.ts",
|
||||
startLine: 1,
|
||||
startOffset: 1,
|
||||
endLine: 1,
|
||||
endOffset: 20,
|
||||
},
|
||||
}).response;
|
||||
assert.deepEqual(response1, {
|
||||
edits: [
|
||||
{
|
||||
fileName: "/a.ts",
|
||||
textChanges: [
|
||||
{
|
||||
start: { line: 1, offset: 1 },
|
||||
end: { line: 1, offset: 20 },
|
||||
newText: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fileName: "/tsconfig.json",
|
||||
textChanges: [
|
||||
{
|
||||
start: { line: 1, offset: 21 },
|
||||
end: { line: 1, offset: 21 },
|
||||
newText: ", \"./a.1.ts\"",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fileName: "/a.1.ts",
|
||||
textChanges: [
|
||||
{
|
||||
start: { line: 0, offset: 0 },
|
||||
end: { line: 0, offset: 0 },
|
||||
newText: "export const a = 0;",
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
renameFilename: undefined,
|
||||
renameLocation: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsserverProjectSystem CachingFileSystemInformation", () => {
|
||||
@@ -7501,8 +7564,8 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("tsserverProjectSystem Watched recursive directories with windows style file system", () => {
|
||||
function verifyWatchedDirectories(useProjectAtRoot: boolean) {
|
||||
const root = useProjectAtRoot ? "c:/" : "c:/myfolder/allproject/";
|
||||
function verifyWatchedDirectories(rootedPath: string, useProjectAtRoot: boolean) {
|
||||
const root = useProjectAtRoot ? rootedPath : `${rootedPath}myfolder/allproject/`;
|
||||
const configFile: File = {
|
||||
path: root + "project/tsconfig.json",
|
||||
content: "{}"
|
||||
@@ -7531,12 +7594,22 @@ namespace ts.projectSystem {
|
||||
].concat(useProjectAtRoot ? [] : [root + nodeModulesAtTypes]), /*recursive*/ true);
|
||||
}
|
||||
|
||||
it("When project is in rootFolder", () => {
|
||||
verifyWatchedDirectories(/*useProjectAtRoot*/ true);
|
||||
function verifyRootedDirectoryWatch(rootedPath: string) {
|
||||
it("When project is in rootFolder of style c:/", () => {
|
||||
verifyWatchedDirectories(rootedPath, /*useProjectAtRoot*/ true);
|
||||
});
|
||||
|
||||
it("When files at some folder other than root", () => {
|
||||
verifyWatchedDirectories(rootedPath, /*useProjectAtRoot*/ false);
|
||||
});
|
||||
}
|
||||
|
||||
describe("for rootFolder of style c:/", () => {
|
||||
verifyRootedDirectoryWatch("c:/");
|
||||
});
|
||||
|
||||
it("When files at some folder other than root", () => {
|
||||
verifyWatchedDirectories(/*useProjectAtRoot*/ false);
|
||||
describe("for rootFolder of style c:/users/username", () => {
|
||||
verifyRootedDirectoryWatch("c:/users/username/");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+38
-9
@@ -5,6 +5,11 @@ namespace vfs {
|
||||
*/
|
||||
export const builtFolder = "/.ts";
|
||||
|
||||
/**
|
||||
* Posix-style path to additional mountable folders (./tests/projects in this repo)
|
||||
*/
|
||||
export const projectsFolder = "/.projects";
|
||||
|
||||
/**
|
||||
* Posix-style path to additional test libraries
|
||||
*/
|
||||
@@ -348,10 +353,7 @@ namespace vfs {
|
||||
if (!result.node) this._mkdir(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print diagnostic information about the structure of the file system to the console.
|
||||
*/
|
||||
public debugPrint(): void {
|
||||
public getFileListing(): string {
|
||||
let result = "";
|
||||
const printLinks = (dirname: string | undefined, links: collections.SortedMap<string, Inode>) => {
|
||||
const iterator = collections.getIterator(links);
|
||||
@@ -379,7 +381,14 @@ namespace vfs {
|
||||
}
|
||||
};
|
||||
printLinks(/*dirname*/ undefined, this._getRootLinks());
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print diagnostic information about the structure of the file system to the console.
|
||||
*/
|
||||
public debugPrint(): void {
|
||||
console.log(this.getFileListing());
|
||||
}
|
||||
|
||||
// POSIX API (aligns with NodeJS "fs" module API)
|
||||
@@ -404,7 +413,25 @@ namespace vfs {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file status.
|
||||
* Change file access times
|
||||
*
|
||||
* NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module.
|
||||
*/
|
||||
public utimesSync(path: string, atime: Date, mtime: Date) {
|
||||
if (this.isReadonly) throw createIOError("EROFS");
|
||||
if (!isFinite(+atime) || !isFinite(+mtime)) throw createIOError("EINVAL");
|
||||
|
||||
const entry = this._walk(this._resolve(path));
|
||||
if (!entry || !entry.node) {
|
||||
throw createIOError("ENOENT");
|
||||
}
|
||||
entry.node.atimeMs = +atime;
|
||||
entry.node.mtimeMs = +mtime;
|
||||
entry.node.ctimeMs = this.time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file status. If `path` is a symbolic link, it is dereferenced.
|
||||
*
|
||||
* @link http://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html
|
||||
*
|
||||
@@ -414,9 +441,10 @@ namespace vfs {
|
||||
return this._stat(this._walk(this._resolve(path), /*noFollow*/ true));
|
||||
}
|
||||
|
||||
|
||||
private _stat(entry: WalkResult) {
|
||||
const node = entry.node;
|
||||
if (!node) throw createIOError("ENOENT");
|
||||
if (!node) throw createIOError(`ENOENT`, entry.realpath);
|
||||
return new Stats(
|
||||
node.dev,
|
||||
node.ino,
|
||||
@@ -1127,8 +1155,8 @@ namespace vfs {
|
||||
EROFS: "file system is read-only"
|
||||
});
|
||||
|
||||
export function createIOError(code: keyof typeof IOErrorMessages) {
|
||||
const err: NodeJS.ErrnoException = new Error(`${code}: ${IOErrorMessages[code]}`);
|
||||
export function createIOError(code: keyof typeof IOErrorMessages, details = "") {
|
||||
const err: NodeJS.ErrnoException = new Error(`${code}: ${IOErrorMessages[code]} ${details}`);
|
||||
err.code = code;
|
||||
if (Error.captureStackTrace) Error.captureStackTrace(err, createIOError);
|
||||
return err;
|
||||
@@ -1282,6 +1310,7 @@ namespace vfs {
|
||||
files: {
|
||||
[builtFolder]: new Mount(vpath.resolve(host.getWorkspaceRoot(), "built/local"), resolver),
|
||||
[testLibFolder]: new Mount(vpath.resolve(host.getWorkspaceRoot(), "tests/lib"), resolver),
|
||||
[projectsFolder]: new Mount(vpath.resolve(host.getWorkspaceRoot(), "tests/projects"), resolver),
|
||||
[srcFolder]: {}
|
||||
},
|
||||
cwd: srcFolder,
|
||||
|
||||
@@ -1947,12 +1947,18 @@
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Nepovedlo se najít definici knihovny pro {0}.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Nepovedlo se najít definici knihovny pro {0}. Neměli jste na mysli spíš {1}?]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -1947,6 +1947,18 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
@@ -8721,6 +8733,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. A type parameter name was expected without curly braces.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Jeton inattendu. Un nom de paramètre de type est attendu sans accolades.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_expected_1179" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. '{' expected.]]></Val>
|
||||
|
||||
@@ -1935,6 +1935,24 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[La definizione della libreria per '{0}' non è stata trovata.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[La definizione della libreria per '{0}' non è stata trovata. Si intendeva '{1}'?]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
|
||||
@@ -1935,6 +1935,18 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
@@ -8712,6 +8724,9 @@
|
||||
<Item ItemId=";Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. A type parameter name was expected without curly braces.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[予期しないトークンです。型パラメーター名には、中かっこを含めることはできません。]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -1935,6 +1935,18 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
@@ -8709,6 +8721,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. A type parameter name was expected without curly braces.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[예기치 않은 토큰입니다. 중괄호가 없는 형식 매개 변수 이름이 필요합니다.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_expected_1179" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. '{' expected.]]></Val>
|
||||
|
||||
@@ -1928,6 +1928,18 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
@@ -8699,6 +8711,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. A type parameter name was expected without curly braces.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Token inesperado. Um nome de parâmetro de tipo era esperado sem chaves.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_expected_1179" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. '{' expected.]]></Val>
|
||||
|
||||
@@ -1934,6 +1934,18 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_2726" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'.]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_lib_definition_for_0_Did_you_mean_1_2727" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find lib definition for '{0}'. Did you mean '{1}'?]]></Val>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Cannot_find_module_0_2307" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Cannot find module '{0}'.]]></Val>
|
||||
@@ -8708,6 +8720,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. A type parameter name was expected without curly braces.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Непредвиденная лексема. Ожидалось имя параметра типа без фигурных скобок.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Unexpected_token_expected_1179" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Unexpected token. '{' expected.]]></Val>
|
||||
|
||||
@@ -451,6 +451,7 @@ namespace ts.server {
|
||||
kind: tree.kind,
|
||||
kindModifiers: tree.kindModifiers,
|
||||
spans: tree.spans.map(span => this.decodeSpan(span, fileName, lineMap)),
|
||||
nameSpan: tree.nameSpan && this.decodeSpan(tree.nameSpan, fileName, lineMap),
|
||||
childItems: map(tree.childItems, item => this.decodeNavigationTree(item, fileName, lineMap))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -550,6 +550,12 @@ namespace ts.server {
|
||||
return this.program.getSourceFileByPath(path);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
getSourceFileOrConfigFile(path: Path): SourceFile | undefined {
|
||||
const options = this.program.getCompilerOptions();
|
||||
return path === options.configFilePath ? options.configFile : this.getSourceFile(path);
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.program) {
|
||||
// if we have a program - release all files that are enlisted in program but arent root
|
||||
@@ -629,8 +635,8 @@ namespace ts.server {
|
||||
return this.rootFiles;
|
||||
}
|
||||
return map(this.program.getSourceFiles(), sourceFile => {
|
||||
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.path);
|
||||
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.`);
|
||||
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath || sourceFile.path);
|
||||
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`);
|
||||
return scriptInfo!;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2555,6 +2555,7 @@ namespace ts.server.protocol {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
spans: TextSpan[];
|
||||
nameSpan: TextSpan | undefined;
|
||||
childItems?: NavigationTree[];
|
||||
}
|
||||
|
||||
|
||||
+33
-21
@@ -1507,6 +1507,7 @@ namespace ts.server {
|
||||
kind: tree.kind,
|
||||
kindModifiers: tree.kindModifiers,
|
||||
spans: tree.spans.map(span => this.toLocationTextSpan(span, scriptInfo)),
|
||||
nameSpan: tree.nameSpan && this.toLocationTextSpan(tree.nameSpan, scriptInfo),
|
||||
childItems: map(tree.childItems, item => this.toLocationNavigationTree(item, scriptInfo))
|
||||
};
|
||||
}
|
||||
@@ -1770,20 +1771,10 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray<FileTextChanges>): protocol.FileCodeEdits[] {
|
||||
return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!));
|
||||
}
|
||||
|
||||
private mapTextChangesToCodeEditsUsingScriptinfo(textChanges: FileTextChanges, scriptInfo: ScriptInfo | undefined): protocol.FileCodeEdits {
|
||||
Debug.assert(!!textChanges.isNewFile === !scriptInfo);
|
||||
if (scriptInfo) {
|
||||
return {
|
||||
fileName: textChanges.fileName,
|
||||
textChanges: textChanges.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo))
|
||||
};
|
||||
}
|
||||
else {
|
||||
return this.convertNewFileTextChangeToCodeEdit(textChanges);
|
||||
}
|
||||
return textChanges.map(change => {
|
||||
const path = normalizedPathToPath(toNormalizedPath(change.fileName), this.host.getCurrentDirectory(), fileName => this.getCanonicalFileName(fileName));
|
||||
return mapTextChangesToCodeEdits(change, project.getSourceFileOrConfigFile(path));
|
||||
});
|
||||
}
|
||||
|
||||
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
|
||||
@@ -1794,13 +1785,6 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
private convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
|
||||
Debug.assert(textChanges.textChanges.length === 1);
|
||||
const change = first(textChanges.textChanges);
|
||||
Debug.assert(change.span.start === 0 && change.span.length === 0);
|
||||
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
|
||||
}
|
||||
|
||||
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
@@ -2279,6 +2263,34 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
|
||||
Debug.assert(!!textChanges.isNewFile === !sourceFile);
|
||||
if (sourceFile) {
|
||||
return {
|
||||
fileName: textChanges.fileName,
|
||||
textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, sourceFile)),
|
||||
};
|
||||
}
|
||||
else {
|
||||
return convertNewFileTextChangeToCodeEdit(textChanges);
|
||||
}
|
||||
}
|
||||
|
||||
function convertTextChangeToCodeEdit(change: TextChange, sourceFile: SourceFile): protocol.CodeEdit {
|
||||
return {
|
||||
start: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start)),
|
||||
end: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start + change.span.length)),
|
||||
newText: change.newText ? change.newText : "",
|
||||
};
|
||||
}
|
||||
|
||||
function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
|
||||
Debug.assert(textChanges.textChanges.length === 1);
|
||||
const change = first(textChanges.textChanges);
|
||||
Debug.assert(change.span.start === 0 && change.span.length === 0);
|
||||
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
|
||||
}
|
||||
|
||||
export interface HandlerResponse {
|
||||
response?: {};
|
||||
responseRequired?: boolean;
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace ts.codefix {
|
||||
getCodeActions(context) {
|
||||
const { sourceFile, program, preferences } = context;
|
||||
const changes = textChanges.ChangeTracker.with(context, changes => {
|
||||
const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target!, preferences);
|
||||
const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target!, getQuotePreference(sourceFile, preferences));
|
||||
if (moduleExportsChangedToDefault) {
|
||||
for (const importingFile of program.getSourceFiles()) {
|
||||
fixImportOfModuleExports(importingFile, sourceFile, changes, preferences);
|
||||
fixImportOfModuleExports(importingFile, sourceFile, changes, getQuotePreference(importingFile, preferences));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -17,7 +17,7 @@ namespace ts.codefix {
|
||||
},
|
||||
});
|
||||
|
||||
function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: SourceFile, changes: textChanges.ChangeTracker, preferences: UserPreferences) {
|
||||
function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: SourceFile, changes: textChanges.ChangeTracker, quotePreference: QuotePreference) {
|
||||
for (const moduleSpecifier of importingFile.imports) {
|
||||
const imported = getResolvedModule(importingFile, moduleSpecifier.text);
|
||||
if (!imported || imported.resolvedFileName !== exportingFile.fileName) {
|
||||
@@ -27,7 +27,7 @@ namespace ts.codefix {
|
||||
const importNode = importFromModuleSpecifier(moduleSpecifier);
|
||||
switch (importNode.kind) {
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
changes.replaceNode(importingFile, importNode, makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, preferences));
|
||||
changes.replaceNode(importingFile, importNode, makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference));
|
||||
break;
|
||||
case SyntaxKind.CallExpression:
|
||||
if (isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) {
|
||||
@@ -39,13 +39,13 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
/** @returns Whether we converted a `module.exports =` to a default export. */
|
||||
function convertFileToEs6Module(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, target: ScriptTarget, preferences: UserPreferences): ModuleExportsChanged {
|
||||
function convertFileToEs6Module(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, target: ScriptTarget, quotePreference: QuotePreference): ModuleExportsChanged {
|
||||
const identifiers: Identifiers = { original: collectFreeIdentifiers(sourceFile), additional: createMap<true>() };
|
||||
const exports = collectExportRenames(sourceFile, checker, identifiers);
|
||||
convertExportsAccesses(sourceFile, exports, changes);
|
||||
let moduleExportsChangedToDefault = false;
|
||||
for (const statement of sourceFile.statements) {
|
||||
const moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, preferences);
|
||||
const moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, quotePreference);
|
||||
moduleExportsChangedToDefault = moduleExportsChangedToDefault || moduleExportsChanged;
|
||||
}
|
||||
return moduleExportsChangedToDefault;
|
||||
@@ -98,10 +98,10 @@ namespace ts.codefix {
|
||||
/** Whether `module.exports =` was changed to `export default` */
|
||||
type ModuleExportsChanged = boolean;
|
||||
|
||||
function convertStatement(sourceFile: SourceFile, statement: Statement, checker: TypeChecker, changes: textChanges.ChangeTracker, identifiers: Identifiers, target: ScriptTarget, exports: ExportRenames, preferences: UserPreferences): ModuleExportsChanged {
|
||||
function convertStatement(sourceFile: SourceFile, statement: Statement, checker: TypeChecker, changes: textChanges.ChangeTracker, identifiers: Identifiers, target: ScriptTarget, exports: ExportRenames, quotePreference: QuotePreference): ModuleExportsChanged {
|
||||
switch (statement.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
convertVariableStatement(sourceFile, statement as VariableStatement, changes, checker, identifiers, target, preferences);
|
||||
convertVariableStatement(sourceFile, statement as VariableStatement, changes, checker, identifiers, target, quotePreference);
|
||||
return false;
|
||||
case SyntaxKind.ExpressionStatement: {
|
||||
const { expression } = statement as ExpressionStatement;
|
||||
@@ -109,7 +109,7 @@ namespace ts.codefix {
|
||||
case SyntaxKind.CallExpression: {
|
||||
if (isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true)) {
|
||||
// For side-effecting require() call, just make a side-effecting import.
|
||||
changes.replaceNode(sourceFile, statement, makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0], preferences));
|
||||
changes.replaceNode(sourceFile, statement, makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0], quotePreference));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -125,7 +125,15 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function convertVariableStatement(sourceFile: SourceFile, statement: VariableStatement, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers, target: ScriptTarget, preferences: UserPreferences): void {
|
||||
function convertVariableStatement(
|
||||
sourceFile: SourceFile,
|
||||
statement: VariableStatement,
|
||||
changes: textChanges.ChangeTracker,
|
||||
checker: TypeChecker,
|
||||
identifiers: Identifiers,
|
||||
target: ScriptTarget,
|
||||
quotePreference: QuotePreference,
|
||||
): void {
|
||||
const { declarationList } = statement;
|
||||
let foundImport = false;
|
||||
const newNodes = flatMap(declarationList.declarations, decl => {
|
||||
@@ -138,11 +146,11 @@ namespace ts.codefix {
|
||||
}
|
||||
else if (isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) {
|
||||
foundImport = true;
|
||||
return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target, preferences);
|
||||
return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target, quotePreference);
|
||||
}
|
||||
else if (isPropertyAccessExpression(initializer) && isRequireCall(initializer.expression, /*checkArgumentIsStringLiteralLike*/ true)) {
|
||||
foundImport = true;
|
||||
return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, preferences);
|
||||
return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, quotePreference);
|
||||
}
|
||||
}
|
||||
// Move it out to its own variable statement. (This will not be used if `!foundImport`)
|
||||
@@ -155,20 +163,20 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
/** Converts `const name = require("moduleSpecifier").propertyName` */
|
||||
function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: StringLiteralLike, identifiers: Identifiers, preferences: UserPreferences): ReadonlyArray<Node> {
|
||||
function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: StringLiteralLike, identifiers: Identifiers, quotePreference: QuotePreference): ReadonlyArray<Node> {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern: {
|
||||
// `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;`
|
||||
const tmp = makeUniqueName(propertyName, identifiers);
|
||||
return [
|
||||
makeSingleImport(tmp, propertyName, moduleSpecifier, preferences),
|
||||
makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference),
|
||||
makeConst(/*modifiers*/ undefined, name, createIdentifier(tmp)),
|
||||
];
|
||||
}
|
||||
case SyntaxKind.Identifier:
|
||||
// `const a = require("b").c` --> `import { c as a } from "./b";
|
||||
return [makeSingleImport(name.text, propertyName, moduleSpecifier, preferences)];
|
||||
return [makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)];
|
||||
default:
|
||||
return Debug.assertNever(name);
|
||||
}
|
||||
@@ -340,7 +348,7 @@ namespace ts.codefix {
|
||||
checker: TypeChecker,
|
||||
identifiers: Identifiers,
|
||||
target: ScriptTarget,
|
||||
preferences: UserPreferences,
|
||||
quotePreference: QuotePreference,
|
||||
): ReadonlyArray<Node> {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern: {
|
||||
@@ -349,7 +357,7 @@ namespace ts.codefix {
|
||||
? undefined
|
||||
: makeImportSpecifier(e.propertyName && (e.propertyName as Identifier).text, e.name.text)); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217)
|
||||
if (importSpecifiers) {
|
||||
return [makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, preferences)];
|
||||
return [makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)];
|
||||
}
|
||||
}
|
||||
// falls through -- object destructuring has an interesting pattern and must be a variable declaration
|
||||
@@ -360,12 +368,12 @@ namespace ts.codefix {
|
||||
*/
|
||||
const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers);
|
||||
return [
|
||||
makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, preferences),
|
||||
makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference),
|
||||
makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), createIdentifier(tmp)),
|
||||
];
|
||||
}
|
||||
case SyntaxKind.Identifier:
|
||||
return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, preferences);
|
||||
return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference);
|
||||
default:
|
||||
return Debug.assertNever(name);
|
||||
}
|
||||
@@ -375,7 +383,7 @@ namespace ts.codefix {
|
||||
* Convert `import x = require("x").`
|
||||
* Also converts uses like `x.y()` to `y()` and uses a named import.
|
||||
*/
|
||||
function convertSingleIdentifierImport(file: SourceFile, name: Identifier, moduleSpecifier: StringLiteralLike, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers, preferences: UserPreferences): ReadonlyArray<Node> {
|
||||
function convertSingleIdentifierImport(file: SourceFile, name: Identifier, moduleSpecifier: StringLiteralLike, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers, quotePreference: QuotePreference): ReadonlyArray<Node> {
|
||||
const nameSymbol = checker.getSymbolAtLocation(name);
|
||||
// Maps from module property name to name actually used. (The same if there isn't shadowing.)
|
||||
const namedBindingsNames = createMap<string>();
|
||||
@@ -410,7 +418,7 @@ namespace ts.codefix {
|
||||
// If it was unused, ensure that we at least import *something*.
|
||||
needDefaultImport = true;
|
||||
}
|
||||
return [makeImport(needDefaultImport ? getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, preferences)];
|
||||
return [makeImport(needDefaultImport ? getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)];
|
||||
}
|
||||
|
||||
// Identifiers helpers
|
||||
@@ -488,10 +496,10 @@ namespace ts.codefix {
|
||||
getSynthesizedDeepClones(cls.members));
|
||||
}
|
||||
|
||||
function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike, preferences: UserPreferences): ImportDeclaration {
|
||||
function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike, quotePreference: QuotePreference): ImportDeclaration {
|
||||
return propertyName === "default"
|
||||
? makeImport(createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, preferences)
|
||||
: makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, preferences);
|
||||
? makeImport(createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference)
|
||||
: makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference);
|
||||
}
|
||||
|
||||
function makeImportSpecifier(propertyName: string | undefined, name: string): ImportSpecifier {
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace ts.codefix {
|
||||
const variations: CodeFixAction[] = [];
|
||||
|
||||
// import Bluebird from "bluebird";
|
||||
variations.push(createAction(context, sourceFile, node, makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, context.preferences)));
|
||||
variations.push(createAction(context, sourceFile, node, makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, getQuotePreference(sourceFile, context.preferences))));
|
||||
|
||||
if (getEmitModuleKind(opts) === ModuleKind.CommonJS) {
|
||||
// import Bluebird = require("bluebird");
|
||||
|
||||
@@ -109,14 +109,8 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined {
|
||||
if (type.flags & TypeFlags.String) {
|
||||
return createLiteral("");
|
||||
}
|
||||
else if (type.flags & TypeFlags.Number) {
|
||||
return createNumericLiteral("0");
|
||||
}
|
||||
else if (type.flags & TypeFlags.Boolean) {
|
||||
return createFalse();
|
||||
if (type.flags & TypeFlags.BooleanLiteral) {
|
||||
return type === checker.getFalseType() ? createFalse() : createTrue();
|
||||
}
|
||||
else if (type.isLiteral()) {
|
||||
return createLiteral(type.value);
|
||||
@@ -133,6 +127,9 @@ namespace ts.codefix {
|
||||
|
||||
return createNew(createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
|
||||
}
|
||||
else if (checker.isArrayLikeType(type)) {
|
||||
return createArrayLiteral();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ namespace ts.codefix {
|
||||
switch (token.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
tryDeleteIdentifier(changes, sourceFile, <Identifier>token, deletedAncestors, checker, isFixAll);
|
||||
deleteAssignments(changes, sourceFile, token as Identifier, checker);
|
||||
break;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
@@ -163,6 +164,15 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function deleteAssignments(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier, checker: TypeChecker) {
|
||||
FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, (ref: Node) => {
|
||||
if (ref.parent.kind === SyntaxKind.PropertyAccessExpression) ref = ref.parent;
|
||||
if (ref.parent.kind === SyntaxKind.BinaryExpression && ref.parent.parent.kind === SyntaxKind.ExpressionStatement) {
|
||||
changes.deleteNode(sourceFile, ref.parent.parent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function tryDeleteDefault(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, deletedAncestors: NodeSet | undefined): void {
|
||||
if (isDeclarationName(token)) {
|
||||
if (deletedAncestors) deletedAncestors.add(token.parent);
|
||||
@@ -228,15 +238,12 @@ namespace ts.codefix {
|
||||
|
||||
case SyntaxKind.BindingElement: {
|
||||
const pattern = (parent as BindingElement).parent;
|
||||
switch (pattern.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
changes.deleteNode(sourceFile, parent); // Don't delete ','
|
||||
break;
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
changes.deleteNodeInList(sourceFile, parent);
|
||||
break;
|
||||
default:
|
||||
return Debug.assertNever(pattern);
|
||||
const preserveComma = pattern.kind === SyntaxKind.ArrayBindingPattern && parent !== last(pattern.elements);
|
||||
if (preserveComma) {
|
||||
changes.deleteNode(sourceFile, parent);
|
||||
}
|
||||
else {
|
||||
changes.deleteNodeInList(sourceFile, parent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace ts.codefix {
|
||||
|
||||
export function createMethodFromCallExpression(
|
||||
context: CodeFixContextBase,
|
||||
{ typeArguments, arguments: args }: CallExpression,
|
||||
{ typeArguments, arguments: args, parent: parent }: CallExpression,
|
||||
methodName: string,
|
||||
inJs: boolean,
|
||||
makeStatic: boolean,
|
||||
@@ -135,7 +135,7 @@ namespace ts.codefix {
|
||||
return createMethod(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*asteriskToken*/ isYieldExpression(parent) ? createToken(SyntaxKind.AsteriskToken) : undefined,
|
||||
methodName,
|
||||
/*questionToken*/ undefined,
|
||||
/*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) =>
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace ts.codefix {
|
||||
const lastImportDeclaration = findLast(sourceFile.statements, isAnyImportSyntax);
|
||||
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier);
|
||||
const quotedModuleSpecifier = createLiteral(moduleSpecifierWithoutQuotes, shouldUseSingleQuote(sourceFile, preferences));
|
||||
const quotedModuleSpecifier = makeStringLiteral(moduleSpecifierWithoutQuotes, getQuotePreference(sourceFile, preferences));
|
||||
const importDecl = importKind !== ImportKind.Equals
|
||||
? createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
@@ -225,16 +225,6 @@ namespace ts.codefix {
|
||||
return createCodeAction(Diagnostics.Import_0_from_module_1, [symbolName, moduleSpecifierWithoutQuotes], changes);
|
||||
}
|
||||
|
||||
function shouldUseSingleQuote(sourceFile: SourceFile, preferences: UserPreferences): boolean {
|
||||
if (preferences.quotePreference) {
|
||||
return preferences.quotePreference === "single";
|
||||
}
|
||||
else {
|
||||
const firstModuleSpecifier = firstOrUndefined(sourceFile.imports);
|
||||
return !!firstModuleSpecifier && !isStringDoubleQuoted(firstModuleSpecifier, sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
function createImportClauseOfKind(kind: ImportKind.Default | ImportKind.Named | ImportKind.Namespace, symbolName: string) {
|
||||
const id = createIdentifier(symbolName);
|
||||
switch (kind) {
|
||||
|
||||
@@ -37,6 +37,6 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, info: Info, preferences: UserPreferences): void {
|
||||
changes.replaceNode(sourceFile, info.importNode, makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, preferences));
|
||||
changes.replaceNode(sourceFile, info.importNode, makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, getQuotePreference(sourceFile, preferences)));
|
||||
}
|
||||
}
|
||||
|
||||
+48
-23
@@ -101,7 +101,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined {
|
||||
const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
|
||||
const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
|
||||
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
|
||||
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
|
||||
@@ -143,6 +143,10 @@ namespace ts.Completions {
|
||||
addRange(entries, getKeywordCompletions(keywordFilters));
|
||||
}
|
||||
|
||||
for (const literal of literals) {
|
||||
entries.push(createCompletionEntryForLiteral(literal));
|
||||
}
|
||||
|
||||
return { isGlobalCompletion: isInSnippetScope, isMemberCompletion, isNewIdentifierLocation, entries };
|
||||
}
|
||||
|
||||
@@ -184,6 +188,11 @@ namespace ts.Completions {
|
||||
});
|
||||
}
|
||||
|
||||
const completionNameForLiteral = JSON.stringify;
|
||||
function createCompletionEntryForLiteral(literal: string | number): CompletionEntry {
|
||||
return { name: completionNameForLiteral(literal), kind: ScriptElementKind.string, kindModifiers: ScriptElementKindModifier.none, sortText: "0" };
|
||||
}
|
||||
|
||||
function createCompletionEntry(
|
||||
symbol: Symbol,
|
||||
location: Node | undefined,
|
||||
@@ -372,7 +381,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.LiteralType:
|
||||
switch (node.parent.parent.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent as LiteralTypeNode), typeChecker), isNewIdentifier: false };
|
||||
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent as LiteralTypeNode)), isNewIdentifier: false };
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
// Get all apparent property names
|
||||
// i.e. interface Foo {
|
||||
@@ -448,7 +457,7 @@ namespace ts.Completions {
|
||||
function fromContextualType(): StringLiteralCompletion {
|
||||
// Get completion for string literal from string literal type
|
||||
// i.e. var x: "hi" | "hello" = "/*completion position*/"
|
||||
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker), typeChecker), isNewIdentifier: false };
|
||||
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +471,7 @@ namespace ts.Completions {
|
||||
if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return;
|
||||
const type = checker.getParameterType(candidate, argumentInfo.argumentIndex);
|
||||
isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String);
|
||||
return getStringLiteralTypes(type, checker, uniques);
|
||||
return getStringLiteralTypes(type, uniques);
|
||||
});
|
||||
|
||||
return { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier };
|
||||
@@ -472,11 +481,11 @@ namespace ts.Completions {
|
||||
return type && { kind: StringLiteralCompletionKind.Properties, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) };
|
||||
}
|
||||
|
||||
function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> {
|
||||
function getStringLiteralTypes(type: Type | undefined, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> {
|
||||
if (!type) return emptyArray;
|
||||
type = skipConstraint(type);
|
||||
return type.isUnion()
|
||||
? flatMap(type.types, t => getStringLiteralTypes(t, typeChecker, uniques))
|
||||
? flatMap(type.types, t => getStringLiteralTypes(t, uniques))
|
||||
: type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value)
|
||||
? [type]
|
||||
: emptyArray;
|
||||
@@ -491,7 +500,7 @@ namespace ts.Completions {
|
||||
readonly isJsxInitializer: IsJsxInitializer;
|
||||
}
|
||||
function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier,
|
||||
): SymbolCompletion | { type: "request", request: Request } | { type: "none" } {
|
||||
): SymbolCompletion | { type: "request", request: Request } | { type: "literal", literal: string | number } | { type: "none" } {
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
const completionData = getCompletionData(program, log, sourceFile, isUncheckedFile(sourceFile, compilerOptions), position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId);
|
||||
if (!completionData) {
|
||||
@@ -501,7 +510,10 @@ namespace ts.Completions {
|
||||
return { type: "request", request: completionData };
|
||||
}
|
||||
|
||||
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer } = completionData;
|
||||
const { symbols, literals, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer } = completionData;
|
||||
|
||||
const literal = find(literals, l => completionNameForLiteral(l) === entryId.name);
|
||||
if (literal !== undefined) return { type: "literal", literal };
|
||||
|
||||
// Find the symbol with the matching entry name.
|
||||
// We don't need to perform character checks here because we're only comparing the
|
||||
@@ -574,12 +586,22 @@ namespace ts.Completions {
|
||||
const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, program.getSourceFiles(), preferences);
|
||||
return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location!, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217
|
||||
}
|
||||
case "literal": {
|
||||
const { literal } = symbolCompletion;
|
||||
return createSimpleDetails(completionNameForLiteral(literal), ScriptElementKind.string, typeof literal === "string" ? SymbolDisplayPartKind.stringLiteral : SymbolDisplayPartKind.numericLiteral);
|
||||
}
|
||||
case "none":
|
||||
// Didn't find a symbol with this name. See if we can find a keyword instead.
|
||||
return allKeywordsCompletions().some(c => c.name === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.keyword, [displayPart(name, SymbolDisplayPartKind.keyword)]) : undefined;
|
||||
return allKeywordsCompletions().some(c => c.name === name) ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined;
|
||||
default:
|
||||
Debug.assertNever(symbolCompletion);
|
||||
}
|
||||
}
|
||||
|
||||
function createSimpleDetails(name: string, kind: ScriptElementKind, kind2: SymbolDisplayPartKind): CompletionEntryDetails {
|
||||
return createCompletionDetails(name, ScriptElementKindModifier.none, kind, [displayPart(name, kind2)]);
|
||||
}
|
||||
|
||||
function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails {
|
||||
const { displayParts, documentation, symbolKind, tags } =
|
||||
checker.runWithCancellationToken(cancellationToken, checker =>
|
||||
@@ -669,6 +691,7 @@ namespace ts.Completions {
|
||||
readonly isNewIdentifierLocation: boolean;
|
||||
readonly location: Node | undefined;
|
||||
readonly keywordFilters: KeywordCompletionFilters;
|
||||
readonly literals: ReadonlyArray<string | number>;
|
||||
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
readonly recommendedCompletion: Symbol | undefined;
|
||||
readonly previousToken: Node | undefined;
|
||||
@@ -685,23 +708,22 @@ namespace ts.Completions {
|
||||
None,
|
||||
}
|
||||
|
||||
function getRecommendedCompletion(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Symbol | undefined {
|
||||
const contextualType = getContextualType(currentToken, position, sourceFile, checker);
|
||||
function getRecommendedCompletion(previousToken: Node, contextualType: Type, checker: TypeChecker): Symbol | undefined {
|
||||
// For a union, return the first one with a recommended completion.
|
||||
return firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => {
|
||||
const symbol = type && type.symbol;
|
||||
// Don't include make a recommended completion for an abstract class
|
||||
return symbol && (symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Enum | SymbolFlags.Class) && !isAbstractConstructorSymbol(symbol))
|
||||
? getFirstSymbolInChain(symbol, currentToken, checker)
|
||||
? getFirstSymbolInChain(symbol, previousToken, checker)
|
||||
: undefined;
|
||||
});
|
||||
}
|
||||
|
||||
function getContextualType(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined {
|
||||
const { parent } = currentToken;
|
||||
switch (currentToken.kind) {
|
||||
function getContextualType(previousToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined {
|
||||
const { parent } = previousToken;
|
||||
switch (previousToken.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return getContextualTypeFromParent(currentToken as Identifier, checker);
|
||||
return getContextualTypeFromParent(previousToken as Identifier, checker);
|
||||
case SyntaxKind.EqualsToken:
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
@@ -720,14 +742,14 @@ namespace ts.Completions {
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return isJsxExpression(parent) && parent.parent.kind !== SyntaxKind.JsxElement ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
|
||||
default:
|
||||
const argInfo = SignatureHelp.getArgumentInfoForCompletions(currentToken, position, sourceFile);
|
||||
const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile);
|
||||
return argInfo
|
||||
// At `,`, treat this as the next argument after the comma.
|
||||
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0))
|
||||
: isEqualityOperatorKind(currentToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
|
||||
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0))
|
||||
: isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
|
||||
// completion at `x ===/**/` should be for the right side
|
||||
? checker.getTypeAtLocation(parent.left)
|
||||
: checker.getContextualType(currentToken as Expression);
|
||||
: checker.getContextualType(previousToken as Expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,8 +1027,11 @@ namespace ts.Completions {
|
||||
|
||||
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
|
||||
|
||||
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, position, sourceFile, typeChecker);
|
||||
return { kind: CompletionDataKind.Data, symbols, completionKind, isInSnippetScope, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
|
||||
const contextualType = previousToken && getContextualType(previousToken, position, sourceFile, typeChecker);
|
||||
const literals = mapDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), t => t.isLiteral() ? t.value : undefined);
|
||||
|
||||
const recommendedCompletion = previousToken && contextualType && getRecommendedCompletion(previousToken, contextualType, typeChecker);
|
||||
return { kind: CompletionDataKind.Data, symbols, completionKind, isInSnippetScope, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
|
||||
|
||||
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
|
||||
|
||||
@@ -1074,7 +1099,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function addTypeProperties(type: Type): void {
|
||||
isNewIdentifierLocation = hasIndexSignature(type);
|
||||
isNewIdentifierLocation = !!type.getStringIndexType();
|
||||
|
||||
if (isUncheckedFile) {
|
||||
// In javascript files, for union types, we don't just get the members that
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace ts.NavigationBar {
|
||||
*/
|
||||
interface NavigationBarNode {
|
||||
node: Node;
|
||||
name: DeclarationName | undefined;
|
||||
additionalNodes: Node[] | undefined;
|
||||
parent: NavigationBarNode | undefined; // Present for all but root node
|
||||
children: NavigationBarNode[] | undefined;
|
||||
@@ -91,7 +92,7 @@ namespace ts.NavigationBar {
|
||||
|
||||
function rootNavigationBarNode(sourceFile: SourceFile): NavigationBarNode {
|
||||
Debug.assert(!parentsStack.length);
|
||||
const root: NavigationBarNode = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 };
|
||||
const root: NavigationBarNode = { node: sourceFile, name: undefined, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 };
|
||||
parent = root;
|
||||
for (const statement of sourceFile.statements) {
|
||||
addChildrenRecursively(statement);
|
||||
@@ -108,6 +109,7 @@ namespace ts.NavigationBar {
|
||||
function emptyNavigationBarNode(node: Node): NavigationBarNode {
|
||||
return {
|
||||
node,
|
||||
name: isDeclaration(node) || isExpression(node) ? getNameOfDeclaration(node) : undefined,
|
||||
additionalNodes: undefined,
|
||||
parent,
|
||||
children: undefined,
|
||||
@@ -420,12 +422,11 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
}
|
||||
|
||||
function getItemName(node: Node): string {
|
||||
function getItemName(node: Node, name: Node | undefined): string {
|
||||
if (node.kind === SyntaxKind.ModuleDeclaration) {
|
||||
return getModuleName(<ModuleDeclaration>node);
|
||||
}
|
||||
|
||||
const name = getNameOfDeclaration(<Declaration>node);
|
||||
if (name) {
|
||||
const text = nodeText(name);
|
||||
if (text.length > 0) {
|
||||
@@ -534,17 +535,18 @@ namespace ts.NavigationBar {
|
||||
|
||||
function convertToTree(n: NavigationBarNode): NavigationTree {
|
||||
return {
|
||||
text: getItemName(n.node),
|
||||
text: getItemName(n.node, n.name),
|
||||
kind: getNodeKind(n.node),
|
||||
kindModifiers: getModifiers(n.node),
|
||||
spans: getSpans(n),
|
||||
nameSpan: n.name && getNodeSpan(n.name),
|
||||
childItems: map(n.children, convertToTree)
|
||||
};
|
||||
}
|
||||
|
||||
function convertToTopLevelItem(n: NavigationBarNode): NavigationBarItem {
|
||||
return {
|
||||
text: getItemName(n.node),
|
||||
text: getItemName(n.node, n.name),
|
||||
kind: getNodeKind(n.node),
|
||||
kindModifiers: getModifiers(n.node),
|
||||
spans: getSpans(n),
|
||||
@@ -556,7 +558,7 @@ namespace ts.NavigationBar {
|
||||
|
||||
function convertToChildItem(n: NavigationBarNode): NavigationBarItem {
|
||||
return {
|
||||
text: getItemName(n.node),
|
||||
text: getItemName(n.node, n.name),
|
||||
kind: getNodeKind(n.node),
|
||||
kindModifiers: getNodeModifiers(n.node),
|
||||
spans: getSpans(n),
|
||||
|
||||
@@ -118,7 +118,8 @@ namespace ts.refactor {
|
||||
}
|
||||
|
||||
const useEs6ModuleSyntax = !!oldFile.externalModuleIndicator;
|
||||
const importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEs6ModuleSyntax, preferences);
|
||||
const quotePreference = getQuotePreference(oldFile, preferences);
|
||||
const importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEs6ModuleSyntax, quotePreference);
|
||||
if (importsFromNewFile) {
|
||||
changes.insertNodeBefore(oldFile, oldFile.statements[0], importsFromNewFile, /*blankLineBetween*/ true);
|
||||
}
|
||||
@@ -129,7 +130,7 @@ namespace ts.refactor {
|
||||
updateImportsInOtherFiles(changes, program, oldFile, usage.movedSymbols, newModuleName);
|
||||
|
||||
return [
|
||||
...getNewFileImportsAndAddExportInOldFile(oldFile, usage.oldImportsNeededByNewFile, usage.newFileImportsFromOldFile, changes, checker, useEs6ModuleSyntax, preferences),
|
||||
...getNewFileImportsAndAddExportInOldFile(oldFile, usage.oldImportsNeededByNewFile, usage.newFileImportsFromOldFile, changes, checker, useEs6ModuleSyntax, quotePreference),
|
||||
...addExports(oldFile, toMove.all, usage.oldFileImportsFromNewFile, useEs6ModuleSyntax),
|
||||
];
|
||||
}
|
||||
@@ -268,7 +269,7 @@ namespace ts.refactor {
|
||||
| ImportEqualsDeclaration
|
||||
| VariableStatement;
|
||||
|
||||
function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, newFileNameWithExtension: string, useEs6Imports: boolean, preferences: UserPreferences): Statement | undefined {
|
||||
function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, newFileNameWithExtension: string, useEs6Imports: boolean, quotePreference: QuotePreference): Statement | undefined {
|
||||
let defaultImport: Identifier | undefined;
|
||||
const imports: string[] = [];
|
||||
newFileNeedExport.forEach(symbol => {
|
||||
@@ -279,14 +280,14 @@ namespace ts.refactor {
|
||||
imports.push(symbol.name);
|
||||
}
|
||||
});
|
||||
return makeImportOrRequire(defaultImport, imports, newFileNameWithExtension, useEs6Imports, preferences);
|
||||
return makeImportOrRequire(defaultImport, imports, newFileNameWithExtension, useEs6Imports, quotePreference);
|
||||
}
|
||||
|
||||
function makeImportOrRequire(defaultImport: Identifier | undefined, imports: ReadonlyArray<string>, path: string, useEs6Imports: boolean, preferences: UserPreferences): Statement | undefined {
|
||||
function makeImportOrRequire(defaultImport: Identifier | undefined, imports: ReadonlyArray<string>, path: string, useEs6Imports: boolean, quotePreference: QuotePreference): Statement | undefined {
|
||||
path = ensurePathIsNonModuleName(path);
|
||||
if (useEs6Imports) {
|
||||
const specifiers = imports.map(i => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(i)));
|
||||
return makeImportIfNecessary(defaultImport, specifiers, path, preferences);
|
||||
return makeImportIfNecessary(defaultImport, specifiers, path, quotePreference);
|
||||
}
|
||||
else {
|
||||
Debug.assert(!defaultImport); // If there's a default export, it should have been an es6 module.
|
||||
@@ -392,7 +393,7 @@ namespace ts.refactor {
|
||||
changes: textChanges.ChangeTracker,
|
||||
checker: TypeChecker,
|
||||
useEs6ModuleSyntax: boolean,
|
||||
preferences: UserPreferences,
|
||||
quotePreference: QuotePreference,
|
||||
): ReadonlyArray<SupportedImportStatement> {
|
||||
const copiedOldImports: SupportedImportStatement[] = [];
|
||||
for (const oldStatement of oldFile.statements) {
|
||||
@@ -424,7 +425,7 @@ namespace ts.refactor {
|
||||
}
|
||||
});
|
||||
|
||||
append(copiedOldImports, makeImportOrRequire(oldFileDefault, oldFileNamedImports, removeFileExtension(getBaseFileName(oldFile.fileName)), useEs6ModuleSyntax, preferences));
|
||||
append(copiedOldImports, makeImportOrRequire(oldFileDefault, oldFileNamedImports, removeFileExtension(getBaseFileName(oldFile.fileName)), useEs6ModuleSyntax, quotePreference));
|
||||
return copiedOldImports;
|
||||
}
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ namespace ts {
|
||||
return !!(this.flags & TypeFlags.UnionOrIntersection);
|
||||
}
|
||||
isLiteral(): this is LiteralType {
|
||||
return !!(this.flags & TypeFlags.Literal);
|
||||
return !!(this.flags & TypeFlags.StringOrNumberLiteral);
|
||||
}
|
||||
isStringLiteral(): this is StringLiteralType {
|
||||
return !!(this.flags & TypeFlags.StringLiteral);
|
||||
@@ -540,6 +540,7 @@ namespace ts {
|
||||
public _declarationBrand: any;
|
||||
public fileName: string;
|
||||
public path: Path;
|
||||
public resolvedPath: Path;
|
||||
public text: string;
|
||||
public scriptSnapshot: IScriptSnapshot;
|
||||
public lineMap: ReadonlyArray<number>;
|
||||
|
||||
@@ -735,7 +735,7 @@ namespace ts.textChanges {
|
||||
export function newFileChanges(oldFile: SourceFile, fileName: string, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges {
|
||||
// TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this
|
||||
const nonFormattedText = statements.map(s => getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter);
|
||||
const sourceFile = createSourceFile(fileName, nonFormattedText, ScriptTarget.ESNext);
|
||||
const sourceFile = createSourceFile(fileName, nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true);
|
||||
const changes = formatting.formatDocument(sourceFile, formatContext);
|
||||
const text = applyChanges(nonFormattedText, changes);
|
||||
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
|
||||
|
||||
@@ -425,6 +425,7 @@ namespace ts {
|
||||
* There will be more than one if this is the result of merging.
|
||||
*/
|
||||
spans: TextSpan[];
|
||||
nameSpan: TextSpan | undefined;
|
||||
/** Present if non-empty */
|
||||
childItems?: NavigationTree[];
|
||||
}
|
||||
|
||||
@@ -1257,18 +1257,34 @@ namespace ts {
|
||||
return createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(host));
|
||||
}
|
||||
|
||||
export function makeImportIfNecessary(defaultImport: Identifier | undefined, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: string, preferences: UserPreferences): ImportDeclaration | undefined {
|
||||
return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, preferences) : undefined;
|
||||
export function makeImportIfNecessary(defaultImport: Identifier | undefined, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: string, quotePreference: QuotePreference): ImportDeclaration | undefined {
|
||||
return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined;
|
||||
}
|
||||
|
||||
export function makeImport(defaultImport: Identifier | undefined, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: string | Expression, preferences: UserPreferences): ImportDeclaration {
|
||||
export function makeImport(defaultImport: Identifier | undefined, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: string | Expression, quotePreference: QuotePreference): ImportDeclaration {
|
||||
return createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
defaultImport || namedImports
|
||||
? createImportClause(defaultImport, namedImports && namedImports.length ? createNamedImports(namedImports) : undefined)
|
||||
: undefined,
|
||||
typeof moduleSpecifier === "string" ? createLiteral(moduleSpecifier, preferences.quotePreference === "single") : moduleSpecifier);
|
||||
typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier);
|
||||
}
|
||||
|
||||
export function makeStringLiteral(text: string, quotePreference: QuotePreference): StringLiteral {
|
||||
return createLiteral(text, quotePreference === QuotePreference.Single);
|
||||
}
|
||||
|
||||
export const enum QuotePreference { Single, Double }
|
||||
|
||||
export function getQuotePreference(sourceFile: SourceFile, preferences: UserPreferences): QuotePreference {
|
||||
if (preferences.quotePreference) {
|
||||
return preferences.quotePreference === "single" ? QuotePreference.Single : QuotePreference.Double;
|
||||
}
|
||||
else {
|
||||
const firstModuleSpecifier = firstOrUndefined(sourceFile.imports);
|
||||
return !!firstModuleSpecifier && !isStringDoubleQuoted(firstModuleSpecifier, sourceFile) ? QuotePreference.Single : QuotePreference.Double;
|
||||
}
|
||||
}
|
||||
|
||||
export function symbolNameNoDefault(symbol: Symbol): string | undefined {
|
||||
|
||||
+17
-4
@@ -1674,11 +1674,14 @@ declare namespace ts {
|
||||
interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
interface JsonSourceFile extends SourceFile {
|
||||
statements: NodeArray<JsonObjectExpressionStatement>;
|
||||
@@ -2661,6 +2664,9 @@ declare namespace ts {
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
createHash?(data: string): string;
|
||||
getModifiedTime?(fileName: string): Date;
|
||||
setModifiedTime?(fileName: string, date: Date): void;
|
||||
deleteFile?(fileName: string): void;
|
||||
}
|
||||
interface SourceMapRange extends TextRange {
|
||||
source?: SourceMapSource;
|
||||
@@ -3015,6 +3021,8 @@ declare namespace ts {
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
setModifiedTime?(path: string, time: Date): void;
|
||||
deleteFile?(path: string): void;
|
||||
/**
|
||||
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
|
||||
*/
|
||||
@@ -3380,6 +3388,7 @@ declare namespace ts {
|
||||
function isEnumMember(node: Node): node is EnumMember;
|
||||
function isSourceFile(node: Node): node is SourceFile;
|
||||
function isBundle(node: Node): node is Bundle;
|
||||
function isUnparsedSource(node: Node): node is UnparsedSource;
|
||||
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
|
||||
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
|
||||
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
|
||||
@@ -3831,8 +3840,8 @@ declare namespace ts {
|
||||
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
|
||||
function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string): InputFiles;
|
||||
function createUnparsedSourceFile(text: string, map?: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles;
|
||||
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
|
||||
@@ -4053,6 +4062,10 @@ declare namespace ts {
|
||||
* @returns A 'Program' object.
|
||||
*/
|
||||
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
*/
|
||||
function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined;
|
||||
}
|
||||
declare namespace ts {
|
||||
interface EmitOutput {
|
||||
@@ -4657,6 +4670,7 @@ declare namespace ts {
|
||||
* There will be more than one if this is the result of merging.
|
||||
*/
|
||||
spans: TextSpan[];
|
||||
nameSpan: TextSpan | undefined;
|
||||
/** Present if non-empty */
|
||||
childItems?: NavigationTree[];
|
||||
}
|
||||
@@ -7532,6 +7546,7 @@ declare namespace ts.server.protocol {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
spans: TextSpan[];
|
||||
nameSpan: TextSpan | undefined;
|
||||
childItems?: NavigationTree[];
|
||||
}
|
||||
type TelemetryEventName = "telemetry";
|
||||
@@ -8562,9 +8577,7 @@ declare namespace ts.server {
|
||||
private mapCodeAction;
|
||||
private mapCodeFixAction;
|
||||
private mapTextChangesToCodeEdits;
|
||||
private mapTextChangesToCodeEditsUsingScriptinfo;
|
||||
private convertTextChangeToCodeEdit;
|
||||
private convertNewFileTextChangeToCodeEdit;
|
||||
private getBraceMatching;
|
||||
private getDiagnosticsForProject;
|
||||
getCanonicalFileName(fileName: string): string;
|
||||
|
||||
+16
-2
@@ -1674,11 +1674,14 @@ declare namespace ts {
|
||||
interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
interface JsonSourceFile extends SourceFile {
|
||||
statements: NodeArray<JsonObjectExpressionStatement>;
|
||||
@@ -2661,6 +2664,9 @@ declare namespace ts {
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
createHash?(data: string): string;
|
||||
getModifiedTime?(fileName: string): Date;
|
||||
setModifiedTime?(fileName: string, date: Date): void;
|
||||
deleteFile?(fileName: string): void;
|
||||
}
|
||||
interface SourceMapRange extends TextRange {
|
||||
source?: SourceMapSource;
|
||||
@@ -3015,6 +3021,8 @@ declare namespace ts {
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
setModifiedTime?(path: string, time: Date): void;
|
||||
deleteFile?(path: string): void;
|
||||
/**
|
||||
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
|
||||
*/
|
||||
@@ -3380,6 +3388,7 @@ declare namespace ts {
|
||||
function isEnumMember(node: Node): node is EnumMember;
|
||||
function isSourceFile(node: Node): node is SourceFile;
|
||||
function isBundle(node: Node): node is Bundle;
|
||||
function isUnparsedSource(node: Node): node is UnparsedSource;
|
||||
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
|
||||
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
|
||||
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
|
||||
@@ -3831,8 +3840,8 @@ declare namespace ts {
|
||||
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
|
||||
function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string): InputFiles;
|
||||
function createUnparsedSourceFile(text: string, map?: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles;
|
||||
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
|
||||
@@ -4053,6 +4062,10 @@ declare namespace ts {
|
||||
* @returns A 'Program' object.
|
||||
*/
|
||||
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
*/
|
||||
function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined;
|
||||
}
|
||||
declare namespace ts {
|
||||
interface EmitOutput {
|
||||
@@ -4657,6 +4670,7 @@ declare namespace ts {
|
||||
* There will be more than one if this is the result of merging.
|
||||
*/
|
||||
spans: TextSpan[];
|
||||
nameSpan: TextSpan | undefined;
|
||||
/** Present if non-empty */
|
||||
childItems?: NavigationTree[];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
//// [asyncArrowFunction11_es5.ts]
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
class A {
|
||||
b = async (...args: any[]) => {
|
||||
await Promise.resolve();
|
||||
const obj = { ["a"]: () => this }; // computed property name after `await` triggers case
|
||||
};
|
||||
}
|
||||
|
||||
//// [asyncArrowFunction11_es5.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
var _this = this;
|
||||
this.b = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return __awaiter(_this, void 0, void 0, function () {
|
||||
var _a, obj;
|
||||
var _this = this;
|
||||
return __generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0: return [4 /*yield*/, Promise.resolve()];
|
||||
case 1:
|
||||
_b.sent();
|
||||
obj = (_a = {}, _a["a"] = function () { return _this; }, _a);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
@@ -0,0 +1,22 @@
|
||||
=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction11_es5.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
class A {
|
||||
>A : Symbol(A, Decl(asyncArrowFunction11_es5.ts, 0, 0))
|
||||
|
||||
b = async (...args: any[]) => {
|
||||
>b : Symbol(A.b, Decl(asyncArrowFunction11_es5.ts, 1, 9))
|
||||
>args : Symbol(args, Decl(asyncArrowFunction11_es5.ts, 2, 15))
|
||||
|
||||
await Promise.resolve();
|
||||
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
const obj = { ["a"]: () => this }; // computed property name after `await` triggers case
|
||||
>obj : Symbol(obj, Decl(asyncArrowFunction11_es5.ts, 4, 13))
|
||||
>["a"] : Symbol(["a"], Decl(asyncArrowFunction11_es5.ts, 4, 21))
|
||||
>"a" : Symbol(["a"], Decl(asyncArrowFunction11_es5.ts, 4, 21))
|
||||
>this : Symbol(A, Decl(asyncArrowFunction11_es5.ts, 0, 0))
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction11_es5.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
class A {
|
||||
>A : A
|
||||
|
||||
b = async (...args: any[]) => {
|
||||
>b : (...args: any[]) => Promise<void>
|
||||
>async (...args: any[]) => { await Promise.resolve(); const obj = { ["a"]: () => this }; // computed property name after `await` triggers case } : (...args: any[]) => Promise<void>
|
||||
>args : any[]
|
||||
|
||||
await Promise.resolve();
|
||||
>await Promise.resolve() : void
|
||||
>Promise.resolve() : Promise<void>
|
||||
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
|
||||
>Promise : PromiseConstructor
|
||||
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
|
||||
|
||||
const obj = { ["a"]: () => this }; // computed property name after `await` triggers case
|
||||
>obj : { ["a"]: () => this; }
|
||||
>{ ["a"]: () => this } : { ["a"]: () => this; }
|
||||
>["a"] : () => this
|
||||
>"a" : "a"
|
||||
>() => this : () => this
|
||||
>this : this
|
||||
|
||||
};
|
||||
}
|
||||
@@ -38,11 +38,11 @@ class FetchUser extends React.Component<IFetchUserProps, any> {
|
||||
|
||||
? this.props.children(this.state.result)
|
||||
>this.props.children(this.state.result) : JSX.Element
|
||||
>this.props.children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.props.children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.props : IFetchUserProps & { children?: React.ReactNode; }
|
||||
>this : this
|
||||
>props : IFetchUserProps & { children?: React.ReactNode; }
|
||||
>children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.state.result : any
|
||||
>this.state : any
|
||||
>this : this
|
||||
|
||||
@@ -38,11 +38,11 @@ class FetchUser extends React.Component<IFetchUserProps, any> {
|
||||
|
||||
? this.props.children(this.state.result)
|
||||
>this.props.children(this.state.result) : JSX.Element
|
||||
>this.props.children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.props.children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.props : IFetchUserProps & { children?: React.ReactNode; }
|
||||
>this : this
|
||||
>props : IFetchUserProps & { children?: React.ReactNode; }
|
||||
>children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>children : ((user: IUser) => JSX.Element) | (((user: IUser) => JSX.Element) & string) | (((user: IUser) => JSX.Element) & number) | (((user: IUser) => JSX.Element) & false) | (((user: IUser) => JSX.Element) & true) | (((user: IUser) => JSX.Element) & React.ReactElement<any>) | (((user: IUser) => JSX.Element) & (string | number | boolean | any[] | React.ReactElement<any>)[])
|
||||
>this.state.result : any
|
||||
>this.state : any
|
||||
>this : this
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//// [tests/cases/compiler/declarationEmitWithDefaultAsComputedName.ts] ////
|
||||
|
||||
//// [other.ts]
|
||||
type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
options: Experiment<Name>
|
||||
) => Experiment<Name>;
|
||||
export default createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
|
||||
//// [main.ts]
|
||||
import other from "./other";
|
||||
export const obj = {
|
||||
[other.name]: 1,
|
||||
};
|
||||
|
||||
//// [other.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
//// [main.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var _a;
|
||||
var other_1 = require("./other");
|
||||
exports.obj = (_a = {},
|
||||
_a[other_1.default.name] = 1,
|
||||
_a);
|
||||
|
||||
|
||||
//// [other.d.ts]
|
||||
declare type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const _default: Experiment<"foo">;
|
||||
export default _default;
|
||||
//// [main.d.ts]
|
||||
import other from "./other";
|
||||
export declare const obj: {
|
||||
[other.name]: number;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
=== tests/cases/compiler/other.ts ===
|
||||
type Experiment<Name> = {
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 0, 16))
|
||||
|
||||
name: Name;
|
||||
>name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
>Name : Symbol(Name, Decl(other.ts, 0, 16))
|
||||
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
>createExperiment : Symbol(createExperiment, Decl(other.ts, 3, 13))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
options: Experiment<Name>
|
||||
>options : Symbol(options, Decl(other.ts, 3, 54))
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
) => Experiment<Name>;
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
export default createExperiment({
|
||||
>createExperiment : Symbol(createExperiment, Decl(other.ts, 3, 13))
|
||||
|
||||
name: "foo"
|
||||
>name : Symbol(name, Decl(other.ts, 6, 33))
|
||||
|
||||
});
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
import other from "./other";
|
||||
>other : Symbol(other, Decl(main.ts, 0, 6))
|
||||
|
||||
export const obj = {
|
||||
>obj : Symbol(obj, Decl(main.ts, 1, 12))
|
||||
|
||||
[other.name]: 1,
|
||||
>[other.name] : Symbol([other.name], Decl(main.ts, 1, 20))
|
||||
>other.name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
>other : Symbol(other, Decl(main.ts, 0, 6))
|
||||
>name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
=== tests/cases/compiler/other.ts ===
|
||||
type Experiment<Name> = {
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
name: Name;
|
||||
>name : Name
|
||||
>Name : Name
|
||||
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
>createExperiment : <Name extends string>(options: Experiment<Name>) => Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
options: Experiment<Name>
|
||||
>options : Experiment<Name>
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
) => Experiment<Name>;
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
export default createExperiment({
|
||||
>createExperiment({ name: "foo"}) : Experiment<"foo">
|
||||
>createExperiment : <Name extends string>(options: Experiment<Name>) => Experiment<Name>
|
||||
>{ name: "foo"} : { name: "foo"; }
|
||||
|
||||
name: "foo"
|
||||
>name : "foo"
|
||||
>"foo" : "foo"
|
||||
|
||||
});
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
import other from "./other";
|
||||
>other : { name: "foo"; }
|
||||
|
||||
export const obj = {
|
||||
>obj : { [other.name]: number; }
|
||||
>{ [other.name]: 1,} : { [other.name]: number; }
|
||||
|
||||
[other.name]: 1,
|
||||
>[other.name] : number
|
||||
>other.name : "foo"
|
||||
>other : { name: "foo"; }
|
||||
>name : "foo"
|
||||
>1 : 1
|
||||
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
//// [tests/cases/compiler/declarationEmitWithDefaultAsComputedName2.ts] ////
|
||||
|
||||
//// [other.ts]
|
||||
type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
options: Experiment<Name>
|
||||
) => Experiment<Name>;
|
||||
export default createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
|
||||
//// [main.ts]
|
||||
import * as other2 from "./other";
|
||||
export const obj = {
|
||||
[other2.default.name]: 1
|
||||
};
|
||||
|
||||
//// [other.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
//// [main.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var _a;
|
||||
var other2 = require("./other");
|
||||
exports.obj = (_a = {},
|
||||
_a[other2.default.name] = 1,
|
||||
_a);
|
||||
|
||||
|
||||
//// [other.d.ts]
|
||||
declare type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const _default: Experiment<"foo">;
|
||||
export default _default;
|
||||
//// [main.d.ts]
|
||||
import * as other2 from "./other";
|
||||
export declare const obj: {
|
||||
[other2.default.name]: number;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/compiler/other.ts ===
|
||||
type Experiment<Name> = {
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 0, 16))
|
||||
|
||||
name: Name;
|
||||
>name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
>Name : Symbol(Name, Decl(other.ts, 0, 16))
|
||||
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
>createExperiment : Symbol(createExperiment, Decl(other.ts, 3, 13))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
options: Experiment<Name>
|
||||
>options : Symbol(options, Decl(other.ts, 3, 54))
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
) => Experiment<Name>;
|
||||
>Experiment : Symbol(Experiment, Decl(other.ts, 0, 0))
|
||||
>Name : Symbol(Name, Decl(other.ts, 3, 33))
|
||||
|
||||
export default createExperiment({
|
||||
>createExperiment : Symbol(createExperiment, Decl(other.ts, 3, 13))
|
||||
|
||||
name: "foo"
|
||||
>name : Symbol(name, Decl(other.ts, 6, 33))
|
||||
|
||||
});
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
import * as other2 from "./other";
|
||||
>other2 : Symbol(other2, Decl(main.ts, 0, 6))
|
||||
|
||||
export const obj = {
|
||||
>obj : Symbol(obj, Decl(main.ts, 1, 12))
|
||||
|
||||
[other2.default.name]: 1
|
||||
>[other2.default.name] : Symbol([other2.default.name], Decl(main.ts, 1, 20))
|
||||
>other2.default.name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
>other2.default : Symbol(other2.default, Decl(other.ts, 5, 22))
|
||||
>other2 : Symbol(other2, Decl(main.ts, 0, 6))
|
||||
>default : Symbol(other2.default, Decl(other.ts, 5, 22))
|
||||
>name : Symbol(name, Decl(other.ts, 0, 25))
|
||||
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
=== tests/cases/compiler/other.ts ===
|
||||
type Experiment<Name> = {
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
name: Name;
|
||||
>name : Name
|
||||
>Name : Name
|
||||
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
>createExperiment : <Name extends string>(options: Experiment<Name>) => Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
options: Experiment<Name>
|
||||
>options : Experiment<Name>
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
) => Experiment<Name>;
|
||||
>Experiment : Experiment<Name>
|
||||
>Name : Name
|
||||
|
||||
export default createExperiment({
|
||||
>createExperiment({ name: "foo"}) : Experiment<"foo">
|
||||
>createExperiment : <Name extends string>(options: Experiment<Name>) => Experiment<Name>
|
||||
>{ name: "foo"} : { name: "foo"; }
|
||||
|
||||
name: "foo"
|
||||
>name : "foo"
|
||||
>"foo" : "foo"
|
||||
|
||||
});
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
import * as other2 from "./other";
|
||||
>other2 : typeof other2
|
||||
|
||||
export const obj = {
|
||||
>obj : { [other2.default.name]: number; }
|
||||
>{ [other2.default.name]: 1} : { [other2.default.name]: number; }
|
||||
|
||||
[other2.default.name]: 1
|
||||
>[other2.default.name] : number
|
||||
>other2.default.name : "foo"
|
||||
>other2.default : { name: "foo"; }
|
||||
>other2 : typeof other2
|
||||
>default : { name: "foo"; }
|
||||
>name : "foo"
|
||||
>1 : 1
|
||||
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
tests/cases/compiler/importNotElidedWhenNotFound.ts(1,15): error TS2307: Cannot find module 'file'.
|
||||
tests/cases/compiler/importNotElidedWhenNotFound.ts(2,15): error TS2307: Cannot find module 'other_file'.
|
||||
tests/cases/compiler/importNotElidedWhenNotFound.ts(10,16): error TS2307: Cannot find module 'file2'.
|
||||
tests/cases/compiler/importNotElidedWhenNotFound.ts(11,16): error TS2307: Cannot find module 'file3'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/importNotElidedWhenNotFound.ts (2 errors) ====
|
||||
==== tests/cases/compiler/importNotElidedWhenNotFound.ts (4 errors) ====
|
||||
import X from 'file';
|
||||
~~~~~~
|
||||
!!! error TS2307: Cannot find module 'file'.
|
||||
@@ -14,4 +16,17 @@ tests/cases/compiler/importNotElidedWhenNotFound.ts(2,15): error TS2307: Cannot
|
||||
constructor() {
|
||||
super(X);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import X2 from 'file2';
|
||||
~~~~~~~
|
||||
!!! error TS2307: Cannot find module 'file2'.
|
||||
import X3 from 'file3';
|
||||
~~~~~~~
|
||||
!!! error TS2307: Cannot find module 'file3'.
|
||||
class Q extends Z {
|
||||
constructor() {
|
||||
super(X2, X3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,16 @@ class Y extends Z {
|
||||
constructor() {
|
||||
super(X);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import X2 from 'file2';
|
||||
import X3 from 'file3';
|
||||
class Q extends Z {
|
||||
constructor() {
|
||||
super(X2, X3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [importNotElidedWhenNotFound.js]
|
||||
"use strict";
|
||||
@@ -30,3 +39,12 @@ var Y = /** @class */ (function (_super) {
|
||||
}
|
||||
return Y;
|
||||
}(other_file_1["default"]));
|
||||
var file2_1 = require("file2");
|
||||
var file3_1 = require("file3");
|
||||
var Q = /** @class */ (function (_super) {
|
||||
__extends(Q, _super);
|
||||
function Q() {
|
||||
return _super.call(this, file2_1["default"], file3_1["default"]) || this;
|
||||
}
|
||||
return Q;
|
||||
}(other_file_1["default"]));
|
||||
|
||||
@@ -14,3 +14,21 @@ class Y extends Z {
|
||||
>X : Symbol(X, Decl(importNotElidedWhenNotFound.ts, 0, 6))
|
||||
}
|
||||
}
|
||||
|
||||
import X2 from 'file2';
|
||||
>X2 : Symbol(X2, Decl(importNotElidedWhenNotFound.ts, 9, 6))
|
||||
|
||||
import X3 from 'file3';
|
||||
>X3 : Symbol(X3, Decl(importNotElidedWhenNotFound.ts, 10, 6))
|
||||
|
||||
class Q extends Z {
|
||||
>Q : Symbol(Q, Decl(importNotElidedWhenNotFound.ts, 10, 23))
|
||||
>Z : Symbol(Z, Decl(importNotElidedWhenNotFound.ts, 1, 6))
|
||||
|
||||
constructor() {
|
||||
super(X2, X3);
|
||||
>X2 : Symbol(X2, Decl(importNotElidedWhenNotFound.ts, 9, 6))
|
||||
>X3 : Symbol(X3, Decl(importNotElidedWhenNotFound.ts, 10, 6))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,3 +16,23 @@ class Y extends Z {
|
||||
>X : any
|
||||
}
|
||||
}
|
||||
|
||||
import X2 from 'file2';
|
||||
>X2 : any
|
||||
|
||||
import X3 from 'file3';
|
||||
>X3 : any
|
||||
|
||||
class Q extends Z {
|
||||
>Q : Q
|
||||
>Z : any
|
||||
|
||||
constructor() {
|
||||
super(X2, X3);
|
||||
>super(X2, X3) : void
|
||||
>super : any
|
||||
>X2 : any
|
||||
>X3 : any
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
tests/cases/compiler/metadataImportType.ts(2,6): error TS2304: Cannot find name 'test'.
|
||||
tests/cases/compiler/metadataImportType.ts(3,8): error TS2307: Cannot find module './b'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/metadataImportType.ts (2 errors) ====
|
||||
export class A {
|
||||
@test
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'test'.
|
||||
b: import('./b').B
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './b'.
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//// [metadataImportType.ts]
|
||||
export class A {
|
||||
@test
|
||||
b: import('./b').B
|
||||
}
|
||||
|
||||
//// [metadataImportType.js]
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
exports.__esModule = true;
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
__decorate([
|
||||
test,
|
||||
__metadata("design:type", Object)
|
||||
], A.prototype, "b");
|
||||
return A;
|
||||
}());
|
||||
exports.A = A;
|
||||
@@ -0,0 +1,8 @@
|
||||
=== tests/cases/compiler/metadataImportType.ts ===
|
||||
export class A {
|
||||
>A : Symbol(A, Decl(metadataImportType.ts, 0, 0))
|
||||
|
||||
@test
|
||||
b: import('./b').B
|
||||
>b : Symbol(A.b, Decl(metadataImportType.ts, 0, 16))
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/metadataImportType.ts ===
|
||||
export class A {
|
||||
>A : A
|
||||
|
||||
@test
|
||||
>test : any
|
||||
|
||||
b: import('./b').B
|
||||
>b : any
|
||||
>B : No type information available!
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
*/
|
||||
/lib/
|
||||
/lib/lib.d.ts
|
||||
/lib/lib.dom.d.ts
|
||||
/lib/lib.es5.d.ts
|
||||
/lib/lib.scripthost.d.ts
|
||||
/lib/lib.webworker.importscripts.d.ts
|
||||
/src/
|
||||
/src/2/
|
||||
/src/2/second-output.d.ts
|
||||
/src/2/second-output.d.ts.map
|
||||
/src/2/second-output.js
|
||||
/src/2/second-output.js.map
|
||||
/src/first/
|
||||
/src/first/bin/
|
||||
/src/first/bin/first-output.d.ts
|
||||
/src/first/bin/first-output.d.ts.map
|
||||
/src/first/bin/first-output.js
|
||||
/src/first/bin/first-output.js.map
|
||||
/src/first/first_part1.ts
|
||||
/src/first/first_part2.ts
|
||||
/src/first/first_part3.ts
|
||||
/src/first/tsconfig.json
|
||||
/src/first_part1.ts
|
||||
/src/first_part2.ts
|
||||
/src/first_part3.ts
|
||||
/src/second/
|
||||
/src/second/second_part1.ts
|
||||
/src/second/second_part2.ts
|
||||
/src/second/tsconfig.json
|
||||
/src/second_part1.ts
|
||||
/src/second_part2.ts
|
||||
/src/third/
|
||||
/src/third/third_part1.ts
|
||||
/src/third/thirdjs/
|
||||
/src/third/thirdjs/output/
|
||||
/src/third/thirdjs/output/third-output.d.ts
|
||||
/src/third/thirdjs/output/third-output.d.ts.map
|
||||
/src/third/thirdjs/output/third-output.js
|
||||
/src/third/thirdjs/output/third-output.js.map
|
||||
/src/third/tsconfig.json
|
||||
/src/third_part1.ts
|
||||
/src/tsconfig.json
|
||||
@@ -0,0 +1,26 @@
|
||||
var s = "Hello, world";
|
||||
console.log(s);
|
||||
console.log(f());
|
||||
function f() {
|
||||
return "JS does hoists";
|
||||
}
|
||||
//# sourceMappingURL=first-output.js.map
|
||||
var N;
|
||||
(function (N) {
|
||||
function f() {
|
||||
console.log('testing');
|
||||
}
|
||||
f();
|
||||
})(N || (N = {}));
|
||||
var C = (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.doSomething = function () {
|
||||
console.log("something got done");
|
||||
};
|
||||
return C;
|
||||
}());
|
||||
//# sourceMappingURL=second-output.js.map
|
||||
var c = new C();
|
||||
c.doSomething();
|
||||
//# sourceMappingURL=third-output.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"third-output.js","sections":[{"offset":{"line":0,"column":0},"map":{"version":3,"file":"first-output.js","sourceRoot":"","sources":["first_part1.ts","first_part2.ts","first_part3.ts"],"names":[],"mappings":"AAIA,IAAM,CAAC,GAAG,cAAc,CAAC;AAMzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;ACVf,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;ACAjB;IACI,OAAO,gBAAgB,CAAC;AAC5B,CAAC"}},{"offset":{"line":7,"column":0},"map":{"version":3,"file":"second-output.js","sourceRoot":"","sources":["second_part1.ts","second_part2.ts"],"names":[],"mappings":"AAIA,IAAU,CAAC,CAMV;AAND,WAAU,CAAC;IACP;QACI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,CAAC,EAAE,CAAC;AACR,CAAC,EANS,CAAC,KAAD,CAAC,QAMV;ACVD;IAAA;IAIA,CAAC;IAHG,uBAAW,GAAX;QACI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtC,CAAC;IACL,QAAC;AAAD,CAAC,AAJD,IAIC"}},{"offset":{"line":22,"column":41},"map":{"version":3,"file":"third-output.js","sourceRoot":"","sources":["third_part1.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;AAChB,CAAC,CAAC,WAAW,EAAE,CAAC"}}]}
|
||||
@@ -0,0 +1,26 @@
|
||||
var s = "Hello, world";
|
||||
console.log(s);
|
||||
console.log(f());
|
||||
function f() {
|
||||
return "JS does hoists";
|
||||
}
|
||||
//# sourceMappingURL=first-output.js.map
|
||||
var N;
|
||||
(function (N) {
|
||||
function f() {
|
||||
console.log('testing');
|
||||
}
|
||||
f();
|
||||
})(N || (N = {}));
|
||||
var C = (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.doSomething = function () {
|
||||
console.log("something got done");
|
||||
};
|
||||
return C;
|
||||
}());
|
||||
//# sourceMappingURL=second-output.js.map
|
||||
var c = new C();
|
||||
c.doSomething();
|
||||
//# sourceMappingURL=third-output.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"third-output.js","sections":[{"offset":{"line":0,"column":0},"map":{"version":3,"file":"first-output.js","sourceRoot":"","sources":["../first_part1.ts","../first_part2.ts","../first_part3.ts"],"names":[],"mappings":"AAIA,IAAM,CAAC,GAAG,cAAc,CAAC;AAMzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;ACVf,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;ACAjB;IACI,OAAO,gBAAgB,CAAC;AAC5B,CAAC"}},{"offset":{"line":7,"column":0},"map":{"version":3,"file":"second-output.js","sourceRoot":"","sources":["../second/second_part1.ts","../second/second_part2.ts"],"names":[],"mappings":"AAIA,IAAU,CAAC,CAMV;AAND,WAAU,CAAC;IACP;QACI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,CAAC,EAAE,CAAC;AACR,CAAC,EANS,CAAC,KAAD,CAAC,QAMV;ACVD;IAAA;IAIA,CAAC;IAHG,uBAAW,GAAX;QACI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtC,CAAC;IACL,QAAC;AAAD,CAAC,AAJD,IAIC"}},{"offset":{"line":22,"column":41},"map":{"version":3,"file":"third-output.js","sourceRoot":"","sources":["../../third_part1.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;AAChB,CAAC,CAAC,WAAW,EAAE,CAAC"}}]}
|
||||
@@ -14,5 +14,5 @@ function foo() {
|
||||
}
|
||||
// Shouldn't see any errors down here
|
||||
var y = {a} 1 };
|
||||
</>;
|
||||
</>;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ define(["require", "exports", "react"], function (require, exports, React) {
|
||||
// Should be OK
|
||||
var MainMenu = function (props) { return (<div>
|
||||
<h3>Main Menu</h3>
|
||||
</div>); };
|
||||
</div>); };
|
||||
var App = function (_a) {
|
||||
var children = _a.children;
|
||||
return (<div>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// @declaration: true
|
||||
// @target: es5
|
||||
|
||||
// @filename: other.ts
|
||||
type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
options: Experiment<Name>
|
||||
) => Experiment<Name>;
|
||||
export default createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
|
||||
// @filename: main.ts
|
||||
import other from "./other";
|
||||
export const obj = {
|
||||
[other.name]: 1,
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// @declaration: true
|
||||
// @target: es5
|
||||
|
||||
// @filename: other.ts
|
||||
type Experiment<Name> = {
|
||||
name: Name;
|
||||
};
|
||||
declare const createExperiment: <Name extends string>(
|
||||
options: Experiment<Name>
|
||||
) => Experiment<Name>;
|
||||
export default createExperiment({
|
||||
name: "foo"
|
||||
});
|
||||
|
||||
// @filename: main.ts
|
||||
import * as other2 from "./other";
|
||||
export const obj = {
|
||||
[other2.default.name]: 1
|
||||
};
|
||||
@@ -5,4 +5,12 @@ class Y extends Z {
|
||||
constructor() {
|
||||
super(X);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import X2 from 'file2';
|
||||
import X3 from 'file3';
|
||||
class Q extends Z {
|
||||
constructor() {
|
||||
super(X2, X3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// @experimentalDecorators: true
|
||||
// @emitDecoratorMetadata: true
|
||||
export class A {
|
||||
@test
|
||||
b: import('./b').B
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// @target: es5
|
||||
// @lib: esnext, dom
|
||||
// @downlevelIteration: true
|
||||
// https://github.com/Microsoft/TypeScript/issues/24722
|
||||
class A {
|
||||
b = async (...args: any[]) => {
|
||||
await Promise.resolve();
|
||||
const obj = { ["a"]: () => this }; // computed property name after `await` triggers case
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class C {
|
||||
//// *method() {
|
||||
//// yield* this.y();
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "addMissingMember",
|
||||
fixAllDescription: "Add all missing members",
|
||||
newFileContent:
|
||||
`class C {
|
||||
*method() {
|
||||
yield* this.y();
|
||||
}
|
||||
*y(): any {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}`,
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class C {
|
||||
//// method() {
|
||||
//// yield* this.y();
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "addMissingMember",
|
||||
fixAllDescription: "Add all missing members",
|
||||
newFileContent:
|
||||
`class C {
|
||||
method() {
|
||||
yield* this.y();
|
||||
}
|
||||
y(): any {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}`,
|
||||
});
|
||||
@@ -12,15 +12,15 @@
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
//// a: boolean;
|
||||
////
|
||||
//// static b: string;
|
||||
//// static b: boolean;
|
||||
////
|
||||
//// private c: string;
|
||||
//// private c: boolean;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
//// e: string | boolean;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
@@ -46,9 +46,9 @@ function fixes(name: string, type: string, options: { isPrivate?: boolean, noIni
|
||||
}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
...fixes("a", "string"),
|
||||
...fixes("c", "string", { isPrivate: true }),
|
||||
...fixes("e", "string | number"),
|
||||
...fixes("a", "boolean"),
|
||||
...fixes("c", "boolean", { isPrivate: true }),
|
||||
...fixes("e", "string | boolean"),
|
||||
...fixes("f", "1"),
|
||||
...fixes("g", '"123" | "456"'),
|
||||
...fixes("h", "boolean"),
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string;
|
||||
//// a: boolean;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: string = "";
|
||||
a: boolean = false;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -1,15 +0,0 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: number;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: number = 0;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -3,13 +3,13 @@
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string | number;
|
||||
//// a: string | boolean;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: string | number = "";
|
||||
a: string | boolean = false;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -12,15 +12,15 @@
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
//// a: boolean;
|
||||
////
|
||||
//// static b: string;
|
||||
//// static b: boolean;
|
||||
////
|
||||
//// private c: string;
|
||||
//// private c: boolean;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
//// e: string | boolean;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
@@ -35,6 +35,8 @@
|
||||
//// k: AT;
|
||||
////
|
||||
//// l: Foo;
|
||||
////
|
||||
//// m: number[];
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
@@ -50,15 +52,15 @@ class Foo {}
|
||||
|
||||
class T {
|
||||
|
||||
a: string = "";
|
||||
a: boolean = false;
|
||||
|
||||
static b: string;
|
||||
static b: boolean;
|
||||
|
||||
private c: string = "";
|
||||
private c: boolean = false;
|
||||
|
||||
d: number | undefined;
|
||||
|
||||
e: string | number = "";
|
||||
e: string | boolean = false;
|
||||
|
||||
f: 1 = 1;
|
||||
|
||||
@@ -73,5 +75,7 @@ class T {
|
||||
k: AT = new AT;
|
||||
|
||||
l: Foo = new Foo;
|
||||
|
||||
m: number[] = [];
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noLib: true
|
||||
// @noUnusedLocals: true
|
||||
|
||||
////let x = 0;
|
||||
////x = 1;
|
||||
////
|
||||
////export class C {
|
||||
//// private p: number;
|
||||
////
|
||||
//// m() { this.p = 0; }
|
||||
////}
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
newFileContent:
|
||||
`
|
||||
export class C {
|
||||
|
||||
m() { }
|
||||
}`,
|
||||
});
|
||||
@@ -57,7 +57,7 @@ verify.codeFixAll({
|
||||
x; z;
|
||||
}
|
||||
{
|
||||
const [x,] = o;
|
||||
const [x] = o;
|
||||
x;
|
||||
}
|
||||
{
|
||||
@@ -65,7 +65,7 @@ verify.codeFixAll({
|
||||
y;
|
||||
}
|
||||
{
|
||||
const [, y,] = o;
|
||||
const [, y] = o;
|
||||
y;
|
||||
}
|
||||
{
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
////"a"./**/
|
||||
|
||||
goTo.marker();
|
||||
verify.not.completionListContains('alert');
|
||||
verify.completionListContains('charAt');
|
||||
verify.completions({
|
||||
marker: "",
|
||||
exact: [
|
||||
"toString", "charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "localeCompare", "match", "replace", "search", "slice",
|
||||
"split", "substring", "toLowerCase", "toLocaleLowerCase", "toUpperCase", "toLocaleUpperCase", "trim", "length", "substr", "valueOf",
|
||||
],
|
||||
});
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////const x: 0 | "one" = /**/;
|
||||
|
||||
verify.completions({
|
||||
marker: "",
|
||||
includes: [
|
||||
{ name: "0", kind: "string", text: "0" },
|
||||
{ name: '"one"', kind: "string", text: '"one"' },
|
||||
],
|
||||
isNewIdentifierLocation: true,
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user