Merge branch 'master' into fix2-getConstraintOfIndexedAccess

Also fix test failure from last commit.
This commit is contained in:
Nathan Shively-Sanders
2017-08-28 10:02:54 -07:00
131 changed files with 1578 additions and 622 deletions
+1 -3
View File
@@ -49,6 +49,7 @@
"@types/run-sequence": "latest",
"@types/through2": "latest",
"browserify": "latest",
"browser-resolve": "^1.11.2",
"chai": "latest",
"convert-source-map": "latest",
"del": "latest",
@@ -93,8 +94,5 @@
"fs": false,
"os": false,
"path": false
},
"dependencies": {
"browser-resolve": "^1.11.2"
}
}
+91 -52
View File
@@ -497,6 +497,8 @@ namespace ts {
const builtinGlobals = createSymbolTable();
builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
const isNotOverloadAndNotAccessor = and(isNotOverload, isNotAccessor);
initializeTypeChecker();
return checker;
@@ -638,7 +640,7 @@ namespace ts {
});
}
function mergeModuleAugmentation(moduleName: LiteralExpression): void {
function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void {
const moduleAugmentation = <ModuleDeclaration>moduleName.parent;
if (moduleAugmentation.symbol.declarations[0] !== moduleAugmentation) {
// this is a combined symbol for multiple augmentations within the same file.
@@ -670,7 +672,8 @@ namespace ts {
mergeSymbol(mainModule, moduleAugmentation.symbol);
}
else {
error(moduleName, Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, moduleName.text);
// moduleName will be a StringLiteral since this is not `declare global`.
error(moduleName, Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, (moduleName as StringLiteral).text);
}
}
}
@@ -3112,6 +3115,12 @@ namespace ts {
return "(Anonymous function)";
}
}
if ((symbol as TransientSymbol).syntheticLiteralTypeOrigin) {
const stringValue = (symbol as TransientSymbol).syntheticLiteralTypeOrigin.value;
if (!isIdentifierText(stringValue, compilerOptions.target)) {
return `"${escapeString(stringValue, CharacterCodes.doubleQuote)}"`;
}
}
return unescapeLeadingUnderscores(symbol.escapedName);
}
@@ -5722,7 +5731,14 @@ namespace ts {
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
function addMemberForKeyType(t: Type, propertySymbol?: Symbol) {
function addMemberForKeyType(t: Type, propertySymbolOrIndex?: Symbol | number) {
let propertySymbol: Symbol;
// forEachType delegates to forEach, which calls with a numeric second argument
// the type system currently doesn't catch this incompatibility, so we annotate
// the function ourselves to indicate the runtime behavior and deal with it here
if (typeof propertySymbolOrIndex === "object") {
propertySymbol = propertySymbolOrIndex;
}
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
@@ -5742,6 +5758,7 @@ namespace ts {
prop.syntheticOrigin = propertySymbol;
prop.declarations = propertySymbol.declarations;
}
prop.syntheticLiteralTypeOrigin = t as StringLiteralType;
members.set(propName, prop);
}
else if (t.flags & TypeFlags.String) {
@@ -5914,7 +5931,7 @@ namespace ts {
const keepTypeParameterForMappedType = baseObjectType && getObjectFlags(baseObjectType) & ObjectFlags.Mapped &&
type.indexType.flags & TypeFlags.TypeParameter;
const baseIndexType = !keepTypeParameterForMappedType && getBaseConstraintOfType(type.indexType);
if (baseIndexType === stringType && (!baseObjectType || !getIndexInfoOfType(baseObjectType, IndexKind.String))) {
if (baseIndexType === stringType && !getIndexInfoOfType(baseObjectType || type.objectType, IndexKind.String)) {
// getIndexedAccessType returns `any` for X[string] where X doesn't have an index signature.
// to avoid this, return `undefined`.
return undefined;
@@ -7601,22 +7618,6 @@ namespace ts {
return anyType;
}
function getIndexedAccessForMappedType(type: MappedType, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
if (accessNode) {
// Check if the index type is assignable to 'keyof T' for the object type.
if (!isTypeAssignableTo(indexType, getIndexType(type))) {
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(type));
return unknownType;
}
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && type.declaration.readonlyToken) {
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(type));
}
}
const mapper = createTypeMapper([getTypeParameterFromMappedType(type)], [indexType]);
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
return instantiateType(getTemplateTypeFromMappedType(type), templateMapper);
}
function isGenericObjectType(type: Type): boolean {
return type.flags & TypeFlags.TypeVariable ? true :
getObjectFlags(type) & ObjectFlags.Mapped ? isGenericIndexType(getConstraintTypeFromMappedType(<MappedType>type)) :
@@ -7642,12 +7643,14 @@ namespace ts {
return false;
}
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
// access types with default property values as expressed by D.
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
// undefined if no transformation is possible.
function getTransformedIndexedAccessType(type: IndexedAccessType): Type {
const objectType = type.objectType;
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
// access types with default property values as expressed by D.
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType) && some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
const regularTypes: Type[] = [];
const stringIndexTypes: Type[] = [];
@@ -7664,20 +7667,23 @@ namespace ts {
getIntersectionType(stringIndexTypes)
]);
}
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
// construct the type Box<T[X]>.
if (isGenericMappedType(objectType)) {
const mapper = createTypeMapper([getTypeParameterFromMappedType(<MappedType>objectType)], [type.indexType]);
const objectTypeMapper = (<MappedType>objectType).mapper;
const templateMapper = objectTypeMapper ? combineTypeMappers(objectTypeMapper, mapper) : mapper;
return instantiateType(getTemplateTypeFromMappedType(<MappedType>objectType), templateMapper);
}
return undefined;
}
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type {
// If the object type is a mapped type { [P in K]: E }, where K is generic, we instantiate E using a mapper
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
// construct the type Box<T[X]>.
if (isGenericMappedType(objectType)) {
return getIndexedAccessForMappedType(<MappedType>objectType, indexType, accessNode);
}
// Otherwise, if the index type is generic, or if the object type is generic and doesn't originate in an
// expression, we are performing a higher-order index access where we cannot meaningfully access the properties
// of the object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates
// in an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]'
// If the index type is generic, or if the object type is generic and doesn't originate in an expression,
// we are performing a higher-order index access where we cannot meaningfully access the properties of the
// object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in
// an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]'
// has always been resolved eagerly using the constraint type of 'this' at the given location.
if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) && isGenericObjectType(objectType)) {
if (objectType.flags & TypeFlags.Any) {
@@ -9299,7 +9305,7 @@ namespace ts {
else if (target.flags & TypeFlags.IndexedAccess) {
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
// A is the apparent type of T.
const constraint = getConstraintOfType(<IndexedAccessType>target);
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>target);
if (constraint) {
if (result = isRelatedTo(source, constraint, reportErrors)) {
errorInfo = saveErrorInfo;
@@ -9339,7 +9345,7 @@ namespace ts {
else if (source.flags & TypeFlags.IndexedAccess) {
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
// A is the apparent type of S.
const constraint = getConstraintOfType(<IndexedAccessType>source);
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>source);
if (constraint) {
if (result = isRelatedTo(constraint, target, reportErrors)) {
errorInfo = saveErrorInfo;
@@ -15225,7 +15231,7 @@ namespace ts {
// example, given a 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
// return type of 'wrap'.
if (isExpression(node)) {
if (node.kind !== SyntaxKind.Decorator) {
const contextualType = getContextualType(node);
if (contextualType) {
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
@@ -16377,8 +16383,8 @@ namespace ts {
* Indicates whether a declaration can be treated as a constructor in a JavaScript
* file.
*/
function isJavaScriptConstructor(node: Declaration): boolean {
if (isInJavaScriptFile(node)) {
function isJavaScriptConstructor(node: Declaration | undefined): boolean {
if (node && isInJavaScriptFile(node)) {
// If the node has a @class tag, treat it like a constructor.
if (getJSDocClassTag(node)) return true;
@@ -16393,6 +16399,21 @@ namespace ts {
return false;
}
function getJavaScriptClassType(symbol: Symbol): Type | undefined {
if (isDeclarationOfFunctionOrClassExpression(symbol)) {
symbol = getSymbolOfNode((<VariableDeclaration>symbol.valueDeclaration).initializer);
}
if (isJavaScriptConstructor(symbol.valueDeclaration)) {
return getInferredClassType(symbol);
}
if (symbol.flags & SymbolFlags.Variable) {
const valueType = getTypeOfSymbol(symbol);
if (valueType.symbol && !isInferredClassType(valueType) && isJavaScriptConstructor(valueType.symbol.valueDeclaration)) {
return getInferredClassType(valueType.symbol);
}
}
}
function getInferredClassType(symbol: Symbol) {
const links = getSymbolLinks(symbol);
if (!links.inferredClassType) {
@@ -16436,16 +16457,14 @@ namespace ts {
// in a JS file
// Note:JS inferred classes might come from a variable declaration instead of a function declaration.
// In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration.
let funcSymbol = node.expression.kind === SyntaxKind.Identifier ?
const funcSymbol = node.expression.kind === SyntaxKind.Identifier ?
getResolvedSymbol(node.expression as Identifier) :
checkExpression(node.expression).symbol;
if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) {
funcSymbol = getSymbolOfNode((<VariableDeclaration>funcSymbol.valueDeclaration).initializer);
const type = funcSymbol && getJavaScriptClassType(funcSymbol);
if (type) {
return type;
}
if (funcSymbol && funcSymbol.flags & SymbolFlags.Function && (funcSymbol.members || getJSDocClassTag(funcSymbol.valueDeclaration))) {
return getInferredClassType(funcSymbol);
}
else if (noImplicitAny) {
if (noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
}
return anyType;
@@ -18815,6 +18834,10 @@ namespace ts {
const objectType = (<IndexedAccessType>type).objectType;
const indexType = (<IndexedAccessType>type).indexType;
if (isTypeAssignableTo(indexType, getIndexType(objectType))) {
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
getObjectFlags(objectType) & ObjectFlags.Mapped && (<MappedType>objectType).declaration.readonlyToken) {
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
}
return type;
}
// Check if we're indexing with a numeric type and if either object or index types
@@ -19156,6 +19179,8 @@ namespace ts {
: DeclarationSpaces.ExportNamespace;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
// A NamespaceImport declares an Alias, which is allowed to merge with other values within the module
case SyntaxKind.NamespaceImport:
return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue;
case SyntaxKind.ImportEqualsDeclaration:
let result = DeclarationSpaces.None;
@@ -22262,7 +22287,7 @@ namespace ts {
if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) {
return;
}
const exportedDeclarationsCount = countWhere(declarations, isNotOverload);
const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor);
if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) {
// it is legal to merge type alias with other values
// so count should be either 1 (just type alias) or 2 (type alias + merged value)
@@ -22278,11 +22303,16 @@ namespace ts {
});
links.exportsChecked = true;
}
}
function isNotOverload(declaration: Declaration): boolean {
return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) ||
!!(declaration as FunctionDeclaration).body;
}
function isNotAccessor(declaration: Declaration): boolean {
// Accessors check for their own matching duplicates, and in contexts where they are valid, there are already duplicate identifier checks
return !isAccessor(declaration);
}
function isNotOverload(declaration: Declaration): boolean {
return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) ||
!!(declaration as FunctionDeclaration).body;
}
function checkSourceElement(node: Node): void {
@@ -23479,6 +23509,15 @@ namespace ts {
}
function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
// ensure both `typeName` and `location` are parse tree nodes.
typeName = getParseTreeNode(typeName, isEntityName);
if (!typeName) return TypeReferenceSerializationKind.Unknown;
if (location) {
location = getParseTreeNode(location);
if (!location) return TypeReferenceSerializationKind.Unknown;
}
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
@@ -23767,7 +23806,7 @@ namespace ts {
}
// Initialize global symbol table
let augmentations: ReadonlyArray<StringLiteral>[];
let augmentations: ReadonlyArray<StringLiteral | Identifier>[];
for (const file of host.getSourceFiles()) {
if (!isExternalOrCommonJsModule(file)) {
mergeSymbolTable(globals, file.locals);
+1 -1
View File
@@ -21,7 +21,7 @@ namespace ts {
let declarationListContainerEnd = -1;
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: number[];
let currentLineMap: ReadonlyArray<number>;
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
let hasWrittenComment = false;
let disabled: boolean = printerOptions.removeComments;
+5 -1
View File
@@ -715,7 +715,7 @@ namespace ts {
return result;
}
export function sum<T extends Record<K, number>, K extends string>(array: T[], prop: K): number {
export function sum<T extends Record<K, number>, K extends string>(array: ReadonlyArray<T>, prop: K): number {
let result = 0;
for (const v of array) {
// TODO: Remove the following type assertion once the fix for #17069 is merged
@@ -2626,4 +2626,8 @@ namespace ts {
export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs;
}
export function and<T>(f: (arg: T) => boolean, g: (arg: T) => boolean) {
return (arg: T) => f(arg) && g(arg);
}
}
+1 -1
View File
@@ -60,7 +60,7 @@ namespace ts {
let enclosingDeclaration: Node;
let resultHasExternalModuleIndicator: boolean;
let currentText: string;
let currentLineMap: number[];
let currentLineMap: ReadonlyArray<number>;
let currentIdentifiers: Map<string>;
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
+1 -1
View File
@@ -3696,7 +3696,7 @@
"code": 95003
},
"Extract function into '{0}'": {
"Extract function into {0}": {
"category": "Message",
"code": 95004
}
+44 -3
View File
@@ -2339,13 +2339,13 @@ namespace ts {
: node;
}
export function createBundle(sourceFiles: SourceFile[]) {
export function createBundle(sourceFiles: ReadonlyArray<SourceFile>) {
const node = <Bundle>createNode(SyntaxKind.Bundle);
node.sourceFiles = sourceFiles;
return node;
}
export function updateBundle(node: Bundle, sourceFiles: SourceFile[]) {
export function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>) {
if (node.sourceFiles !== sourceFiles) {
return createBundle(sourceFiles);
}
@@ -2372,6 +2372,24 @@ namespace ts {
);
}
export function createImmediatelyInvokedArrowFunction(statements: Statement[]): CallExpression;
export function createImmediatelyInvokedArrowFunction(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
export function createImmediatelyInvokedArrowFunction(statements: Statement[], param?: ParameterDeclaration, paramValue?: Expression) {
return createCall(
createArrowFunction(
/*modifiers*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ param ? [param] : [],
/*type*/ undefined,
/*equalsGreaterThanToken*/ undefined,
createBlock(statements, /*multiLine*/ true)
),
/*typeArguments*/ undefined,
/*argumentsArray*/ paramValue ? [paramValue] : []
);
}
export function createComma(left: Expression, right: Expression) {
return <Expression>createBinary(left, SyntaxKind.CommaToken, right);
}
@@ -4036,8 +4054,31 @@ namespace ts {
}
}
/**
* Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions.
*
* A parenthesized expression can be ignored when all of the following are true:
*
* - It's `pos` and `end` are not -1
* - It does not have a custom source map range
* - It does not have a custom comment range
* - It does not have synthetic leading or trailing comments
*
* If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around
* the expression to maintain precedence, a new parenthesized expression should be created automatically when
* the containing expression is created/updated.
*/
function isIgnorableParen(node: Expression) {
return node.kind === SyntaxKind.ParenthesizedExpression
&& nodeIsSynthesized(node)
&& nodeIsSynthesized(getSourceMapRange(node))
&& nodeIsSynthesized(getCommentRange(node))
&& !some(getSyntheticLeadingComments(node))
&& !some(getSyntheticTrailingComments(node));
}
export function recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression {
if (outerExpression && isOuterExpression(outerExpression, kinds)) {
if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) {
return updateOuterExpression(
outerExpression,
recreateOuterExpressions(outerExpression.expression, innerExpression)
+43 -31
View File
@@ -205,13 +205,15 @@ namespace ts {
}
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
let diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
program.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken));
const diagnostics = [
...program.getOptionsDiagnostics(cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...program.getGlobalDiagnostics(cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (program.getCompilerOptions().declaration) {
diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken));
addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, cancellationToken));
}
return sortAndDeduplicateDiagnostics(diagnostics);
@@ -223,7 +225,7 @@ namespace ts {
getNewLine(): string;
}
export function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string {
export function formatDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string {
let output = "";
for (const diagnostic of diagnostics) {
@@ -399,7 +401,7 @@ namespace ts {
* @param oldProgram - Reuses an old program structure.
* @returns A 'Program' object.
*/
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
let program: Program;
let files: SourceFile[] = [];
let commonSourceDirectory: string;
@@ -888,7 +890,7 @@ namespace ts {
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
if (resolveModuleNamesWorker) {
const moduleNames = map(concatenate(newSourceFile.imports, newSourceFile.moduleAugmentations), getTextOfLiteral);
const moduleNames = getModuleNames(newSourceFile);
const oldProgramState = { program: oldProgram, file: oldSourceFile, modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState);
// ensure that module resolution results are still correct
@@ -996,7 +998,7 @@ namespace ts {
}
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
let declarationDiagnostics: Diagnostic[] = [];
let declarationDiagnostics: ReadonlyArray<Diagnostic> = [];
if (options.noEmit) {
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
@@ -1006,10 +1008,12 @@ namespace ts {
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
// get any preEmit diagnostics, not just the ones
if (options.noEmitOnError) {
const diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
program.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken));
const diagnostics = [
...program.getOptionsDiagnostics(cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...program.getGlobalDiagnostics(cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
@@ -1060,8 +1064,8 @@ namespace ts {
function getDiagnosticsHelper(
sourceFile: SourceFile,
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
cancellationToken: CancellationToken): Diagnostic[] {
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => ReadonlyArray<Diagnostic>,
cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
if (sourceFile) {
return getDiagnostics(sourceFile, cancellationToken);
}
@@ -1073,15 +1077,15 @@ namespace ts {
}));
}
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken);
}
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken);
}
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
const options = program.getCompilerOptions();
// collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit)
if (!sourceFile || options.out || options.outFile) {
@@ -1092,7 +1096,7 @@ namespace ts {
}
}
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): ReadonlyArray<Diagnostic> {
// For JavaScript files, we report semantic errors for using TypeScript-only
// constructs from within a JavaScript file as syntactic errors.
if (isSourceFileJavaScript(sourceFile)) {
@@ -1430,12 +1434,10 @@ namespace ts {
return a.fileName === b.fileName;
}
function moduleNameIsEqualTo(a: LiteralExpression, b: LiteralExpression): boolean {
return a.text === b.text;
}
function getTextOfLiteral(literal: LiteralExpression): string {
return literal.text;
function moduleNameIsEqualTo(a: StringLiteral | Identifier, b: StringLiteral | Identifier): boolean {
return a.kind === SyntaxKind.StringLiteral
? b.kind === SyntaxKind.StringLiteral && a.text === b.text
: b.kind === SyntaxKind.Identifier && a.escapedText === b.escapedText;
}
function collectExternalModuleReferences(file: SourceFile): void {
@@ -1448,7 +1450,7 @@ namespace ts {
// file.imports may not be undefined if there exists dynamic import
let imports: StringLiteral[];
let moduleAugmentations: StringLiteral[];
let moduleAugmentations: Array<StringLiteral | Identifier>;
let ambientModules: string[];
// If we are importing helpers, we need to add a synthetic reference to resolve the
@@ -1477,7 +1479,7 @@ namespace ts {
return;
function collectModuleReferences(node: Node, inAmbientModule: boolean): void {
function collectModuleReferences(node: Statement, inAmbientModule: boolean): void {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
@@ -1499,8 +1501,8 @@ namespace ts {
break;
case SyntaxKind.ModuleDeclaration:
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) {
const moduleName = <StringLiteral>(<ModuleDeclaration>node).name; // TODO: GH#17347
const nameText = ts.getTextOfIdentifierOrLiteral(moduleName);
const moduleName = (<ModuleDeclaration>node).name;
const nameText = getTextOfIdentifierOrLiteral(moduleName);
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
// This will happen in two cases:
// - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
@@ -1817,8 +1819,7 @@ namespace ts {
collectExternalModuleReferences(file);
if (file.imports.length || file.moduleAugmentations.length) {
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
const nonGlobalAugmentation = filter(file.moduleAugmentations, (moduleAugmentation) => moduleAugmentation.kind === SyntaxKind.StringLiteral);
const moduleNames = map(concatenate(file.imports, nonGlobalAugmentation), getTextOfLiteral);
const moduleNames = getModuleNames(file);
const oldProgramState = { program: oldProgram, file, modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState);
Debug.assert(resolutions.length === moduleNames.length);
@@ -2229,4 +2230,15 @@ namespace ts {
Debug.assert(names.every(name => name !== undefined), "A name is undefined.", () => JSON.stringify(names));
return names;
}
function getModuleNames({ imports, moduleAugmentations }: SourceFile): string[] {
const res = imports.map(i => i.text);
for (const aug of moduleAugmentations) {
if (aug.kind === SyntaxKind.StringLiteral) {
res.push(aug.text);
}
// Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`.
}
return res;
}
}
+1 -1
View File
@@ -343,7 +343,7 @@ namespace ts {
}
/* @internal */
export function getLineStarts(sourceFile: SourceFileLike): number[] {
export function getLineStarts(sourceFile: SourceFileLike): ReadonlyArray<number> {
return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
}
+1 -1
View File
@@ -92,7 +92,7 @@ namespace ts {
* @param transforms An array of `TransformerFactory` callbacks.
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
*/
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: T[], transformers: TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: ReadonlyArray<T>, transformers: ReadonlyArray<TransformerFactory<T>>, allowDtsFiles: boolean): TransformationResult<T> {
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
+1 -1
View File
@@ -409,7 +409,7 @@ namespace ts {
*/
function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: Expression, propertyName: PropertyName): LeftHandSideExpression {
if (isComputedPropertyName(propertyName)) {
const argumentExpression = ensureIdentifier(flattenContext, propertyName.expression, /*reuseIdentifierExpressions*/ false, /*location*/ propertyName);
const argumentExpression = ensureIdentifier(flattenContext, visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName);
return createElementAccess(value, argumentExpression);
}
else if (isStringOrNumericLiteral(propertyName)) {
+4 -55
View File
@@ -339,64 +339,12 @@ namespace ts {
&& !(<ReturnStatement>node).expression;
}
function isClassLikeVariableStatement(node: Node) {
if (!isVariableStatement(node)) return false;
const variable = singleOrUndefined((<VariableStatement>node).declarationList.declarations);
return variable
&& variable.initializer
&& isIdentifier(variable.name)
&& (isClassLike(variable.initializer)
|| (isAssignmentExpression(variable.initializer)
&& isIdentifier(variable.initializer.left)
&& isClassLike(variable.initializer.right)));
}
function isTypeScriptClassWrapper(node: Node) {
const call = tryCast(node, isCallExpression);
if (!call || isParseTreeNode(call) ||
some(call.typeArguments) ||
some(call.arguments)) {
return false;
}
const func = tryCast(skipOuterExpressions(call.expression), isFunctionExpression);
if (!func || isParseTreeNode(func) ||
some(func.typeParameters) ||
some(func.parameters) ||
func.type ||
!func.body) {
return false;
}
const statements = func.body.statements;
if (statements.length < 2) {
return false;
}
const firstStatement = statements[0];
if (isParseTreeNode(firstStatement) ||
!isClassLike(firstStatement) &&
!isClassLikeVariableStatement(firstStatement)) {
return false;
}
const lastStatement = elementAt(statements, -1);
const returnStatement = tryCast(isVariableStatement(lastStatement) ? elementAt(statements, -2) : lastStatement, isReturnStatement);
if (!returnStatement ||
!returnStatement.expression ||
!isIdentifier(skipOuterExpressions(returnStatement.expression))) {
return false;
}
return true;
}
function shouldVisitNode(node: Node): boolean {
return (node.transformFlags & TransformFlags.ContainsES2015) !== 0
|| convertedLoopState !== undefined
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block)))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node))
|| isTypeScriptClassWrapper(node);
|| (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0;
}
function visitor(node: Node): VisitResult<Node> {
@@ -3308,13 +3256,14 @@ namespace ts {
* @param node a CallExpression.
*/
function visitCallExpression(node: CallExpression) {
if (isTypeScriptClassWrapper(node)) {
if (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) {
return visitTypeScriptClassWrapper(node);
}
if (node.transformFlags & TransformFlags.ES2015) {
return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true);
}
return updateCall(
node,
visitNode(node.expression, callExpressionVisitor, isExpression),
@@ -3357,7 +3306,7 @@ namespace ts {
// We skip any outer expressions in a number of places to get to the innermost
// expression, but we will restore them later to preserve comments and source maps.
const body = cast(skipOuterExpressions(node.expression), isFunctionExpression).body;
const body = cast(cast(skipOuterExpressions(node.expression), isArrowFunction).body, isBlock);
// The class statements are the statements generated by visiting the first statement of the
// body (1), while all other statements are added to remainingStatements (2)
+24 -21
View File
@@ -430,26 +430,29 @@ namespace ts {
*/
function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
if (currentModuleInfo.exportEquals) {
if (emitAsReturn) {
const statement = createReturn(currentModuleInfo.exportEquals.expression);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
statements.push(statement);
}
else {
const statement = createStatement(
createAssignment(
createPropertyAccess(
createIdentifier("module"),
"exports"
),
currentModuleInfo.exportEquals.expression
)
);
const expressionResult = visitNode(currentModuleInfo.exportEquals.expression, importCallExpressionVisitor);
if (expressionResult) {
if (emitAsReturn) {
const statement = createReturn(expressionResult);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
statements.push(statement);
}
else {
const statement = createStatement(
createAssignment(
createPropertyAccess(
createIdentifier("module"),
"exports"
),
expressionResult
)
);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoComments);
statements.push(statement);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoComments);
statements.push(statement);
}
}
}
}
@@ -497,7 +500,7 @@ namespace ts {
}
}
function importCallExpressionVisitor(node: Node): VisitResult<Node> {
function importCallExpressionVisitor(node: Expression): VisitResult<Expression> {
// This visitor does not need to descend into the tree if there is no dynamic import,
// as export/import statements are only transformed at the top level of a file.
if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) {
@@ -1204,7 +1207,7 @@ namespace ts {
}
if (hasModifier(decl, ModifierFlags.Export)) {
const exportName = hasModifier(decl, ModifierFlags.Default) ? createIdentifier("default") : decl.name;
const exportName = hasModifier(decl, ModifierFlags.Default) ? createIdentifier("default") : getDeclarationName(decl);
statements = appendExportStatement(statements, exportName, getLocalName(decl), /*location*/ decl);
}
+5 -2
View File
@@ -613,13 +613,16 @@ namespace ts {
addRange(statements, context.endLexicalEnvironment());
const iife = createImmediatelyInvokedArrowFunction(statements);
setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper);
const varStatement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false),
/*type*/ undefined,
createImmediatelyInvokedFunctionExpression(statements)
iife
)
])
);
@@ -1944,7 +1947,7 @@ namespace ts {
const name = getMutableClone(<Identifier>node);
name.flags &= ~NodeFlags.Synthesized;
name.original = undefined;
name.parent = currentScope;
name.parent = getParseTreeNode(currentScope); // ensure the parent is set to a parse tree node.
if (useFallback) {
return createLogicalAnd(
createStrictInequality(
+1 -1
View File
@@ -124,7 +124,7 @@ namespace ts {
else {
// export class x { }
const name = (<ClassDeclaration>node).name;
if (!uniqueExports.get(unescapeLeadingUnderscores(name.escapedText))) {
if (name && !uniqueExports.get(unescapeLeadingUnderscores(name.escapedText))) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(unescapeLeadingUnderscores(name.escapedText), true);
exportedNames = append(exportedNames, name);
+3 -3
View File
@@ -469,7 +469,7 @@ namespace ts {
let diagnostics: Diagnostic[];
// First get and report any syntactic errors.
diagnostics = program.getSyntacticDiagnostics();
diagnostics = program.getSyntacticDiagnostics().slice();
// If we didn't have any syntactic errors, then also try getting the global and
// semantic errors.
@@ -477,13 +477,13 @@ namespace ts {
diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
if (diagnostics.length === 0) {
diagnostics = program.getSemanticDiagnostics();
diagnostics = program.getSemanticDiagnostics().slice();
}
}
// Otherwise, emit and report any errors we ran into.
const emitOutput = program.emit();
diagnostics = diagnostics.concat(emitOutput.diagnostics);
addRange(diagnostics, emitOutput.diagnostics);
reportDiagnostics(sortAndDeduplicateDiagnostics(diagnostics), compilerHost);
+27 -23
View File
@@ -2254,7 +2254,7 @@ namespace ts {
*/
export interface SourceFileLike {
readonly text: string;
lineMap: number[];
lineMap: ReadonlyArray<number>;
}
@@ -2286,16 +2286,16 @@ namespace ts {
*/
/* @internal */ redirectInfo?: RedirectInfo | undefined;
amdDependencies: AmdDependency[];
amdDependencies: ReadonlyArray<AmdDependency>;
moduleName: string;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<FileReference>;
languageVariant: LanguageVariant;
isDeclarationFile: boolean;
// this map is used by transpiler to supply alternative names for dependencies (i.e. in case of bundling)
/* @internal */
renamedDependencies?: Map<string>;
renamedDependencies?: ReadonlyMap<string>;
/**
* lib.d.ts should have a reference comment like
@@ -2331,19 +2331,20 @@ namespace ts {
/* @internal */ jsDocDiagnostics?: Diagnostic[];
// Stores additional file-level diagnostics reported by the program
/* @internal */ additionalSyntacticDiagnostics?: Diagnostic[];
/* @internal */ additionalSyntacticDiagnostics?: ReadonlyArray<Diagnostic>;
// Stores a line map for the file.
// This field should never be used directly to obtain line map, use getLineMap function instead.
/* @internal */ lineMap: number[];
/* @internal */ classifiableNames?: UnderscoreEscapedMap<true>;
/* @internal */ lineMap: ReadonlyArray<number>;
/* @internal */ classifiableNames?: ReadonlyUnderscoreEscapedMap<true>;
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
// It is used to resolve module names in the checker.
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
/* @internal */ resolvedModules: Map<ResolvedModuleFull>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ imports: ReadonlyArray<StringLiteral>;
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral>;
// Identifier only if `declare global`
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral | Identifier>;
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
@@ -2351,7 +2352,7 @@ namespace ts {
export interface Bundle extends Node {
kind: SyntaxKind.Bundle;
sourceFiles: SourceFile[];
sourceFiles: ReadonlyArray<SourceFile>;
}
export interface JsonSourceFile extends SourceFile {
@@ -2398,19 +2399,19 @@ namespace ts {
/**
* Get a list of root file names that were passed to a 'createProgram'
*/
getRootFileNames(): string[];
getRootFileNames(): ReadonlyArray<string>;
/**
* Get a list of files in the program
*/
getSourceFiles(): SourceFile[];
getSourceFiles(): ReadonlyArray<SourceFile>;
/**
* Get a list of file names that were passed to 'createProgram' or referenced in a
* program source file but could not be located.
*/
/* @internal */
getMissingFilePaths(): Path[];
getMissingFilePaths(): ReadonlyArray<Path>;
/**
* Emits the JavaScript and declaration files. If targetSourceFile is not specified, then
@@ -2424,11 +2425,11 @@ namespace ts {
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Gets a type checker that can be used to semantically analyze source files in the program.
@@ -2522,7 +2523,7 @@ namespace ts {
export interface EmitResult {
emitSkipped: boolean;
/** Contains declaration emit diagnostics */
diagnostics: Diagnostic[];
diagnostics: ReadonlyArray<Diagnostic>;
emittedFiles: string[]; // Array of files the compiler wrote to disk
/* @internal */ sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
@@ -2531,9 +2532,9 @@ namespace ts {
export interface TypeCheckerHost {
getCompilerOptions(): CompilerOptions;
getSourceFiles(): SourceFile[];
getSourceFiles(): ReadonlyArray<SourceFile>;
getSourceFile(fileName: string): SourceFile;
getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective>;
}
export interface TypeChecker {
@@ -2972,6 +2973,7 @@ namespace ts {
leftSpread?: Symbol; // Left source for synthetic spread property
rightSpread?: Symbol; // Right source for synthetic spread property
syntheticOrigin?: Symbol; // For a property on a mapped or spread type, points back to the original property
syntheticLiteralTypeOrigin?: StringLiteralType; // For a property on a mapped type, indicates the type whose text to use as the declaration name, instead of the symbol name
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked
@@ -3315,6 +3317,7 @@ namespace ts {
/* @internal */
export interface MappedType extends ObjectType {
// { [typeParameter in constraintType]: templateType }
declaration: MappedTypeNode;
typeParameter?: TypeParameter;
constraintType?: Type;
@@ -4137,7 +4140,7 @@ namespace ts {
export interface SourceMapSource {
fileName: string;
text: string;
/* @internal */ lineMap: number[];
/* @internal */ lineMap: ReadonlyArray<number>;
skipTrivia?: (pos: number) => number;
}
@@ -4184,6 +4187,7 @@ namespace ts {
HasEndOfDeclarationMarker = 1 << 22, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions.
/*@internal*/ TypeScriptClassWrapper = 1 << 25, // The node is an IIFE class wrapper created by the ts transform.
}
export interface EmitHelper {
@@ -4244,7 +4248,7 @@ namespace ts {
/* @internal */
export interface EmitHost extends ScriptReferenceHost {
getSourceFiles(): SourceFile[];
getSourceFiles(): ReadonlyArray<SourceFile>;
/* @internal */
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
+78 -55
View File
@@ -2068,9 +2068,9 @@ namespace ts {
|| kind === SyntaxKind.SourceFile;
}
export function nodeIsSynthesized(node: TextRange): boolean {
return positionIsSynthesized(node.pos)
|| positionIsSynthesized(node.end);
export function nodeIsSynthesized(range: TextRange): boolean {
return positionIsSynthesized(range.pos)
|| positionIsSynthesized(range.end);
}
export function getOriginalSourceFile(sourceFile: SourceFile) {
@@ -2380,6 +2380,7 @@ namespace ts {
"\u2029": "\\u2029", // paragraphSeparator
"\u0085": "\\u0085" // nextLine
});
const escapedNullRegExp = /\\0[0-9]/g;
/**
* Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
@@ -2391,7 +2392,11 @@ namespace ts {
quoteChar === CharacterCodes.backtick ? backtickQuoteEscapedCharsRegExp :
quoteChar === CharacterCodes.singleQuote ? singleQuoteEscapedCharsRegExp :
doubleQuoteEscapedCharsRegExp;
return s.replace(escapedCharsRegExp, getReplacement);
return s.replace(escapedCharsRegExp, getReplacement).replace(escapedNullRegExp, nullReplacement);
}
function nullReplacement(c: string) {
return "\\x00" + c.charAt(c.length - 1);
}
function getReplacement(c: string) {
@@ -2572,7 +2577,7 @@ namespace ts {
* @param host An EmitHost.
* @param targetSourceFile An optional target source file to emit.
*/
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): SourceFile[] {
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): ReadonlyArray<SourceFile> {
const options = host.getCompilerOptions();
const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
if (options.outFile || options.out) {
@@ -4946,49 +4951,43 @@ namespace ts {
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.PropertyAccessExpression
|| kind === SyntaxKind.ElementAccessExpression
|| kind === SyntaxKind.NewExpression
|| kind === SyntaxKind.CallExpression
|| kind === SyntaxKind.JsxElement
|| kind === SyntaxKind.JsxSelfClosingElement
|| kind === SyntaxKind.TaggedTemplateExpression
|| kind === SyntaxKind.ArrayLiteralExpression
|| kind === SyntaxKind.ParenthesizedExpression
|| kind === SyntaxKind.ObjectLiteralExpression
|| kind === SyntaxKind.ClassExpression
|| kind === SyntaxKind.FunctionExpression
|| kind === SyntaxKind.Identifier
|| kind === SyntaxKind.RegularExpressionLiteral
|| kind === SyntaxKind.NumericLiteral
|| kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral
|| kind === SyntaxKind.TemplateExpression
|| kind === SyntaxKind.FalseKeyword
|| kind === SyntaxKind.NullKeyword
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.TrueKeyword
|| kind === SyntaxKind.SuperKeyword
|| kind === SyntaxKind.ImportKeyword
|| kind === SyntaxKind.NonNullExpression
|| kind === SyntaxKind.MetaProperty;
}
/* @internal */
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}
function isUnaryExpressionKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.PrefixUnaryExpression
|| kind === SyntaxKind.PostfixUnaryExpression
|| kind === SyntaxKind.DeleteExpression
|| kind === SyntaxKind.TypeOfExpression
|| kind === SyntaxKind.VoidExpression
|| kind === SyntaxKind.AwaitExpression
|| kind === SyntaxKind.TypeAssertionExpression
|| isLeftHandSideExpressionKind(kind);
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ClassExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.Identifier:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NonNullExpression:
case SyntaxKind.MetaProperty:
case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression
return true;
default:
return false;
}
}
/* @internal */
@@ -4996,6 +4995,21 @@ namespace ts {
return isUnaryExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}
function isUnaryExpressionKind(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.TypeAssertionExpression:
return true;
default:
return isLeftHandSideExpressionKind(kind);
}
}
/* @internal */
export function isUnaryExpressionWithWrite(expr: Node): expr is PrefixUnaryExpression | PostfixUnaryExpression {
switch (expr.kind) {
@@ -5009,23 +5023,32 @@ namespace ts {
}
}
function isExpressionKind(kind: SyntaxKind) {
return kind === SyntaxKind.ConditionalExpression
|| kind === SyntaxKind.YieldExpression
|| kind === SyntaxKind.ArrowFunction
|| kind === SyntaxKind.BinaryExpression
|| kind === SyntaxKind.SpreadElement
|| kind === SyntaxKind.AsExpression
|| kind === SyntaxKind.OmittedExpression
|| kind === SyntaxKind.CommaListExpression
|| isUnaryExpressionKind(kind);
}
/* @internal */
/**
* Determines whether a node is an expression based only on its kind.
* Use `isPartOfExpression` if not in transforms.
*/
export function isExpression(node: Node): node is Expression {
return isExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}
function isExpressionKind(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.ConditionalExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.BinaryExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.AsExpression:
case SyntaxKind.OmittedExpression:
case SyntaxKind.CommaListExpression:
case SyntaxKind.PartiallyEmittedExpression:
return true;
default:
return isUnaryExpressionKind(kind);
}
}
export function isAssertionExpression(node: Node): node is AssertionExpression {
const kind = node.kind;
return kind === SyntaxKind.TypeAssertionExpression
+37 -17
View File
@@ -490,7 +490,8 @@ namespace FourSlash {
}
private getDiagnostics(fileName: string): ts.Diagnostic[] {
return this.languageService.getSyntacticDiagnostics(fileName).concat(this.languageService.getSemanticDiagnostics(fileName));
return ts.concatenate(this.languageService.getSyntacticDiagnostics(fileName),
this.languageService.getSemanticDiagnostics(fileName));
}
private getAllDiagnostics(): ts.Diagnostic[] {
@@ -1148,7 +1149,7 @@ namespace FourSlash {
this.testDiagnostics(expected, diagnostics);
}
private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) {
private testDiagnostics(expected: string, diagnostics: ReadonlyArray<ts.Diagnostic>) {
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
const actual = stringify(realized);
assert.equal(actual, expected);
@@ -1585,7 +1586,7 @@ namespace FourSlash {
public printErrorList() {
const syntacticErrors = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
const semanticErrors = this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
const errorList = syntacticErrors.concat(semanticErrors);
const errorList = ts.concatenate(syntacticErrors, semanticErrors);
Harness.IO.log(`Error list (${errorList.length} errors)`);
if (errorList.length) {
@@ -2760,20 +2761,25 @@ namespace FourSlash {
});
}
public verifyRefactorAvailable(negative: boolean, name?: string, subName?: string) {
public verifyRefactorAvailable(negative: boolean, name: string, actionName?: string) {
const selection = this.getSelection();
let refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, selection) || [];
if (name) {
refactors = refactors.filter(r => r.name === name && (subName === undefined || r.actions.some(a => a.name === subName)));
}
refactors = refactors.filter(r => r.name === name && (actionName === undefined || r.actions.some(a => a.name === actionName)));
const isAvailable = refactors.length > 0;
if (negative && isAvailable) {
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found some: ${refactors.map(r => r.name).join(", ")}`);
if (negative) {
if (isAvailable) {
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found: ${refactors.map(r => r.name).join(", ")}`);
}
}
else if (!negative && !isAvailable) {
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`);
else {
if (!isAvailable) {
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`);
}
if (refactors.length > 1) {
this.raiseError(`${refactors.length} available refactors both have name ${name} and action ${actionName}`);
}
}
}
@@ -2793,14 +2799,22 @@ namespace FourSlash {
}
}
public applyRefactor(refactorName: string, actionName: string) {
public applyRefactor({ refactorName, actionName, actionDescription }: FourSlashInterface.ApplyRefactorOptions) {
const range = this.getSelection();
const refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, range);
const refactor = ts.find(refactors, r => r.name === refactorName);
const refactor = refactors.find(r => r.name === refactorName);
if (!refactor) {
this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.`);
}
const action = refactor.actions.find(a => a.name === actionName);
if (!action) {
this.raiseError(`The expected action: ${action} is not included in: ${refactor.actions.map(a => a.name)}`);
}
if (action.description !== actionDescription) {
this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`);
}
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName);
for (const edit of editInfo.edits) {
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
@@ -3681,8 +3695,8 @@ namespace FourSlashInterface {
this.state.verifyApplicableRefactorAvailableForRange(this.negative);
}
public refactorAvailable(name?: string, subName?: string) {
this.state.verifyRefactorAvailable(this.negative, name, subName);
public refactorAvailable(name: string, actionName?: string) {
this.state.verifyRefactorAvailable(this.negative, name, actionName);
}
}
@@ -4080,8 +4094,8 @@ namespace FourSlashInterface {
this.state.enableFormatting = false;
}
public applyRefactor(refactorName: string, actionName: string) {
this.state.applyRefactor(refactorName, actionName);
public applyRefactor(options: ApplyRefactorOptions) {
this.state.applyRefactor(options);
}
}
@@ -4294,4 +4308,10 @@ namespace FourSlashInterface {
return { classificationType, text, textSpan };
}
}
export interface ApplyRefactorOptions {
refactorName: string;
actionName: string;
actionDescription: string;
}
}
+5 -5
View File
@@ -207,7 +207,7 @@ namespace Utils {
return a !== undefined && typeof a.pos === "number";
}
export function convertDiagnostics(diagnostics: ts.Diagnostic[]) {
export function convertDiagnostics(diagnostics: ReadonlyArray<ts.Diagnostic>) {
return diagnostics.map(convertDiagnostic);
}
@@ -337,7 +337,7 @@ namespace Utils {
}
}
export function assertDiagnosticsEquals(array1: ts.Diagnostic[], array2: ts.Diagnostic[]) {
export function assertDiagnosticsEquals(array1: ReadonlyArray<ts.Diagnostic>, array2: ReadonlyArray<ts.Diagnostic>) {
if (array1 === array2) {
return;
}
@@ -1284,12 +1284,12 @@ namespace Harness {
return normalized;
}
export function minimalDiagnosticsToString(diagnostics: ts.Diagnostic[]) {
export function minimalDiagnosticsToString(diagnostics: ReadonlyArray<ts.Diagnostic>) {
return ts.formatDiagnostics(diagnostics, { getCanonicalFileName, getCurrentDirectory: () => "", getNewLine: () => Harness.IO.newLine() });
}
export function getErrorBaseline(inputFiles: TestFile[], diagnostics: ts.Diagnostic[]) {
diagnostics.sort(ts.compareDiagnostics);
export function getErrorBaseline(inputFiles: ReadonlyArray<TestFile>, diagnostics: ReadonlyArray<ts.Diagnostic>) {
diagnostics = diagnostics.slice().sort(ts.compareDiagnostics);
let outputLines = "";
// Count up all errors that were found in files other than lib.d.ts so we don't miss any
let totalErrorsReportedInNonLibraryFiles = 0;
+26 -21
View File
@@ -5,7 +5,7 @@
interface ProjectRunnerTestCase {
scenario: string;
projectRoot: string; // project where it lives - this also is the current directory when compiling
inputFiles: string[]; // list of input files to be given to program
inputFiles: ReadonlyArray<string>; // list of input files to be given to program
resolveMapRoot?: boolean; // should we resolve this map root and give compiler the absolute disk path as map root?
resolveSourceRoot?: boolean; // should we resolve this source root and give compiler the absolute disk path as map root?
baselineCheck?: boolean; // Verify the baselines of output files, if this is false, we will write to output to the disk but there is no verification of baselines
@@ -15,8 +15,8 @@ interface ProjectRunnerTestCase {
interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
// Apart from actual test case the results of the resolution
resolvedInputFiles: string[]; // List of files that were asked to read by compiler
emittedFiles: string[]; // List of files that were emitted by the compiler
resolvedInputFiles: ReadonlyArray<string>; // List of files that were asked to read by compiler
emittedFiles: ReadonlyArray<string>; // List of files that were emitted by the compiler
}
interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.GeneratedFile {
@@ -24,12 +24,12 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera
}
interface CompileProjectFilesResult {
configFileSourceFiles: ts.SourceFile[];
configFileSourceFiles: ReadonlyArray<ts.SourceFile>;
moduleKind: ts.ModuleKind;
program?: ts.Program;
compilerOptions?: ts.CompilerOptions;
errors: ts.Diagnostic[];
sourceMapData?: ts.SourceMapData[];
errors: ReadonlyArray<ts.Diagnostic>;
sourceMapData?: ReadonlyArray<ts.SourceMapData>;
}
interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
@@ -125,17 +125,17 @@ class ProjectRunner extends RunnerBase {
return Harness.IO.resolvePath(testCase.projectRoot);
}
function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ts.SourceFile[],
getInputFiles: () => string[],
function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ReadonlyArray<ts.SourceFile>,
getInputFiles: () => ReadonlyArray<string>,
getSourceFileTextImpl: (fileName: string) => string,
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
compilerOptions: ts.CompilerOptions): CompileProjectFilesResult {
const program = ts.createProgram(getInputFiles(), compilerOptions, createCompilerHost());
let errors = ts.getPreEmitDiagnostics(program);
const errors = ts.getPreEmitDiagnostics(program);
const emitResult = program.emit();
errors = ts.concatenate(errors, emitResult.diagnostics);
ts.addRange(errors, emitResult.diagnostics);
const sourceMapData = emitResult.sourceMaps;
// Clean up source map data that will be used in baselining
@@ -235,7 +235,7 @@ class ProjectRunner extends RunnerBase {
compilerOptions,
sourceMapData: projectCompilerResult.sourceMapData,
outputFiles,
errors: errors ? errors.concat(projectCompilerResult.errors) : projectCompilerResult.errors,
errors: errors ? ts.concatenate(errors, projectCompilerResult.errors) : projectCompilerResult.errors,
};
function createCompilerOptions() {
@@ -422,16 +422,21 @@ class ProjectRunner extends RunnerBase {
}
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
const inputFiles = ts.map(compilerResult.configFileSourceFiles.concat(
compilerResult.program ?
ts.filter(compilerResult.program.getSourceFiles(), sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)) :
[]),
(sourceFile): Harness.Compiler.TestFile => ({
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
RunnerBase.removeFullPaths(sourceFile.fileName) :
sourceFile.fileName,
content: sourceFile.text
}));
const inputSourceFiles = compilerResult.configFileSourceFiles.slice();
if (compilerResult.program) {
for (const sourceFile of compilerResult.program.getSourceFiles()) {
if (!Harness.isDefaultLibraryFile(sourceFile.fileName)) {
inputSourceFiles.push(sourceFile);
}
}
}
const inputFiles = inputSourceFiles.map<Harness.Compiler.TestFile>(sourceFile => ({
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
RunnerBase.removeFullPaths(sourceFile.fileName) :
sourceFile.fileName,
content: sourceFile.text
}));
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
}
+1
View File
@@ -125,6 +125,7 @@
"./unittests/printer.ts",
"./unittests/transform.ts",
"./unittests/customTransforms.ts",
"./unittests/extractMethods.ts",
"./unittests/textChanges.ts",
"./unittests/telemetry.ts",
"./unittests/programMissingFiles.ts"
+21 -2
View File
@@ -3,12 +3,11 @@
namespace ts {
describe("customTransforms", () => {
function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: CustomTransformers) {
function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: CustomTransformers, options: CompilerOptions = {}) {
it(name, () => {
const roots = sources.map(source => createSourceFile(source.file, source.text, ScriptTarget.ES2015));
const fileMap = arrayToMap(roots, file => file.fileName);
const outputs = createMap<string>();
const options: CompilerOptions = {};
const host: CompilerHost = {
getSourceFile: (fileName) => fileMap.get(fileName),
getDefaultLibFileName: () => "lib.d.ts",
@@ -82,5 +81,25 @@ namespace ts {
emitsCorrectly("before", sources, { before: [before] });
emitsCorrectly("after", sources, { after: [after] });
emitsCorrectly("both", sources, { before: [before], after: [after] });
emitsCorrectly("before+decorators", [{
file: "source.ts",
text: `
declare const dec: any;
class B {}
@dec export class C { constructor(b: B) { } }
'change'
`
}], {before: [
context => node => visitNode(node, function visitor(node: Node): Node {
if (isStringLiteral(node) && node.text === "change") return createLiteral("changed");
return visitEachChild(node, visitor, context);
})
]}, {
target: ScriptTarget.ES5,
module: ModuleKind.ES2015,
emitDecoratorMetadata: true,
experimentalDecorators: true
});
});
}
+1 -1
View File
@@ -425,7 +425,7 @@ export = C;
readFile: notImplemented
};
const program = createProgram(rootFiles, options, host);
const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics().concat(program.getOptionsDiagnostics()));
const diagnostics = sortAndDeduplicateDiagnostics([...program.getSemanticDiagnostics(), ...program.getOptionsDiagnostics()]);
assert.equal(diagnostics.length, diagnosticCodes.length, `Incorrect number of expected diagnostics, expected ${diagnosticCodes.length}, got '${Harness.Compiler.minimalDiagnosticsToString(diagnostics)}'`);
for (let i = 0; i < diagnosticCodes.length; i++) {
assert.equal(diagnostics[i].code, diagnosticCodes[i], `Expected diagnostic code ${diagnosticCodes[i]}, got '${diagnostics[i].code}': '${diagnostics[i].messageText}'`);
+5 -5
View File
@@ -48,18 +48,18 @@ namespace ts {
const program = createProgram(["./nonexistent.ts"], options, testCompilerHost);
const missing = program.getMissingFilePaths();
assert.isDefined(missing);
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts"]); // Absolute path
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts" as Path]); // Absolute path
});
it("handles multiple missing root files", () => {
const program = createProgram(["./nonexistent0.ts", "./nonexistent1.ts"], options, testCompilerHost);
const missing = program.getMissingFilePaths().sort();
const missing = program.getMissingFilePaths().slice().sort();
assert.deepEqual(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]);
});
it("handles a mix of present and missing root files", () => {
const program = createProgram(["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], options, testCompilerHost);
const missing = program.getMissingFilePaths().sort();
const missing = program.getMissingFilePaths().slice().sort();
assert.deepEqual(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]);
});
@@ -67,7 +67,7 @@ namespace ts {
const program = createProgram(["./nonexistent.ts", "./nonexistent.ts"], options, testCompilerHost);
const missing = program.getMissingFilePaths();
assert.isDefined(missing);
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts"]);
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts" as Path]);
});
it("normalizes file paths", () => {
@@ -81,7 +81,7 @@ namespace ts {
it("handles missing triple slash references", () => {
const program = createProgram([referenceFileRelativePath], options, testCompilerHost);
const missing = program.getMissingFilePaths().sort();
const missing = program.getMissingFilePaths().slice().sort();
assert.isDefined(missing);
assert.deepEqual(missing, [
// From absolute reference
@@ -21,7 +21,7 @@ namespace ts {
}
interface ProgramWithSourceTexts extends Program {
sourceTexts?: NamedSourceText[];
sourceTexts?: ReadonlyArray<NamedSourceText>;
host: TestCompilerHost;
}
@@ -106,7 +106,7 @@ namespace ts {
return file;
}
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
function createTestCompilerHost(texts: ReadonlyArray<NamedSourceText>, target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
const files = arrayToMap(texts, t => t.name, t => {
if (oldProgram) {
let oldFile = <SourceFileWithText>oldProgram.getSourceFile(t.name);
@@ -162,7 +162,7 @@ namespace ts {
return program;
}
function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: string[], options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
if (!newTexts) {
newTexts = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
}
+3 -3
View File
@@ -5,7 +5,7 @@
namespace ts.server {
export function shouldEmitFile(scriptInfo: ScriptInfo) {
return !scriptInfo.hasMixedContent;
return !scriptInfo.hasMixedContent && !scriptInfo.isDynamic;
}
/**
@@ -188,7 +188,7 @@ namespace ts.server {
*/
getFilesAffectedBy(scriptInfo: ScriptInfo): string[] {
const info = this.getOrCreateFileInfo(scriptInfo.path);
const singleFileResult = scriptInfo.hasMixedContent ? [] : [scriptInfo.fileName];
const singleFileResult = scriptInfo.hasMixedContent || scriptInfo.isDynamic ? [] : [scriptInfo.fileName];
if (info.updateShapeSignature()) {
const options = this.project.getCompilerOptions();
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
@@ -303,7 +303,7 @@ namespace ts.server {
getFilesAffectedBy(scriptInfo: ScriptInfo): string[] {
this.ensureProjectDependencyGraphUpToDate();
const singleFileResult = scriptInfo.hasMixedContent ? [] : [scriptInfo.fileName];
const singleFileResult = scriptInfo.hasMixedContent || scriptInfo.isDynamic ? [] : [scriptInfo.fileName];
const fileInfo = this.getFileInfo(scriptInfo.path);
if (!fileInfo || !fileInfo.updateShapeSignature()) {
return singleFileResult;
+17 -11
View File
@@ -239,18 +239,21 @@ namespace ts.server {
getFileName(f: T): string;
getScriptKind(f: T): ScriptKind;
hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[]): boolean;
isDynamicFile(f: T): boolean;
}
const fileNamePropertyReader: FilePropertyReader<string> = {
getFileName: x => x,
getScriptKind: _ => undefined,
hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)),
isDynamicFile: x => x[0] === "^",
};
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
getFileName: x => x.fileName,
getScriptKind: x => tryConvertScriptKindName(x.scriptKind),
hasMixedContent: x => x.hasMixedContent
hasMixedContent: x => x.hasMixedContent,
isDynamicFile: x => x.fileName[0] === "^",
};
function findProjectByName<T extends Project>(projectName: string, projects: T[]): T {
@@ -1210,15 +1213,16 @@ namespace ts.server {
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader<T>, clientFileName: string, typeAcquisition: TypeAcquisition, configFileErrors: ReadonlyArray<Diagnostic>): void {
let errors: Diagnostic[];
for (const f of files) {
const rootFilename = propertyReader.getFileName(f);
const rootFileName = propertyReader.getFileName(f);
const scriptKind = propertyReader.getScriptKind(f);
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
if (this.host.fileExists(rootFilename)) {
const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFilename), /*openedByClient*/ clientFileName === rootFilename, /*fileContent*/ undefined, scriptKind, hasMixedContent);
const isDynamicFile = propertyReader.isDynamicFile(f);
if (isDynamicFile || this.host.fileExists(rootFileName)) {
const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFileName), /*openedByClient*/ clientFileName === rootFileName, /*fileContent*/ undefined, scriptKind, hasMixedContent, isDynamicFile);
project.addRoot(info);
}
else {
(errors || (errors = [])).push(createFileNotFoundDiagnostic(rootFilename));
(errors || (errors = [])).push(createFileNotFoundDiagnostic(rootFileName));
}
}
project.setProjectErrors(concatenate(configFileErrors, errors));
@@ -1248,7 +1252,8 @@ namespace ts.server {
let rootFilesChanged = false;
for (const f of newUncheckedFiles) {
const newRootFile = propertyReader.getFileName(f);
if (!this.host.fileExists(newRootFile)) {
const isDynamic = propertyReader.isDynamicFile(f);
if (!isDynamic && !this.host.fileExists(newRootFile)) {
(projectErrors || (projectErrors = [])).push(createFileNotFoundDiagnostic(newRootFile));
continue;
}
@@ -1259,7 +1264,7 @@ namespace ts.server {
if (!scriptInfo) {
const scriptKind = propertyReader.getScriptKind(f);
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent);
scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, isDynamic);
}
}
newRootScriptInfos.push(scriptInfo);
@@ -1443,17 +1448,17 @@ namespace ts.server {
watchClosedScriptInfo(info: ScriptInfo) {
// do not watch files with mixed content - server doesn't know how to interpret it
if (!info.hasMixedContent) {
if (!info.hasMixedContent && !info.isDynamic) {
const { fileName } = info;
info.setWatcher(this.host.watchFile(fileName, _ => this.onSourceFileChanged(fileName)));
}
}
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean) {
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, isDynamic?: boolean) {
let info = this.getScriptInfoForNormalizedPath(fileName);
if (!info) {
if (openedByClient || this.host.fileExists(fileName)) {
info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent);
if (openedByClient || isDynamic || this.host.fileExists(fileName)) {
info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent, isDynamic);
this.filenameToScriptInfo.set(info.path, info);
@@ -1463,6 +1468,7 @@ namespace ts.server {
fileContent = this.host.readFile(fileName) || "";
}
}
else {
this.watchClosedScriptInfo(info);
}
+6 -5
View File
@@ -156,11 +156,12 @@ namespace ts.server {
private readonly host: ServerHost,
readonly fileName: NormalizedPath,
readonly scriptKind: ScriptKind,
public hasMixedContent = false) {
public hasMixedContent = false,
public isDynamic = false) {
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
this.textStorage = new TextStorage(host, fileName);
if (hasMixedContent) {
if (hasMixedContent || isDynamic) {
this.textStorage.reload("");
}
this.scriptKind = scriptKind
@@ -180,7 +181,7 @@ namespace ts.server {
public close() {
this.isOpen = false;
this.textStorage.useText(this.hasMixedContent ? "" : undefined);
this.textStorage.useText(this.hasMixedContent || this.isDynamic ? "" : undefined);
this.markContainingProjectsAsDirty();
}
@@ -307,7 +308,7 @@ namespace ts.server {
}
reloadFromFile(tempFileName?: NormalizedPath) {
if (this.hasMixedContent) {
if (this.hasMixedContent || this.isDynamic) {
this.reload("");
}
else {
@@ -354,4 +355,4 @@ namespace ts.server {
return this.scriptKind === ScriptKind.JS || this.scriptKind === ScriptKind.JSX;
}
}
}
}
+1 -1
View File
@@ -425,7 +425,7 @@ namespace ts.server {
private semanticCheck(file: NormalizedPath, project: Project) {
try {
let diags: Diagnostic[] = [];
let diags: ReadonlyArray<Diagnostic> = emptyArray;
if (!isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) {
diags = project.getLanguageService().getSemanticDiagnostics(file);
}
+2 -2
View File
@@ -95,7 +95,7 @@ namespace ts.server {
};
}
export function mergeMapLikes(target: MapLike<any>, source: MapLike <any>): void {
export function mergeMapLikes(target: MapLike<any>, source: MapLike<any>): void {
for (const key in source) {
if (hasProperty(source, key)) {
target[key] = source[key];
@@ -299,4 +299,4 @@ namespace ts.server {
deleted(oldItems[oldIndex++]);
}
}
}
}
+14 -14
View File
@@ -41,7 +41,7 @@ namespace ts.FindAllReferences {
readonly implementations?: boolean;
}
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position);
if (!referencedSymbols || !referencedSymbols.length) {
@@ -60,7 +60,7 @@ namespace ts.FindAllReferences {
return out;
}
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] {
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] {
// A node in a JSDoc comment can't have an implementation anyway.
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false);
const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node);
@@ -68,7 +68,7 @@ namespace ts.FindAllReferences {
return map(referenceEntries, entry => toImplementationLocation(entry, checker));
}
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): Entry[] | undefined {
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node): Entry[] | undefined {
if (node.kind === SyntaxKind.SourceFile) {
return undefined;
}
@@ -93,16 +93,16 @@ namespace ts.FindAllReferences {
}
}
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): ReferenceEntry[] | undefined {
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number, options?: Options): ReferenceEntry[] | undefined {
const x = flattenEntries(findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position, options));
return map(x, toReferenceEntry);
}
export function getReferenceEntriesForNode(node: Node, program: Program, sourceFiles: SourceFile[], cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
export function getReferenceEntriesForNode(node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options));
}
function findAllReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
function findAllReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
return Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options);
}
@@ -264,7 +264,7 @@ namespace ts.FindAllReferences {
/* @internal */
namespace ts.FindAllReferences.Core {
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
export function getReferencedSymbolsForNode(node: Node, program: Program, sourceFiles: SourceFile[], cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
export function getReferencedSymbolsForNode(node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
if (node.kind === ts.SyntaxKind.SourceFile) {
return undefined;
}
@@ -313,7 +313,7 @@ namespace ts.FindAllReferences.Core {
}
}
function getReferencedSymbolsForModule(program: Program, symbol: Symbol, sourceFiles: SourceFile[]): SymbolAndEntries[] {
function getReferencedSymbolsForModule(program: Program, symbol: Symbol, sourceFiles: ReadonlyArray<SourceFile>): SymbolAndEntries[] {
Debug.assert(!!symbol.valueDeclaration);
const references = findModuleReferences(program, sourceFiles, symbol).map<Entry>(reference => {
@@ -349,7 +349,7 @@ namespace ts.FindAllReferences.Core {
}
/** getReferencedSymbols for special node kinds. */
function getReferencedSymbolsSpecial(node: Node, sourceFiles: SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
function getReferencedSymbolsSpecial(node: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
if (isTypeKeyword(node.kind)) {
return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
}
@@ -380,7 +380,7 @@ namespace ts.FindAllReferences.Core {
}
/** Core find-all-references algorithm for a normal symbol. */
function getReferencedSymbolsForSymbol(symbol: Symbol, node: Node, sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
function getReferencedSymbolsForSymbol(symbol: Symbol, node: Node, sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
symbol = skipPastExportOrImportSpecifier(symbol, node, checker);
// Compute the meaning from the location and the symbol it references
@@ -474,7 +474,7 @@ namespace ts.FindAllReferences.Core {
readonly markSeenReExportRHS = nodeSeenTracker();
constructor(
readonly sourceFiles: SourceFile[],
readonly sourceFiles: ReadonlyArray<SourceFile>,
/** True if we're searching for constructor references. */
readonly isForConstructor: boolean,
readonly checker: TypeChecker,
@@ -759,7 +759,7 @@ namespace ts.FindAllReferences.Core {
}
}
function getAllReferencesForKeyword(sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] {
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] {
const references: NodeEntry[] = [];
for (const sourceFile of sourceFiles) {
cancellationToken.throwIfCancellationRequested();
@@ -1259,7 +1259,7 @@ namespace ts.FindAllReferences.Core {
return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol, node: superKeyword }, references }];
}
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] {
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] {
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
// Whether 'this' occurs in a static context within a class.
@@ -1355,7 +1355,7 @@ namespace ts.FindAllReferences.Core {
}
}
function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] {
function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] {
const references: NodeEntry[] = [];
for (const sourceFile of sourceFiles) {
+1 -1
View File
@@ -279,7 +279,7 @@ namespace ts.GoToDefinition {
return createDefinitionInfo(decl, symbolKind, symbolName, containerName);
}
function findReferenceInPosition(refs: FileReference[], pos: number): FileReference {
function findReferenceInPosition(refs: ReadonlyArray<FileReference>, pos: number): FileReference {
for (const ref of refs) {
if (ref.pos <= pos && pos <= ref.end) {
return ref;
+7 -7
View File
@@ -7,12 +7,12 @@ namespace ts.FindAllReferences {
/** For rename imports/exports `{ foo as bar }`, `foo` is not a local, so it may be added as a reference immediately without further searching. */
singleReferences: Identifier[];
/** List of source files that may (or may not) use the symbol via a namespace. (For UMD modules this is every file.) */
indirectUsers: SourceFile[];
indirectUsers: ReadonlyArray<SourceFile>;
}
export type ImportTracker = (exportSymbol: Symbol, exportInfo: ExportInfo, isForRename: boolean) => ImportsResult;
/** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */
export function createImportTracker(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken): ImportTracker {
export function createImportTracker(sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken): ImportTracker {
const allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken);
return (exportSymbol, exportInfo, isForRename) => {
const { directImports, indirectUsers } = getImportersForExport(sourceFiles, allDirectImports, exportInfo, checker, cancellationToken);
@@ -38,12 +38,12 @@ namespace ts.FindAllReferences {
/** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */
function getImportersForExport(
sourceFiles: SourceFile[],
sourceFiles: ReadonlyArray<SourceFile>,
allDirectImports: Map<ImporterOrCallExpression[]>,
{ exportingModuleSymbol, exportKind }: ExportInfo,
checker: TypeChecker,
cancellationToken: CancellationToken
): { directImports: Importer[], indirectUsers: SourceFile[] } {
): { directImports: Importer[], indirectUsers: ReadonlyArray<SourceFile> } {
const markSeenDirectImport = nodeSeenTracker<ImporterOrCallExpression>();
const markSeenIndirectUser = nodeSeenTracker<SourceFileLike>();
const directImports: Importer[] = [];
@@ -54,7 +54,7 @@ namespace ts.FindAllReferences {
return { directImports, indirectUsers: getIndirectUsers() };
function getIndirectUsers(): SourceFile[] {
function getIndirectUsers(): ReadonlyArray<SourceFile> {
if (isAvailableThroughGlobal) {
// It has `export as namespace`, so anything could potentially use it.
return sourceFiles;
@@ -313,7 +313,7 @@ namespace ts.FindAllReferences {
| { kind: "import", literal: StringLiteral }
/** <reference path> or <reference types> */
| { kind: "reference", referencingFile: SourceFile, ref: FileReference };
export function findModuleReferences(program: Program, sourceFiles: SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] {
export function findModuleReferences(program: Program, sourceFiles: ReadonlyArray<SourceFile>, searchModuleSymbol: Symbol): ModuleReference[] {
const refs: ModuleReference[] = [];
const checker = program.getTypeChecker();
for (const referencingFile of sourceFiles) {
@@ -343,7 +343,7 @@ namespace ts.FindAllReferences {
}
/** Returns a map from a module symbol Id to all import statements that directly reference the module. */
function getDirectImportsMap(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken): Map<ImporterOrCallExpression[]> {
function getDirectImportsMap(sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken): Map<ImporterOrCallExpression[]> {
const map = createMap<ImporterOrCallExpression[]>();
for (const sourceFile of sourceFiles) {
+1 -1
View File
@@ -2,7 +2,7 @@
namespace ts.NavigateTo {
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
export function getNavigateToItems(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[] {
export function getNavigateToItems(sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[] {
const patternMatcher = createPatternMatcher(searchValue);
let rawItems: RawNavigateToItem[] = [];
+25 -22
View File
@@ -231,18 +231,7 @@ namespace ts.refactor.extractMethod {
if (errors) {
return { errors };
}
// If our selection is the expression in an ExpressionStatement, expand
// the selection to include the enclosing Statement (this stops us
// from trying to care about the return value of the extracted function
// and eliminates double semicolon insertion in certain scenarios)
const range = isStatement(start)
? [start]
: start.parent && start.parent.kind === SyntaxKind.ExpressionStatement
? [start.parent as Statement]
: start as Expression;
return { targetRange: { range, facts: rangeFacts, declarations } };
return { targetRange: { range: getStatementOrExpressionRange(start), facts: rangeFacts, declarations } };
}
function createErrorResult(sourceFile: SourceFile, start: number, length: number, message: DiagnosticMessage): RangeToExtract {
@@ -289,7 +278,7 @@ namespace ts.refactor.extractMethod {
Continue = 1 << 1,
Return = 1 << 2
}
if (!isStatement(nodeToCheck) && !(isExpression(nodeToCheck) && isExtractableExpression(nodeToCheck))) {
if (!isStatement(nodeToCheck) && !(isPartOfExpression(nodeToCheck) && isExtractableExpression(nodeToCheck))) {
return [createDiagnosticForNode(nodeToCheck, Messages.StatementOrExpressionExpected)];
}
@@ -459,6 +448,20 @@ namespace ts.refactor.extractMethod {
}
}
function getStatementOrExpressionRange(node: Node): Statement[] | Expression {
if (isStatement(node)) {
return [node];
}
else if (isPartOfExpression(node)) {
// If our selection is the expression in an ExpressionStatement, expand
// the selection to include the enclosing Statement (this stops us
// from trying to care about the return value of the extracted function
// and eliminates double semicolon insertion in certain scenarios)
return isExpressionStatement(node.parent) ? [node.parent] : node as Expression;
}
return undefined;
}
function isValidExtractionTarget(node: Node): node is Scope {
// Note that we don't use isFunctionLike because we don't want to put the extracted closure *inside* a method
return (node.kind === SyntaxKind.FunctionDeclaration) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node);
@@ -560,32 +563,32 @@ namespace ts.refactor.extractMethod {
return "constructor";
case SyntaxKind.FunctionExpression:
return scope.name
? `function expression ${scope.name.getText()}`
? `function expression ${scope.name.text}`
: "anonymous function expression";
case SyntaxKind.FunctionDeclaration:
return `function ${scope.name.getText()}`;
return `function '${scope.name.text}'`;
case SyntaxKind.ArrowFunction:
return "arrow function";
case SyntaxKind.MethodDeclaration:
return `method ${scope.name.getText()}`;
return `method '${scope.name.getText()}`;
case SyntaxKind.GetAccessor:
return `get ${scope.name.getText()}`;
return `'get ${scope.name.getText()}'`;
case SyntaxKind.SetAccessor:
return `set ${scope.name.getText()}`;
return `'set ${scope.name.getText()}'`;
}
}
else if (isModuleBlock(scope)) {
return `namespace ${scope.parent.name.getText()}`;
return `namespace '${scope.parent.name.getText()}'`;
}
else if (isClassLike(scope)) {
return scope.kind === SyntaxKind.ClassDeclaration
? `class ${scope.name.text}`
? `class '${scope.name.text}'`
: scope.name.text
? `class expression ${scope.name.text}`
? `class expression '${scope.name.text}'`
: "anonymous class expression";
}
else if (isSourceFile(scope)) {
return `file '${scope.fileName}'`;
return scope.externalModuleIndicator ? "module scope" : "global scope";
}
else {
return "unknown";
+7 -8
View File
@@ -495,7 +495,7 @@ namespace ts {
public path: Path;
public text: string;
public scriptSnapshot: IScriptSnapshot;
public lineMap: number[];
public lineMap: ReadonlyArray<number>;
public statements: NodeArray<Statement>;
public endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
@@ -545,7 +545,7 @@ namespace ts {
return ts.getLineAndCharacterOfPosition(this, position);
}
public getLineStarts(): number[] {
public getLineStarts(): ReadonlyArray<number> {
return getLineStarts(this);
}
@@ -1336,10 +1336,10 @@ namespace ts {
}
/// Diagnostics
function getSyntacticDiagnostics(fileName: string) {
function getSyntacticDiagnostics(fileName: string): Diagnostic[] {
synchronizeHostData();
return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken);
return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice();
}
/**
@@ -1356,18 +1356,17 @@ namespace ts {
const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
if (!program.getCompilerOptions().declaration) {
return semanticDiagnostics;
return semanticDiagnostics.slice();
}
// If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken);
return concatenate(semanticDiagnostics, declarationDiagnostics);
return [...semanticDiagnostics, ...declarationDiagnostics];
}
function getCompilerOptionsDiagnostics() {
synchronizeHostData();
return program.getOptionsDiagnostics(cancellationToken).concat(
program.getGlobalDiagnostics(cancellationToken));
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
}
function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
+2 -2
View File
@@ -568,7 +568,7 @@ namespace ts {
}
}
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; code: number; }[] {
export function realizeDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, newLine: string): { message: string; start: number; length: number; category: string; code: number; }[] {
return diagnostics.map(d => realizeDiagnostic(d, newLine));
}
@@ -641,7 +641,7 @@ namespace ts {
});
}
private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[] {
private realizeDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): { message: string; start: number; length: number; category: string; }[] {
const newLine = getNewLineOrDefaultFromHost(this.host);
return ts.realizeDiagnostics(diagnostics, newLine);
}
+1 -1
View File
@@ -68,7 +68,7 @@ namespace ts {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineEndOfPosition(pos: number): number;
getLineStarts(): number[];
getLineStarts(): ReadonlyArray<number>;
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
}
@@ -0,0 +1,21 @@
//// [asyncArrowInClassES5.ts]
// https://github.com/Microsoft/TypeScript/issues/16924
// Should capture `this`
class Test {
static member = async (x: string) => { };
}
//// [asyncArrowInClassES5.js]
// https://github.com/Microsoft/TypeScript/issues/16924
// Should capture `this`
var _this = this;
var Test = /** @class */ (function () {
function Test() {
}
Test.member = function (x) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/];
}); }); };
return Test;
}());
@@ -0,0 +1,12 @@
=== tests/cases/compiler/asyncArrowInClassES5.ts ===
// https://github.com/Microsoft/TypeScript/issues/16924
// Should capture `this`
class Test {
>Test : Symbol(Test, Decl(asyncArrowInClassES5.ts, 0, 0))
static member = async (x: string) => { };
>member : Symbol(Test.member, Decl(asyncArrowInClassES5.ts, 3, 12))
>x : Symbol(x, Decl(asyncArrowInClassES5.ts, 4, 27))
}
@@ -0,0 +1,13 @@
=== tests/cases/compiler/asyncArrowInClassES5.ts ===
// https://github.com/Microsoft/TypeScript/issues/16924
// Should capture `this`
class Test {
>Test : Test
static member = async (x: string) => { };
>member : (x: string) => Promise<void>
>async (x: string) => { } : (x: string) => Promise<void>
>x : string
}
@@ -0,0 +1,8 @@
//// [computerPropertiesInES5ShouldBeTransformed.ts]
const b = ({ [`key`]: renamed }) => renamed;
//// [computerPropertiesInES5ShouldBeTransformed.js]
var b = function (_a) {
var _b = "key", renamed = _a[_b];
return renamed;
};
@@ -0,0 +1,6 @@
=== tests/cases/compiler/computerPropertiesInES5ShouldBeTransformed.ts ===
const b = ({ [`key`]: renamed }) => renamed;
>b : Symbol(b, Decl(computerPropertiesInES5ShouldBeTransformed.ts, 0, 5))
>renamed : Symbol(renamed, Decl(computerPropertiesInES5ShouldBeTransformed.ts, 0, 12))
>renamed : Symbol(renamed, Decl(computerPropertiesInES5ShouldBeTransformed.ts, 0, 12))
@@ -0,0 +1,8 @@
=== tests/cases/compiler/computerPropertiesInES5ShouldBeTransformed.ts ===
const b = ({ [`key`]: renamed }) => renamed;
>b : ({ [`key`]: renamed }: {}) => any
>({ [`key`]: renamed }) => renamed : ({ [`key`]: renamed }: {}) => any
>`key` : "key"
>renamed : any
>renamed : any
@@ -0,0 +1,41 @@
=== tests/cases/conformance/salsa/node.d.ts ===
declare function require(id: string): any;
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>id : Symbol(id, Decl(node.d.ts, 0, 25))
declare var module: any, exports: any;
>module : Symbol(module, Decl(node.d.ts, 1, 11))
>exports : Symbol(exports, Decl(node.d.ts, 1, 24))
=== tests/cases/conformance/salsa/index.js ===
const A = require("./other");
>A : Symbol(A, Decl(index.js, 0, 5))
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>"./other" : Symbol("tests/cases/conformance/salsa/other", Decl(other.js, 0, 0))
const a = new A().id;
>a : Symbol(a, Decl(index.js, 1, 5))
>new A().id : Symbol(A.id, Decl(other.js, 0, 14))
>A : Symbol(A, Decl(index.js, 0, 5))
>id : Symbol(A.id, Decl(other.js, 0, 14))
const B = function() { this.id = 1; }
>B : Symbol(B, Decl(index.js, 3, 5))
>id : Symbol(B.id, Decl(index.js, 3, 22))
const b = new B().id;
>b : Symbol(b, Decl(index.js, 4, 5))
>new B().id : Symbol(B.id, Decl(index.js, 3, 22))
>B : Symbol(B, Decl(index.js, 3, 5))
>id : Symbol(B.id, Decl(index.js, 3, 22))
=== tests/cases/conformance/salsa/other.js ===
function A() { this.id = 1; }
>A : Symbol(A, Decl(other.js, 0, 0))
>id : Symbol(A.id, Decl(other.js, 0, 14))
module.exports = A;
>module : Symbol(export=, Decl(other.js, 0, 29))
>exports : Symbol(export=, Decl(other.js, 0, 29))
>A : Symbol(A, Decl(other.js, 0, 0))
@@ -0,0 +1,55 @@
=== tests/cases/conformance/salsa/node.d.ts ===
declare function require(id: string): any;
>require : (id: string) => any
>id : string
declare var module: any, exports: any;
>module : any
>exports : any
=== tests/cases/conformance/salsa/index.js ===
const A = require("./other");
>A : () => void
>require("./other") : () => void
>require : (id: string) => any
>"./other" : "./other"
const a = new A().id;
>a : number
>new A().id : number
>new A() : { id: number; }
>A : () => void
>id : number
const B = function() { this.id = 1; }
>B : () => void
>function() { this.id = 1; } : () => void
>this.id = 1 : 1
>this.id : any
>this : any
>id : any
>1 : 1
const b = new B().id;
>b : number
>new B().id : number
>new B() : { id: number; }
>B : () => void
>id : number
=== tests/cases/conformance/salsa/other.js ===
function A() { this.id = 1; }
>A : () => void
>this.id = 1 : 1
>this.id : any
>this : any
>id : any
>1 : 1
module.exports = A;
>module.exports = A : () => void
>module.exports : any
>module : any
>exports : any
>A : () => void
@@ -0,0 +1,26 @@
// [source.js]
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);
};
var B = /** @class */ (function () {
function B() {
}
return B;
}());
var C = /** @class */ (function () {
function C(b) {
}
C = __decorate([
dec,
__metadata("design:paramtypes", [B])
], C);
return C;
}());
export { C };
"changed";
@@ -0,0 +1,17 @@
//// [declarationQuotedMembers.ts]
export declare const mapped: { [K in 'a-b-c']: number }
export const example = mapped;
//// [declarationQuotedMembers.js]
"use strict";
exports.__esModule = true;
exports.example = exports.mapped;
//// [declarationQuotedMembers.d.ts]
export declare const mapped: {
[K in 'a-b-c']: number;
};
export declare const example: {
"a-b-c": number;
};
@@ -0,0 +1,9 @@
=== tests/cases/compiler/declarationQuotedMembers.ts ===
export declare const mapped: { [K in 'a-b-c']: number }
>mapped : Symbol(mapped, Decl(declarationQuotedMembers.ts, 0, 20))
>K : Symbol(K, Decl(declarationQuotedMembers.ts, 0, 32))
export const example = mapped;
>example : Symbol(example, Decl(declarationQuotedMembers.ts, 1, 12))
>mapped : Symbol(mapped, Decl(declarationQuotedMembers.ts, 0, 20))
@@ -0,0 +1,9 @@
=== tests/cases/compiler/declarationQuotedMembers.ts ===
export declare const mapped: { [K in 'a-b-c']: number }
>mapped : { a-b-c: number; }
>K : K
export const example = mapped;
>example : { a-b-c: number; }
>mapped : { a-b-c: number; }
@@ -17,6 +17,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
};
var M;
(function (M) {
var _this = this;
var C = /** @class */ (function () {
function C() {
}
@@ -28,6 +28,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
};
var M;
(function (M) {
var _this = this;
var S = /** @class */ (function () {
function S() {
}
@@ -0,0 +1,8 @@
tests/cases/compiler/exportClassWithoutName.ts(1,1): error TS1211: A class declaration without the 'default' modifier must have a name.
==== tests/cases/compiler/exportClassWithoutName.ts (1 errors) ====
export class {
~~~~~~
!!! error TS1211: A class declaration without the 'default' modifier must have a name.
}
@@ -0,0 +1,10 @@
//// [exportClassWithoutName.ts]
export class {
}
//// [exportClassWithoutName.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class default_1 {
}
exports.default_1 = default_1;
@@ -0,0 +1,19 @@
//// [exportEqualsClassNoRedeclarationError.ts]
class SomeClass {
static get someProp(): number {
return 0;
}
static set someProp(value: number) {}
}
export = SomeClass;
//// [exportEqualsClassNoRedeclarationError.js]
"use strict";
class SomeClass {
static get someProp() {
return 0;
}
static set someProp(value) { }
}
module.exports = SomeClass;
@@ -0,0 +1,17 @@
=== tests/cases/compiler/exportEqualsClassNoRedeclarationError.ts ===
class SomeClass {
>SomeClass : Symbol(SomeClass, Decl(exportEqualsClassNoRedeclarationError.ts, 0, 0))
static get someProp(): number {
>someProp : Symbol(SomeClass.someProp, Decl(exportEqualsClassNoRedeclarationError.ts, 0, 17), Decl(exportEqualsClassNoRedeclarationError.ts, 3, 5))
return 0;
}
static set someProp(value: number) {}
>someProp : Symbol(SomeClass.someProp, Decl(exportEqualsClassNoRedeclarationError.ts, 0, 17), Decl(exportEqualsClassNoRedeclarationError.ts, 3, 5))
>value : Symbol(value, Decl(exportEqualsClassNoRedeclarationError.ts, 5, 24))
}
export = SomeClass;
>SomeClass : Symbol(SomeClass, Decl(exportEqualsClassNoRedeclarationError.ts, 0, 0))
@@ -0,0 +1,18 @@
=== tests/cases/compiler/exportEqualsClassNoRedeclarationError.ts ===
class SomeClass {
>SomeClass : SomeClass
static get someProp(): number {
>someProp : number
return 0;
>0 : 0
}
static set someProp(value: number) {}
>someProp : number
>value : number
}
export = SomeClass;
>SomeClass : SomeClass
@@ -0,0 +1,21 @@
tests/cases/compiler/exportEqualsClassRedeclarationError.ts(2,16): error TS2300: Duplicate identifier 'someProp'.
tests/cases/compiler/exportEqualsClassRedeclarationError.ts(6,16): error TS2300: Duplicate identifier 'someProp'.
tests/cases/compiler/exportEqualsClassRedeclarationError.ts(7,16): error TS2300: Duplicate identifier 'someProp'.
==== tests/cases/compiler/exportEqualsClassRedeclarationError.ts (3 errors) ====
class SomeClass {
static get someProp(): number {
~~~~~~~~
!!! error TS2300: Duplicate identifier 'someProp'.
return 0;
}
static set someProp(value: number) {}
~~~~~~~~
!!! error TS2300: Duplicate identifier 'someProp'.
static set someProp(value: number) {}
~~~~~~~~
!!! error TS2300: Duplicate identifier 'someProp'.
}
export = SomeClass;
@@ -0,0 +1,21 @@
//// [exportEqualsClassRedeclarationError.ts]
class SomeClass {
static get someProp(): number {
return 0;
}
static set someProp(value: number) {}
static set someProp(value: number) {}
}
export = SomeClass;
//// [exportEqualsClassRedeclarationError.js]
"use strict";
class SomeClass {
static get someProp() {
return 0;
}
static set someProp(value) { }
static set someProp(value) { }
}
module.exports = SomeClass;
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
function foo() {
@@ -55,7 +55,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
function foo() {
@@ -76,7 +76,7 @@ namespace A {
return a;
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
function foo() {
@@ -9,7 +9,7 @@ namespace A {
}
}
}
==SCOPE::class C==
==SCOPE::class 'C'==
namespace A {
export interface I { x: number };
class C {
@@ -24,7 +24,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
export interface I { x: number };
class C {
@@ -39,7 +39,7 @@ namespace A {
return a1.x + 10;
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
export interface I { x: number };
class C {
@@ -11,7 +11,7 @@ namespace A {
}
}
}
==SCOPE::class C==
==SCOPE::class 'C'==
namespace A {
let y = 1;
class C {
@@ -30,7 +30,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let y = 1;
class C {
@@ -49,7 +49,7 @@ namespace A {
return { __return: a1.x + 10, z };
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let y = 1;
class C {
@@ -13,7 +13,7 @@ namespace A {
}
}
}
==SCOPE::class C==
==SCOPE::class 'C'==
namespace A {
let y = 1;
class C {
@@ -12,7 +12,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
function foo() {
@@ -30,7 +30,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
function foo() {
@@ -48,7 +48,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
function foo() {
@@ -66,7 +66,7 @@ namespace A {
return foo();
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
function foo() {
@@ -11,7 +11,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
function foo() {
}
@@ -28,7 +28,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
function foo() {
}
@@ -45,7 +45,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
function foo() {
}
@@ -62,7 +62,7 @@ namespace A {
return foo();
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
function foo() {
}
@@ -13,7 +13,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
function foo() {
}
@@ -32,7 +32,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
function foo() {
}
@@ -51,7 +51,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
function foo() {
}
@@ -70,7 +70,7 @@ namespace A {
return foo();
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
function foo() {
}
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
export function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export function foo() {
@@ -55,7 +55,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export function foo() {
@@ -76,7 +76,7 @@ namespace A {
return a;
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
export function foo() {
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
export function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export function foo() {
@@ -56,7 +56,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export function foo() {
@@ -78,7 +78,7 @@ namespace A {
return { __return: foo(), a };
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
export function foo() {
@@ -16,7 +16,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
export namespace C {
@@ -38,7 +38,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export namespace C {
@@ -62,7 +62,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export namespace C {
@@ -86,7 +86,7 @@ namespace A {
return { __return: C.foo(), a };
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
export namespace C {
@@ -8,7 +8,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
let x = 1;
namespace B {
@@ -22,7 +22,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
let x = 1;
namespace B {
@@ -36,7 +36,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
let x = 1;
namespace B {
@@ -50,7 +50,7 @@ namespace A {
return 1 + a1 + x;
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
let x = 1;
namespace B {
@@ -8,7 +8,7 @@ namespace A {
}
}
}
==SCOPE::function a==
==SCOPE::function 'a'==
namespace A {
export interface I { x: number };
namespace B {
@@ -22,7 +22,7 @@ namespace A {
}
}
}
==SCOPE::namespace B==
==SCOPE::namespace 'B'==
namespace A {
export interface I { x: number };
namespace B {
@@ -36,7 +36,7 @@ namespace A {
}
}
}
==SCOPE::namespace A==
==SCOPE::namespace 'A'==
namespace A {
export interface I { x: number };
namespace B {
@@ -50,7 +50,7 @@ namespace A {
return a1.x + 10;
}
}
==SCOPE::file '/a.ts'==
==SCOPE::global scope==
namespace A {
export interface I { x: number };
namespace B {
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/dynamicImport/importCallExpressionInExportEqualsAMD.ts] ////
//// [something.ts]
export = 42;
//// [index.ts]
export = async function() {
const something = await import("./something");
};
//// [something.js]
define(["require", "exports"], function (require, exports) {
"use strict";
return 42;
});
//// [index.js]
define(["require", "exports"], function (require, exports) {
"use strict";
return async function () {
const something = await new Promise(function (resolve_1, reject_1) { require(["./something"], resolve_1, reject_1); });
};
});
@@ -0,0 +1,10 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
const something = await import("./something");
>something : Symbol(something, Decl(index.ts, 1, 9))
>"./something" : Symbol("tests/cases/conformance/dynamicImport/something", Decl(something.ts, 0, 0))
};
@@ -0,0 +1,14 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
>async function() { const something = await import("./something");} : () => Promise<void>
const something = await import("./something");
>something : 42
>await import("./something") : 42
>import("./something") : Promise<42>
>"./something" : "./something"
};
@@ -0,0 +1,18 @@
//// [tests/cases/conformance/dynamicImport/importCallExpressionInExportEqualsCJS.ts] ////
//// [something.ts]
export = 42;
//// [index.ts]
export = async function() {
const something = await import("./something");
};
//// [something.js]
"use strict";
module.exports = 42;
//// [index.js]
"use strict";
module.exports = async function () {
const something = await Promise.resolve().then(function () { return require("./something"); });
};
@@ -0,0 +1,10 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
const something = await import("./something");
>something : Symbol(something, Decl(index.ts, 1, 9))
>"./something" : Symbol("tests/cases/conformance/dynamicImport/something", Decl(something.ts, 0, 0))
};
@@ -0,0 +1,14 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
>async function() { const something = await import("./something");} : () => Promise<void>
const something = await import("./something");
>something : 42
>await import("./something") : 42
>import("./something") : Promise<42>
>"./something" : "./something"
};
@@ -0,0 +1,39 @@
//// [tests/cases/conformance/dynamicImport/importCallExpressionInExportEqualsUMD.ts] ////
//// [something.ts]
export = 42;
//// [index.ts]
export = async function() {
const something = await import("./something");
};
//// [something.js]
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
return 42;
});
//// [index.js]
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
var __syncRequire = typeof module === "object" && typeof module.exports === "object";
return async function () {
const something = await (__syncRequire ? Promise.resolve().then(function () { return require("./something"); }) : new Promise(function (resolve_1, reject_1) { require(["./something"], resolve_1, reject_1); }));
};
});
@@ -0,0 +1,10 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
const something = await import("./something");
>something : Symbol(something, Decl(index.ts, 1, 9))
>"./something" : Symbol("tests/cases/conformance/dynamicImport/something", Decl(something.ts, 0, 0))
};
@@ -0,0 +1,14 @@
=== tests/cases/conformance/dynamicImport/something.ts ===
export = 42;
No type information for this code.
No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts ===
export = async function() {
>async function() { const something = await import("./something");} : () => Promise<void>
const something = await import("./something");
>something : 42
>await import("./something") : 42
>import("./something") : Promise<42>
>"./something" : "./something"
};
@@ -124,6 +124,7 @@ var stringOrNumberOrUndefined = C.inStaticNestedArrowFunction;
//// [output.js]
var _this = this;
var C = /** @class */ (function () {
function C() {
var _this = this;
@@ -69,7 +69,7 @@ function boxify<T>(obj: T): Boxified<T> {
result[k] = box(obj[k]);
>result[k] = box(obj[k]) : Box<T[keyof T]>
>result[k] : Box<T[keyof T]>
>result[k] : Boxified<T>[keyof T]
>result : Boxified<T>
>k : keyof T
>box(obj[k]) : Box<T[keyof T]>
@@ -107,7 +107,7 @@ function unboxify<T>(obj: Boxified<T>): T {
>k : keyof T
>unbox(obj[k]) : T[keyof T]
>unbox : <T>(x: Box<T>) => T
>obj[k] : Box<T[keyof T]>
>obj[k] : Boxified<T>[keyof T]
>obj : Boxified<T>
>k : keyof T
}
@@ -131,7 +131,7 @@ function assignBoxified<T>(obj: Boxified<T>, values: T) {
obj[k].value = values[k];
>obj[k].value = values[k] : T[keyof T]
>obj[k].value : T[keyof T]
>obj[k] : Box<T[keyof T]>
>obj[k] : Boxified<T>[keyof T]
>obj : Boxified<T>
>k : keyof T
>value : T[keyof T]
+12 -12
View File
@@ -27,8 +27,8 @@ function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
>obj : { [P in K]: T; }
let x1 = obj[k1];
>x1 : T
>obj[k1] : T
>x1 : { [P in K]: T; }[K]
>obj[k1] : { [P in K]: T; }[K]
>obj : { [P in K]: T; }
>k1 : K
}
@@ -37,8 +37,8 @@ function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
>obj : { [P in K]: T; }
let x2 = obj[k2];
>x2 : T
>obj[k2] : T
>x2 : { [P in K]: T; }[K]
>obj[k2] : { [P in K]: T; }[K]
>obj : { [P in K]: T; }
>k2 : K
}
@@ -70,8 +70,8 @@ function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
>obj : { [P in keyof T]: T[P]; }
let x1 = obj[k1];
>x1 : T[keyof T]
>obj[k1] : T[keyof T]
>x1 : { [P in keyof T]: T[P]; }[keyof T]
>obj[k1] : { [P in keyof T]: T[P]; }[keyof T]
>obj : { [P in keyof T]: T[P]; }
>k1 : keyof T
}
@@ -80,8 +80,8 @@ function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
>obj : { [P in keyof T]: T[P]; }
let x2 = obj[k2];
>x2 : T[keyof T]
>obj[k2] : T[keyof T]
>x2 : { [P in keyof T]: T[P]; }[keyof T]
>obj[k2] : { [P in keyof T]: T[P]; }[keyof T]
>obj : { [P in keyof T]: T[P]; }
>k2 : keyof T
}
@@ -115,8 +115,8 @@ function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
>obj : { [P in K]: T[P]; }
let x1 = obj[k1];
>x1 : T[K]
>obj[k1] : T[K]
>x1 : { [P in K]: T[P]; }[K]
>obj[k1] : { [P in K]: T[P]; }[K]
>obj : { [P in K]: T[P]; }
>k1 : K
}
@@ -125,8 +125,8 @@ function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
>obj : { [P in K]: T[P]; }
let x2 = obj[k2];
>x2 : T[K]
>obj[k2] : T[K]
>x2 : { [P in K]: T[P]; }[K]
>obj[k2] : { [P in K]: T[P]; }[K]
>obj : { [P in K]: T[P]; }
>k2 : K
}
@@ -2194,7 +2194,7 @@ class Form<T> {
this.childFormFactories[prop](value)
>this.childFormFactories[prop](value) : Form<T[K]>
>this.childFormFactories[prop] : (v: T[K]) => Form<T[K]>
>this.childFormFactories[prop] : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }[K]
>this.childFormFactories : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }
>this : this
>childFormFactories : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }
@@ -0,0 +1,49 @@
tests/cases/compiler/mappedTypeIndexedAccess.ts(18,5): error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
Types of property 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/compiler/mappedTypeIndexedAccess.ts(24,5): error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
Types of property 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
==== tests/cases/compiler/mappedTypeIndexedAccess.ts (2 errors) ====
// Repro from #15756
type Pairs<T> = {
[TKey in keyof T]: {
key: TKey;
value: T[TKey];
};
};
type Pair<T> = Pairs<T>[keyof T];
type FooBar = {
foo: string;
bar: number;
};
// Error expected here
let pair1: Pair<FooBar> = {
~~~~~
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
!!! error TS2322: Types of property 'value' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
key: "foo",
value: 3
};
// Error expected here
let pair2: Pairs<FooBar>[keyof FooBar] = {
~~~~~
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
!!! error TS2322: Types of property 'value' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
key: "foo",
value: 3
};
@@ -0,0 +1,43 @@
//// [mappedTypeIndexedAccess.ts]
// Repro from #15756
type Pairs<T> = {
[TKey in keyof T]: {
key: TKey;
value: T[TKey];
};
};
type Pair<T> = Pairs<T>[keyof T];
type FooBar = {
foo: string;
bar: number;
};
// Error expected here
let pair1: Pair<FooBar> = {
key: "foo",
value: 3
};
// Error expected here
let pair2: Pairs<FooBar>[keyof FooBar] = {
key: "foo",
value: 3
};
//// [mappedTypeIndexedAccess.js]
"use strict";
// Repro from #15756
// Error expected here
var pair1 = {
key: "foo",
value: 3
};
// Error expected here
var pair2 = {
key: "foo",
value: 3
};
@@ -1,76 +1,38 @@
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(11,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[keyof T]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(16,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[K]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(20,5): error TS2536: Type 'keyof U' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(21,5): error TS2322: Type 'T[keyof U]' is not assignable to type 'U[keyof U]'.
Type 'T[string]' is not assignable to type 'U[keyof U]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[keyof U]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(21,12): error TS2536: Type 'keyof U' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(25,5): error TS2536: Type 'K' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(26,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[K]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(26,12): error TS2536: Type 'K' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(30,5): error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[string]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(35,5): error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[string]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(40,5): error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[string]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[keyof T]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(45,5): error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[string]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
Type 'T[string]' is not assignable to type 'U[K] | undefined'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[K]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(30,5): error TS2322: Type 'Partial<T>[keyof T]' is not assignable to type 'T[keyof T]'.
Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(35,5): error TS2322: Type 'Partial<T>[K]' is not assignable to type 'T[K]'.
Type 'T[K] | undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[K]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(40,5): error TS2322: Type 'Partial<U>[keyof T]' is not assignable to type 'T[keyof T]'.
Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(45,5): error TS2322: Type 'Partial<U>[K]' is not assignable to type 'T[K]'.
Type 'U[K] | undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[K]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(51,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(56,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[keyof T]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'Readonly<U>[keyof T]'.
Type 'T' is not assignable to type 'Readonly<U>'.
Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[K]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2322: Type 'T[K]' is not assignable to type 'Readonly<U>[K]'.
Type 'T' is not assignable to type 'Readonly<U>'.
Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(72,5): error TS2322: Type 'Partial<T>' is not assignable to type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(78,5): error TS2322: Type 'Partial<Thing>' is not assignable to type 'Partial<T>'.
@@ -78,11 +40,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(88,5): error TS2
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(127,5): error TS2322: Type 'Partial<U>' is not assignable to type 'Identity<U>'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(143,5): error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof T]: U[P]; }'.
Type 'T[P]' is not assignable to type 'U[P]'.
Type 'T[string]' is not assignable to type 'U[P]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[P]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(148,5): error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof U]: U[P]; }'.
Type 'keyof U' is not assignable to type 'keyof T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(153,5): error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in keyof T]: T[P]; }'.
@@ -93,14 +51,10 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(163,5): error TS
Type 'keyof T' is not assignable to type 'K'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in K]: U[P]; }'.
Type 'T[P]' is not assignable to type 'U[P]'.
Type 'T[string]' is not assignable to type 'U[P]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T[P]' is not assignable to type 'U[string]'.
Type 'T[string]' is not assignable to type 'U[string]'.
Type 'T' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
==== tests/cases/conformance/types/mapped/mappedTypeRelationships.ts (30 errors) ====
==== tests/cases/conformance/types/mapped/mappedTypeRelationships.ts (28 errors) ====
function f1<T>(x: T, k: keyof T) {
return x[k];
}
@@ -114,11 +68,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f4<T, U extends T, K extends keyof T>(x: T, y: U, k: K) {
@@ -126,11 +76,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f5<T, U extends T>(x: T, y: U, k: keyof U) {
@@ -140,11 +86,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof U]' is not assignable to type 'U[keyof U]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof U]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[keyof U]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2536: Type 'keyof U' cannot be used to index type 'T'.
}
@@ -156,11 +98,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2536: Type 'K' cannot be used to index type 'T'.
}
@@ -168,57 +106,37 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
function f10<T>(x: T, y: Partial<T>, k: keyof T) {
x[k] = y[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
!!! error TS2322: Type 'Partial<T>[keyof T]' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
y[k] = x[k];
}
function f11<T, K extends keyof T>(x: T, y: Partial<T>, k: K) {
x[k] = y[k]; // Error
~~~~
!!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
!!! error TS2322: Type 'Partial<T>[K]' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
y[k] = x[k];
}
function f12<T, U extends T>(x: T, y: Partial<U>, k: keyof T) {
x[k] = y[k]; // Error
~~~~
!!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
!!! error TS2322: Type 'Partial<U>[keyof T]' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f13<T, U extends T, K extends keyof T>(x: T, y: Partial<U>, k: K) {
x[k] = y[k]; // Error
~~~~
!!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
!!! error TS2322: Type 'Partial<U>[K]' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f20<T>(x: T, y: Readonly<T>, k: keyof T) {
@@ -239,12 +157,10 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
x[k] = y[k];
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'Readonly<U>[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'Readonly<U>'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
}
@@ -253,12 +169,10 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
x[k] = y[k];
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'Readonly<U>[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'Readonly<U>'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
}
@@ -349,11 +263,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
~
!!! error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof T]: U[P]; }'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f72<T, U extends T>(x: { [P in keyof T]: T[P] }, y: { [P in keyof U]: U[P] }) {
@@ -394,10 +304,6 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
~
!!! error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in K]: U[P]; }'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
+1 -1
View File
@@ -45,7 +45,7 @@ function boxify<T>(obj: T): Boxified<T> {
result[k] = { value: obj[k] };
>result[k] = { value: obj[k] } : { value: T[keyof T]; }
>result[k] : Box<T[keyof T]>
>result[k] : Boxified<T>[keyof T]
>result : Boxified<T>
>k : keyof T
>{ value: obj[k] } : { value: T[keyof T]; }
@@ -0,0 +1,33 @@
tests/cases/compiler/index.ts(4,1): error TS2693: 'B' only refers to a type, but is being used as a value here.
tests/cases/compiler/index.ts(9,10): error TS2304: Cannot find name 'OriginalB'.
==== tests/cases/compiler/b.ts (0 errors) ====
export const zzz = 123;
==== tests/cases/compiler/a.ts (0 errors) ====
import * as B from "./b";
interface B {
x: string;
}
const x: B = { x: "" };
B.zzz;
export { B };
==== tests/cases/compiler/index.ts (2 errors) ====
import { B } from "./a";
const x: B = { x: "" };
B.zzz;
~
!!! error TS2693: 'B' only refers to a type, but is being used as a value here.
import * as OriginalB from "./b";
OriginalB.zzz;
const y: OriginalB = x;
~~~~~~~~~
!!! error TS2304: Cannot find name 'OriginalB'.
@@ -0,0 +1,46 @@
//// [tests/cases/compiler/noCrashOnImportShadowing.ts] ////
//// [b.ts]
export const zzz = 123;
//// [a.ts]
import * as B from "./b";
interface B {
x: string;
}
const x: B = { x: "" };
B.zzz;
export { B };
//// [index.ts]
import { B } from "./a";
const x: B = { x: "" };
B.zzz;
import * as OriginalB from "./b";
OriginalB.zzz;
const y: OriginalB = x;
//// [b.js]
"use strict";
exports.__esModule = true;
exports.zzz = 123;
//// [a.js]
"use strict";
exports.__esModule = true;
var B = require("./b");
var x = { x: "" };
B.zzz;
//// [index.js]
"use strict";
exports.__esModule = true;
var x = { x: "" };
B.zzz;
var OriginalB = require("./b");
OriginalB.zzz;
var y = x;
@@ -0,0 +1,15 @@
//// [shouldNotPrintNullEscapesIntoOctalLiterals.ts]
"use strict";
`\x001`;
`\u00001`;
`\u{00000000}1`;
`\u{000000}1`;
`\u{0}1`;
//// [shouldNotPrintNullEscapesIntoOctalLiterals.js]
"use strict";
"\x001";
"\x001";
"\x001";
"\x001";
"\x001";
@@ -0,0 +1,8 @@
=== tests/cases/compiler/shouldNotPrintNullEscapesIntoOctalLiterals.ts ===
"use strict";
No type information for this code.`\x001`;
No type information for this code.`\u00001`;
No type information for this code.`\u{00000000}1`;
No type information for this code.`\u{000000}1`;
No type information for this code.`\u{0}1`;
No type information for this code.
@@ -0,0 +1,19 @@
=== tests/cases/compiler/shouldNotPrintNullEscapesIntoOctalLiterals.ts ===
"use strict";
>"use strict" : "use strict"
`\x001`;
>`\x001` : "\x001"
`\u00001`;
>`\u00001` : "\x001"
`\u{00000000}1`;
>`\u{00000000}1` : "\x001"
`\u{000000}1`;
>`\u{000000}1` : "\x001"
`\u{0}1`;
>`\u{0}1` : "\x001"
@@ -35,6 +35,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _this = this;
var P = /** @class */ (function () {
function P() {
}
@@ -9,6 +9,7 @@ class Vector {
}
//// [thisInArrowFunctionInStaticInitializer1.js]
var _this = this;
function log(a) { }
var Vector = /** @class */ (function () {
function Vector() {
@@ -10,6 +10,7 @@ class P {
}
//// [thisInConstructorParameter2.js]
var _this = this;
var P = /** @class */ (function () {
function P(z, zz) {
if (z === void 0) { z = this; }
@@ -59,6 +59,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _this = this;
//'this' in static member initializer
var ErrClass1 = /** @class */ (function () {
function ErrClass1() {
@@ -60,6 +60,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _this = this;
//'this' in static member initializer
var ErrClass1 = /** @class */ (function () {
function ErrClass1() {
@@ -21,6 +21,7 @@ class Foo {
}
//// [thisInOuterClassBody.js]
var _this = this;
var Foo = /** @class */ (function () {
function Foo() {
this.x = this;

Some files were not shown because too many files have changed in this diff Show More