Merge branch 'master' into this-type-guards

This commit is contained in:
Wesley Wigham
2015-12-08 17:48:33 -08:00
317 changed files with 4387 additions and 984 deletions
+250 -113
View File
@@ -51,6 +51,7 @@ namespace ts {
const emitResolver = createResolver();
const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
undefinedSymbol.declarations = [];
const argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
const checker: TypeChecker = {
@@ -234,6 +235,10 @@ namespace ts {
ResolvedReturnType
}
const builtinGlobals: SymbolTable = {
[undefinedSymbol.name]: undefinedSymbol
};
initializeTypeChecker();
return checker;
@@ -360,6 +365,24 @@ namespace ts {
}
}
function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) {
for (const id in source) {
if (hasProperty(source, id)) {
if (hasProperty(target, id)) {
// Error on redeclarations
forEach(target[id].declarations, addDeclarationDiagnostic(id, message));
}
else {
target[id] = source[id];
}
}
}
function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) {
return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id));
}
}
function getSymbolLinks(symbol: Symbol): SymbolLinks {
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
const id = getSymbolId(symbol);
@@ -379,6 +402,14 @@ namespace ts {
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
}
/** Is this type one of the apparent types created from the primitive types. */
function isPrimitiveApparentType(type: Type): boolean {
return type === globalStringType ||
type === globalNumberType ||
type === globalBooleanType ||
type === globalESSymbolType;
}
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
if (meaning && hasProperty(symbols, name)) {
const symbol = symbols[name];
@@ -1095,39 +1126,81 @@ namespace ts {
return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
}
function extendExportSymbols(target: SymbolTable, source: SymbolTable) {
interface ExportCollisionTracker {
specifierText: string;
exportsWithDuplicate: ExportDeclaration[];
}
/**
* Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
* Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
*/
function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: Map<ExportCollisionTracker>, exportNode?: ExportDeclaration) {
for (const id in source) {
if (id !== "default" && !hasProperty(target, id)) {
target[id] = source[id];
if (lookupTable && exportNode) {
lookupTable[id] = {
specifierText: getTextOfNode(exportNode.moduleSpecifier)
} as ExportCollisionTracker;
}
}
else if (lookupTable && exportNode && id !== "default" && hasProperty(target, id) && resolveSymbol(target[id]) !== resolveSymbol(source[id])) {
if (!lookupTable[id].exportsWithDuplicate) {
lookupTable[id].exportsWithDuplicate = [exportNode];
}
else {
lookupTable[id].exportsWithDuplicate.push(exportNode);
}
}
}
}
function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
let result: SymbolTable;
const visitedSymbols: Symbol[] = [];
visit(moduleSymbol);
return result || moduleSymbol.exports;
return visit(moduleSymbol) || moduleSymbol.exports;
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
function visit(symbol: Symbol) {
if (symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol)) {
visitedSymbols.push(symbol);
if (symbol !== moduleSymbol) {
if (!result) {
result = cloneSymbolTable(moduleSymbol.exports);
}
extendExportSymbols(result, symbol.exports);
}
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
for (const node of exportStars.declarations) {
visit(resolveExternalModuleName(node, (<ExportDeclaration>node).moduleSpecifier));
}
}
function visit(symbol: Symbol): SymbolTable {
if (!(symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol))) {
return;
}
visitedSymbols.push(symbol);
const symbols = cloneSymbolTable(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
const nestedSymbols: SymbolTable = {};
const lookupTable: Map<ExportCollisionTracker> = {};
for (const node of exportStars.declarations) {
const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier);
const exportedSymbols = visit(resolvedModule);
extendExportSymbols(
nestedSymbols,
exportedSymbols,
lookupTable,
node as ExportDeclaration
);
}
for (const id in lookupTable) {
const { exportsWithDuplicate } = lookupTable[id];
// It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself
if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || hasProperty(symbols, id)) {
continue;
}
for (const node of exportsWithDuplicate) {
diagnostics.add(createDiagnosticForNode(
node,
Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity,
lookupTable[id].specifierText,
id
));
}
}
extendExportSymbols(symbols, nestedSymbols);
}
return symbols;
}
}
@@ -1521,9 +1594,9 @@ namespace ts {
return result;
}
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string {
const writer = getSingleLineStringWriter();
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, kind);
const result = writer.string();
releaseStringWriter(writer);
@@ -1881,7 +1954,7 @@ namespace ts {
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
}
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
@@ -1893,7 +1966,7 @@ namespace ts {
}
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
@@ -1907,15 +1980,12 @@ namespace ts {
writer.writeLine();
writer.increaseIndent();
for (const signature of resolved.callSignatures) {
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
for (const signature of resolved.constructSignatures) {
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
@@ -1956,7 +2026,7 @@ namespace ts {
if (p.flags & SymbolFlags.Optional) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
@@ -2078,7 +2148,12 @@ namespace ts {
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, symbolStack?: Symbol[]) {
if (kind === SignatureKind.Construct) {
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
}
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
// Instantiated signature, write type arguments instead
// This is achieved by passing in the mapper separately
@@ -2952,10 +3027,6 @@ namespace ts {
return type.resolvedBaseConstructorType;
}
function hasClassBaseType(type: InterfaceType): boolean {
return !!forEach(getBaseTypes(type), t => !!(t.symbol.flags & SymbolFlags.Class));
}
function getBaseTypes(type: InterfaceType): ObjectType[] {
const isClass = type.symbol.flags & SymbolFlags.Class;
const isInterface = type.symbol.flags & SymbolFlags.Interface;
@@ -3388,11 +3459,11 @@ namespace ts {
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
if (!hasClassBaseType(classType)) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
@@ -3610,7 +3681,7 @@ namespace ts {
return <ResolvedType>type;
}
// Return properties of an object type or an empty array for other types
/** Return properties of an object type or an empty array for other types */
function getPropertiesOfObjectType(type: Type): Symbol[] {
if (type.flags & TypeFlags.ObjectType) {
return resolveStructuredTypeMembers(<ObjectType>type).properties;
@@ -3618,8 +3689,8 @@ namespace ts {
return emptyArray;
}
// If the given type is an object type and that type has a property by the given name,
// return the symbol for that property.Otherwise return undefined.
/** If the given type is an object type and that type has a property by the given name,
* return the symbol for that property. Otherwise return undefined. */
function getPropertyOfObjectType(type: Type, name: string): Symbol {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -5155,9 +5226,6 @@ namespace ts {
}
return objectTypeRelatedTo(source, source, target, /*reportErrors*/ false);
}
if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
return typeParameterIdenticalTo(<TypeParameter>source, <TypeParameter>target);
}
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
@@ -5288,17 +5356,6 @@ namespace ts {
return result;
}
function typeParameterIdenticalTo(source: TypeParameter, target: TypeParameter): Ternary {
// covers case when both type parameters does not have constraint (both equal to noConstraintType)
if (source.constraint === target.constraint) {
return Ternary.True;
}
if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
return Ternary.False;
}
return isIdenticalTo(source.constraint, target.constraint);
}
// Determine if two object types are related by structure. First, check if the result is already available in the global cache.
// Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
@@ -5524,20 +5581,26 @@ namespace ts {
outer: for (const t of targetSignatures) {
if (!t.hasStringLiterals || target.flags & TypeFlags.FromSignature) {
let localErrors = reportErrors;
const checkedAbstractAssignability = false;
// Only elaborate errors from the first failure
let shouldElaborateErrors = reportErrors;
for (const s of sourceSignatures) {
if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
const related = signatureRelatedTo(s, t, localErrors);
const related = signatureRelatedTo(s, t, shouldElaborateErrors);
if (related) {
result &= related;
errorInfo = saveErrorInfo;
continue outer;
}
// Only report errors from the first failure
localErrors = false;
shouldElaborateErrors = false;
}
}
// don't elaborate the primitive apparent types (like Number)
// because the actual primitives will have already been reported.
if (shouldElaborateErrors && !isPrimitiveApparentType(source)) {
reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
typeToString(source),
signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind));
}
return Ternary.False;
}
}
@@ -5820,26 +5883,19 @@ namespace ts {
if (!(isMatchingSignature(source, target, partialMatch))) {
return Ternary.False;
}
let result = Ternary.True;
if (source.typeParameters && target.typeParameters) {
if (source.typeParameters.length !== target.typeParameters.length) {
return Ternary.False;
}
for (let i = 0, len = source.typeParameters.length; i < len; ++i) {
const related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
if (!related) {
return Ternary.False;
}
result &= related;
}
}
else if (source.typeParameters || target.typeParameters) {
// Check that the two signatures have the same number of type parameters. We might consider
// also checking that any type parameter constraints match, but that would require instantiating
// the constraints with a common set of type arguments to get relatable entities in places where
// type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile,
// particularly as we're comparing erased versions of the signatures below.
if ((source.typeParameters ? source.typeParameters.length : 0) !== (target.typeParameters ? target.typeParameters.length : 0)) {
return Ternary.False;
}
// Spec 1.0 Section 3.8.3 & 3.8.4:
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
source = getErasedSignature(source);
target = getErasedSignature(target);
let result = Ternary.True;
const targetLen = target.parameters.length;
for (let i = 0; i < targetLen; i++) {
const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
@@ -6150,14 +6206,25 @@ namespace ts {
function inferFromTypes(source: Type, target: Type) {
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
// Source and target are both unions or both intersections. To improve the quality of
// inferences we first reduce the types by removing constituents that are identically
// matched by a constituent in the other type. For example, when inferring from
// 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
source = reducedSource;
target = reducedTarget;
// Source and target are both unions or both intersections. First, find each
// target constituent type that has an identically matching source constituent
// type, and for each such target constituent type infer from the type to itself.
// When inferring from a type to itself we effectively find all type parameter
// occurrences within that type and infer themselves as their type arguments.
let matchingTypes: Type[];
for (const t of (<UnionOrIntersectionType>target).types) {
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>source).types)) {
(matchingTypes || (matchingTypes = [])).push(t);
inferFromTypes(t, t);
}
}
// Next, to improve the quality of inferences, reduce the source and target types by
// removing the identically matched constituents. For example, when inferring from
// 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'.
if (matchingTypes) {
source = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>source, matchingTypes);
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
}
}
if (target.flags & TypeFlags.TypeParameter) {
// If target is a type parameter, make an inference, unless the source type contains
@@ -6246,9 +6313,12 @@ namespace ts {
}
else {
source = getApparentType(source);
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (source.flags & TypeFlags.ObjectType && (
target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
target.flags & TypeFlags.Tuple ||
target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference with type arguments, a tuple type,
// the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
@@ -6311,9 +6381,9 @@ namespace ts {
}
}
function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
for (const t of target.types) {
if (isTypeIdenticalTo(source, t)) {
function typeIdenticalToSomeType(type: Type, types: Type[]): boolean {
for (const t of types) {
if (isTypeIdenticalTo(t, type)) {
return true;
}
}
@@ -6321,29 +6391,17 @@ namespace ts {
}
/**
* Return the reduced form of the source type. This type is computed by by removing all source
* constituents that have an identical match in the target type.
* Return a new union or intersection type computed by removing a given set of types
* from a given union or intersection type.
*/
function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
let sourceTypes = source.types;
let sourceIndex = 0;
let modified = false;
while (sourceIndex < sourceTypes.length) {
if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
if (!modified) {
sourceTypes = sourceTypes.slice(0);
modified = true;
}
sourceTypes.splice(sourceIndex, 1);
}
else {
sourceIndex++;
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
const reducedTypes: Type[] = [];
for (const t of type.types) {
if (!typeIdenticalToSomeType(t, typesToRemove)) {
reducedTypes.push(t);
}
}
if (modified) {
return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
}
return source;
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes, /*noSubtypeReduction*/ true) : getIntersectionType(reducedTypes);
}
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
@@ -14248,8 +14306,29 @@ namespace ts {
const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
}
// Checks for export * conflicts
const exports = getExportsOfModule(moduleSymbol);
for (const id in exports) {
if (id === "__export") {
continue;
}
const { declarations, flags } = exports[id];
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. (TS Exceptions: namespaces, function overloads, enums, and interfaces)
if (!(flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) && declarations.length > 1) {
const exportedDeclarations: Declaration[] = filter(declarations, isNotOverload);
if (exportedDeclarations.length > 1) {
for (const declaration of exportedDeclarations) {
diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, id));
}
}
}
}
links.exportsChecked = true;
}
function isNotOverload(declaration: Declaration): boolean {
return declaration.kind !== SyntaxKind.FunctionDeclaration || !!(declaration as FunctionDeclaration).body;
}
}
function checkTypePredicate(node: TypePredicateNode) {
@@ -15060,6 +15139,35 @@ namespace ts {
return getReferencedValueSymbol(node) === argumentsSymbol;
}
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
if (!moduleSymbol) {
// module not found - be conservative
return true;
}
const hasExportAssignment = getExportAssignmentSymbol(moduleSymbol) !== undefined;
// if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment
// otherwise it will return moduleSymbol itself
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
const symbolLinks = getSymbolLinks(moduleSymbol);
if (symbolLinks.exportsSomeValue === undefined) {
// for export assignments - check if resolved symbol for RHS is itself a value
// otherwise - check if at least one export is value
symbolLinks.exportsSomeValue = hasExportAssignment
? !!(moduleSymbol.flags & SymbolFlags.Value)
: forEachValue(getExportsOfModule(moduleSymbol), isValue);
}
return symbolLinks.exportsSomeValue;
function isValue(s: Symbol): boolean {
s = resolveSymbol(s);
return s && !!(s.flags & SymbolFlags.Value);
}
}
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
// node of the exported entity's container. Otherwise, return undefined.
function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration {
@@ -15365,6 +15473,7 @@ namespace ts {
getReferencedValueDeclaration,
getTypeReferenceSerializationKind,
isOptionalParameter,
moduleExportsSomeValue,
isArgumentsLocalBinding,
getExternalModuleFileFromDeclaration
};
@@ -15392,10 +15501,12 @@ namespace ts {
}
});
// Setup global builtins
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
getSymbolLinks(undefinedSymbol).type = undefinedType;
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
getSymbolLinks(unknownSymbol).type = unknownType;
globals[undefinedSymbol.name] = undefinedSymbol;
// Initialize special types
globalArrayType = <GenericType>getGlobalType("Array", /*arity*/ 1);
@@ -15533,6 +15644,11 @@ namespace ts {
let flags = 0;
for (const modifier of node.modifiers) {
switch (modifier.kind) {
case SyntaxKind.ConstKeyword:
if (node.kind !== SyntaxKind.EnumDeclaration && node.parent.kind === SyntaxKind.ClassDeclaration) {
return grammarErrorOnNode(node, Diagnostics.A_class_member_cannot_have_the_0_keyword, tokenToString(SyntaxKind.ConstKeyword));
}
break;
case SyntaxKind.PublicKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PrivateKeyword:
@@ -16005,6 +16121,13 @@ namespace ts {
return grammarErrorOnNode((<ShorthandPropertyAssignment>prop).equalsToken, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment);
}
// Modifiers are never allowed on properties except for 'async' on a method declaration
forEach(prop.modifiers, mod => {
if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) {
grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
}
});
// ECMA-262 11.1.5 Object Initialiser
// If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
// a.This production is contained in strict code and IsDataDescriptor(previous) is true and
@@ -16089,13 +16212,27 @@ namespace ts {
if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
const variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
if (!checkGrammarVariableDeclarationList(variableList)) {
if (variableList.declarations.length > 1) {
const declarations = variableList.declarations;
// declarations.length can be zero if there is an error in variable declaration in for-of or for-in
// See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details
// For example:
// var let = 10;
// for (let of [1,2,3]) {} // this is invalid ES6 syntax
// for (let in [1,2,3]) {} // this is invalid ES6 syntax
// We will then want to skip on grammar checking on variableList declaration
if (!declarations.length) {
return false;
}
if (declarations.length > 1) {
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
: Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
}
const firstDeclaration = variableList.declarations[0];
const firstDeclaration = declarations[0];
if (firstDeclaration.initializer) {
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
@@ -16294,7 +16431,7 @@ namespace ts {
}
}
const checkLetConstNames = languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node));
const checkLetConstNames = (isLet(node) || isConst(node));
// 1. LexicalDeclaration : LetOrConst BindingList ;
// It is a Syntax Error if the BoundNames of BindingList contains "let".
@@ -16308,7 +16445,7 @@ namespace ts {
function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
if (name.kind === SyntaxKind.Identifier) {
if ((<Identifier>name).text === "let") {
if ((<Identifier>name).originalKeywordKind === SyntaxKind.LetKeyword) {
return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
}
}
+21 -2
View File
@@ -435,7 +435,7 @@
"category": "Error",
"code": 1147
},
"Cannot compile modules unless the '--module' flag is provided.": {
"Cannot compile modules unless the '--module' flag is provided. Consider setting the 'module' compiler option in a 'tsconfig.json' file.": {
"category": "Error",
"code": 1148
},
@@ -791,7 +791,10 @@
"category": "Error",
"code": 1247
},
"A class member cannot have the '{0}' keyword.": {
"category": "Error",
"code": 1248
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
@@ -844,6 +847,10 @@
"category": "Error",
"code": 2307
},
"Module {0} has already exported a member named '{1}'. Consider explicitly re-exporting to resolve the ambiguity.": {
"category": "Error",
"code": 2308
},
"An export assignment cannot be used in a module with other exported elements.": {
"category": "Error",
"code": 2309
@@ -900,6 +907,10 @@
"category": "Error",
"code": 2322
},
"Cannot redeclare exported variable '{0}'.": {
"category": "Error",
"code": 2323
},
"Property '{0}' is missing in type '{1}'.": {
"category": "Error",
"code": 2324
@@ -1180,6 +1191,10 @@
"category": "Error",
"code": 2396
},
"Declaration name conflicts with built-in global identifier '{0}'.": {
"category": "Error",
"code": 2397
},
"Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": {
"category": "Error",
"code": 2399
@@ -1740,6 +1755,10 @@
"category": "Error",
"code": 2657
},
"Type '{0}' provides no match for the signature '{1}'": {
"category": "Error",
"code": 2658
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
+69 -57
View File
@@ -499,7 +499,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let hasExportStars: boolean;
let hasExportStarsToExportValues: boolean;
let detachedCommentsInfo: { nodePos: number; detachedCommentEndPos: number }[];
@@ -574,7 +574,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = undefined;
hasExportStarsToExportValues = undefined;
detachedCommentsInfo = undefined;
sourceMapData = undefined;
isEs6Module = false;
@@ -1453,6 +1453,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSpreadAttribute:
@@ -3628,12 +3629,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// only allow export default at a source file level
if (modulekind === ModuleKind.CommonJS || modulekind === ModuleKind.AMD || modulekind === ModuleKind.UMD) {
if (!isEs6Module) {
if (languageVersion === ScriptTarget.ES5) {
if (languageVersion !== ScriptTarget.ES3) {
// default value of configurable, enumerable, writable are `false`.
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
writeLine();
}
else if (languageVersion === ScriptTarget.ES3) {
else {
write("exports.__esModule = true;");
writeLine();
}
@@ -5171,35 +5172,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (!(node.flags & NodeFlags.Export)) {
return;
}
// If this is an exported class, but not on the top level (i.e. on an internal
// module), export it
if (node.flags & NodeFlags.Default) {
// if this is a top level default export of decorated class, write the export after the declaration.
writeLine();
if (thisNodeIsDecorated && modulekind === ModuleKind.ES6) {
write("export default ");
emitDeclarationName(node);
write(";");
}
else if (modulekind === ModuleKind.System) {
write(`${exportFunctionForFile}("default", `);
emitDeclarationName(node);
write(");");
}
else if (modulekind !== ModuleKind.ES6) {
write(`exports.default = `);
emitDeclarationName(node);
write(";");
}
if (modulekind !== ModuleKind.ES6) {
emitExportMemberAssignment(node as ClassDeclaration);
}
else if (node.parent.kind !== SyntaxKind.SourceFile || (modulekind !== ModuleKind.ES6 && !(node.flags & NodeFlags.Default))) {
writeLine();
emitStart(node);
emitModuleMemberName(node);
write(" = ");
emitDeclarationName(node);
emitEnd(node);
write(";");
else {
// If this is an exported class, but not on the top level (i.e. on an internal
// module), export it
if (node.flags & NodeFlags.Default) {
// if this is a top level default export of decorated class, write the export after the declaration.
if (thisNodeIsDecorated) {
writeLine();
write("export default ");
emitDeclarationName(node);
write(";");
}
}
else if (node.parent.kind !== SyntaxKind.SourceFile) {
writeLine();
emitStart(node);
emitModuleMemberName(node);
write(" = ");
emitDeclarationName(node);
emitEnd(node);
write(";");
}
}
}
@@ -5800,9 +5796,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (!shouldHoistDeclarationInSystemJsModule(node)) {
// do not emit var if variable was already hoisted
if (!(node.flags & NodeFlags.Export) || isES6ExportedDeclaration(node)) {
const isES6ExportedEnum = isES6ExportedDeclaration(node);
if (!(node.flags & NodeFlags.Export) || (isES6ExportedEnum && isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, SyntaxKind.EnumDeclaration))) {
emitStart(node);
if (isES6ExportedDeclaration(node)) {
if (isES6ExportedEnum) {
write("export ");
}
write("var ");
@@ -5899,6 +5897,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return languageVersion === ScriptTarget.ES6 && !!(resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass);
}
function isFirstDeclarationOfKind(node: Declaration, declarations: Declaration[], kind: SyntaxKind) {
return !forEach(declarations, declaration => declaration.kind === kind && declaration.pos < node.pos);
}
function emitModuleDeclaration(node: ModuleDeclaration) {
// Emit only if this module is non-ambient.
const shouldEmit = shouldEmitModuleDeclaration(node);
@@ -5910,15 +5912,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
const emitVarForModule = !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node);
if (emitVarForModule) {
emitStart(node);
if (isES6ExportedDeclaration(node)) {
write("export ");
const isES6ExportedNamespace = isES6ExportedDeclaration(node);
if (!isES6ExportedNamespace || isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, SyntaxKind.ModuleDeclaration)) {
emitStart(node);
if (isES6ExportedNamespace) {
write("export ");
}
write("var ");
emit(node.name);
write(";");
emitEnd(node);
writeLine();
}
write("var ");
emit(node.name);
write(";");
emitEnd(node);
writeLine();
}
emitStart(node);
@@ -6226,15 +6231,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
else {
// export * from "foo"
writeLine();
write("__export(");
if (modulekind !== ModuleKind.AMD) {
emitRequire(getExternalModuleName(node));
if (hasExportStarsToExportValues && resolver.moduleExportsSomeValue(node.moduleSpecifier)) {
writeLine();
write("__export(");
if (modulekind !== ModuleKind.AMD) {
emitRequire(getExternalModuleName(node));
}
else {
write(generatedName);
}
write(");");
}
else {
write(generatedName);
}
write(");");
}
emitEnd(node);
}
@@ -6322,7 +6329,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
externalImports = [];
exportSpecifiers = {};
exportEquals = undefined;
hasExportStars = false;
hasExportStarsToExportValues = false;
for (const node of sourceFile.statements) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
@@ -6345,8 +6352,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if ((<ExportDeclaration>node).moduleSpecifier) {
if (!(<ExportDeclaration>node).exportClause) {
// export * from "mod"
externalImports.push(<ExportDeclaration>node);
hasExportStars = true;
if (resolver.moduleExportsSomeValue((<ExportDeclaration>node).moduleSpecifier)) {
externalImports.push(<ExportDeclaration>node);
hasExportStarsToExportValues = true;
}
}
else if (resolver.isValueAliasDeclaration(node)) {
// export { x, y } from "mod" where at least one export is a value symbol
@@ -6372,7 +6381,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function emitExportStarHelper() {
if (hasExportStars) {
if (hasExportStarsToExportValues) {
writeLine();
write("function __export(m) {");
increaseIndent();
@@ -6450,7 +6459,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// should always win over entries with similar names that were added via star exports
// to support this we store names of local/indirect exported entries in a set.
// this set is used to filter names brought by star expors.
if (!hasExportStars) {
if (!hasExportStarsToExportValues) {
// local names set is needed only in presence of star exports
return undefined;
}
@@ -6875,6 +6884,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write("});");
}
else {
// collectExternalModuleInfo prefilters star exports to keep only ones that export values
// this means that check 'resolver.moduleExportsSomeValue' is redundant and can be omitted here
writeLine();
// export * from 'foo'
// emit as:
@@ -7143,7 +7154,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = false;
hasExportStarsToExportValues = false;
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
emitEmitHelpers(node);
emitCaptureThisForNodeIfNecessary(node);
@@ -7367,7 +7378,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = false;
hasExportStarsToExportValues = false;
emitEmitHelpers(node);
emitCaptureThisForNodeIfNecessary(node);
emitLinesStartingAt(node.statements, startIndex);
@@ -7819,6 +7830,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
const shebang = getShebang(currentText);
if (shebang) {
write(shebang);
writeLine();
}
}
}
+40 -18
View File
@@ -1134,6 +1134,14 @@ namespace ts {
return token === t && tryParse(nextTokenCanFollowModifier);
}
function nextTokenIsOnSameLineAndCanFollowModifier() {
nextToken();
if (scanner.hasPrecedingLineBreak()) {
return false;
}
return canFollowModifier();
}
function nextTokenCanFollowModifier() {
if (token === SyntaxKind.ConstKeyword) {
// 'const' is only a modifier if followed by 'enum'.
@@ -1154,11 +1162,7 @@ namespace ts {
return canFollowModifier();
}
nextToken();
if (scanner.hasPrecedingLineBreak()) {
return false;
}
return canFollowModifier();
return nextTokenIsOnSameLineAndCanFollowModifier();
}
function parseAnyContextualModifier(): boolean {
@@ -3646,7 +3650,7 @@ namespace ts {
parseExpected(SyntaxKind.OpenBraceToken);
if (token !== SyntaxKind.CloseBraceToken) {
node.expression = parseExpression();
node.expression = parseAssignmentExpressionOrHigher();
}
if (inExpressionContext) {
parseExpected(SyntaxKind.CloseBraceToken);
@@ -3988,6 +3992,7 @@ namespace ts {
}
else {
const propertyAssignment = <PropertyAssignment>createNode(SyntaxKind.PropertyAssignment, fullStart);
propertyAssignment.modifiers = modifiers;
propertyAssignment.name = propertyName;
propertyAssignment.questionToken = questionToken;
parseExpected(SyntaxKind.ColonToken);
@@ -4934,15 +4939,31 @@ namespace ts {
return decorators;
}
function parseModifiers(): ModifiersArray {
/*
* There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member.
* In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect
* and turns it into a standalone declaration), then it is better to parse it and report an error later.
*
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
*/
function parseModifiers(permitInvalidConstAsModifier?: boolean): ModifiersArray {
let flags = 0;
let modifiers: ModifiersArray;
while (true) {
const modifierStart = scanner.getStartPos();
const modifierKind = token;
if (!parseAnyContextualModifier()) {
break;
if (token === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) {
// We need to ensure that any subsequent modifiers appear on the same line
// so that when 'const' is a standalone declaration, we don't issue an error.
if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
break;
}
}
else {
if (!parseAnyContextualModifier()) {
break;
}
}
if (!modifiers) {
@@ -4987,7 +5008,7 @@ namespace ts {
const fullStart = getNodePos();
const decorators = parseDecorators();
const modifiers = parseModifiers();
const modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true);
const accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
if (accessor) {
@@ -5321,16 +5342,17 @@ namespace ts {
}
function parseModuleSpecifier(): Expression {
// We allow arbitrary expressions here, even though the grammar only allows string
// literals. We check to ensure that it is only a string literal later in the grammar
// walker.
const result = parseExpression();
// Ensure the string being required is in our 'identifier' table. This will ensure
// that features like 'find refs' will look inside this file when search for its name.
if (result.kind === SyntaxKind.StringLiteral) {
if (token === SyntaxKind.StringLiteral) {
const result = parseLiteralNode();
internIdentifier((<LiteralExpression>result).text);
return result;
}
else {
// We allow arbitrary expressions here, even though the grammar only allows string
// literals. We check to ensure that it is only a string literal later in the grammar
// check pass.
return parseExpression();
}
return result;
}
function parseNamespaceImport(): NamespaceImport {
+10 -10
View File
@@ -99,7 +99,7 @@ namespace ts {
jsonContent = { typings: undefined };
}
if (jsonContent.typings) {
if (typeof jsonContent.typings === "string") {
const result = loadNodeModuleFromFile(extensions, normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
if (result) {
return result;
@@ -661,19 +661,17 @@ namespace ts {
}
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
// For JavaScript files, we don't want to report the normal typescript semantic errors.
// Instead, we just report errors for using TypeScript-only constructs from within a
// JavaScript file.
if (isSourceFileJavaScript(sourceFile)) {
return getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken);
}
return runWithCancellationToken(() => {
const typeChecker = getDiagnosticsProducingTypeChecker();
Debug.assert(!!sourceFile.bindDiagnostics);
const bindDiagnostics = sourceFile.bindDiagnostics;
const checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
// For JavaScript files, we don't want to report the normal typescript semantic errors.
// Instead, we just report errors for using TypeScript-only constructs from within a
// JavaScript file.
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ?
getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) :
typeChecker.getDiagnostics(sourceFile, cancellationToken);
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
@@ -1079,6 +1077,8 @@ namespace ts {
const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
if (importedFile && resolution.isExternalLibraryImport) {
// Since currently irrespective of allowJs, we only look for supportedTypeScript extension external module files,
// this check is ok. Otherwise this would be never true for javascript file
if (!isExternalModule(importedFile)) {
const start = getTokenPosOfNode(file.imports[i], file);
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
@@ -1234,7 +1234,7 @@ namespace ts {
else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && !options.module) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
const span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_unless_the_module_flag_is_provided));
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_unless_the_module_flag_is_provided_Consider_setting_the_module_compiler_option_in_a_tsconfig_json_file));
}
// Cannot specify module gen target of es6 when below es6
+54 -2
View File
@@ -47,6 +47,21 @@ namespace ts {
constructor(o: any);
}
declare var ChakraHost: {
args: string[];
currentDirectory: string;
executingFile: string;
echo(s: string): void;
quit(exitCode?: number): void;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
resolvePath(path: string): string;
readFile(path: string): string;
writeFile(path: string, contents: string): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
};
export var sys: System = (function () {
function getWScriptSystem(): System {
@@ -194,6 +209,7 @@ namespace ts {
}
};
}
function getNodeSystem(): System {
const _fs = require("fs");
const _path = require("path");
@@ -281,7 +297,7 @@ namespace ts {
// REVIEW: for now this implementation uses polling.
// The advantage of polling is that it works reliably
// on all os and with network mounted files.
// For 90 referenced files, the average time to detect
// For 90 referenced files, the average time to detect
// changes is 2*msInterval (by default 5 seconds).
// The overhead of this is .04 percent (1/2500) with
// average pause of < 1 millisecond (and max
@@ -406,7 +422,7 @@ namespace ts {
};
},
watchDirectory: (path, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return _fs.watch(
path,
@@ -454,6 +470,37 @@ namespace ts {
}
};
}
function getChakraSystem(): System {
return {
newLine: "\r\n",
args: ChakraHost.args,
useCaseSensitiveFileNames: false,
write: ChakraHost.echo,
readFile(path: string, encoding?: string) {
// encoding is automatically handled by the implementation in ChakraHost
return ChakraHost.readFile(path);
},
writeFile(path: string, data: string, writeByteOrderMark?: boolean) {
// If a BOM is required, emit one
if (writeByteOrderMark) {
data = "\uFEFF" + data;
}
ChakraHost.writeFile(path, data);
},
resolvePath: ChakraHost.resolvePath,
fileExists: ChakraHost.fileExists,
directoryExists: ChakraHost.directoryExists,
createDirectory: ChakraHost.createDirectory,
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
readDirectory: ChakraHost.readDirectory,
exit: ChakraHost.quit,
};
}
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
return getWScriptSystem();
}
@@ -462,8 +509,13 @@ namespace ts {
// process.browser check excludes webpack and browserify
return getNodeSystem();
}
else if (typeof ChakraHost !== "undefined") {
return getChakraSystem();
}
else {
return undefined; // Unsupported host
}
})();
}
+3 -1
View File
@@ -1761,7 +1761,7 @@ namespace ts {
export interface SymbolDisplayBuilder {
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
@@ -1906,6 +1906,7 @@ namespace ts {
getReferencedValueDeclaration(reference: Identifier): Declaration;
getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind;
isOptionalParameter(node: ParameterDeclaration): boolean;
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
isArgumentsLocalBinding(node: Identifier): boolean;
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): SourceFile;
}
@@ -2024,6 +2025,7 @@ namespace ts {
exportsChecked?: boolean; // True if exports of external module have been checked
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
bindingElement?: BindingElement; // Binding element associated with property symbol
exportsSomeValue?: boolean; // true if module exports some value (not just types)
}
/* @internal */
+1 -1
View File
@@ -2404,7 +2404,7 @@ namespace ts {
* Serialize an object graph into a JSON string. This is intended only for use on an acyclic graph
* as the fallback implementation does not check for circular references by default.
*/
export const stringify: (value: any) => string = JSON && JSON.stringify
export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify
? JSON.stringify
: stringifyFallback;
+23 -3
View File
@@ -6923,7 +6923,7 @@ interface IDBDatabase extends EventTarget {
onerror: (ev: Event) => any;
version: string;
close(): void;
createObjectStore(name: string, optionalParameters?: any): IDBObjectStore;
createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore;
deleteObjectStore(name: string): void;
transaction(storeNames: any, mode?: string): IDBTransaction;
addEventListener(type: "abort", listener: (ev: Event) => any, useCapture?: boolean): void;
@@ -6948,10 +6948,11 @@ declare var IDBFactory: {
}
interface IDBIndex {
keyPath: string;
keyPath: string | string[];
name: string;
objectStore: IDBObjectStore;
unique: boolean;
multiEntry: boolean;
count(key?: any): IDBRequest;
get(key: any): IDBRequest;
getKey(key: any): IDBRequest;
@@ -6988,7 +6989,7 @@ interface IDBObjectStore {
add(value: any, key?: any): IDBRequest;
clear(): IDBRequest;
count(key?: any): IDBRequest;
createIndex(name: string, keyPath: string, optionalParameters?: any): IDBIndex;
createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;
delete(key: any): IDBRequest;
deleteIndex(indexName: string): void;
get(key: any): IDBRequest;
@@ -12575,6 +12576,16 @@ interface XMLHttpRequestEventTarget {
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
interface IDBObjectStoreParameters {
keyPath?: string | string[];
autoIncrement?: boolean;
}
interface IDBIndexParameters {
unique?: boolean;
multiEntry?: boolean;
}
interface NodeListOf<TNode extends Node> extends NodeList {
length: number;
item(index: number): TNode;
@@ -12610,6 +12621,15 @@ interface ProgressEventInit extends EventInit {
total?: number;
}
interface HTMLTemplateElement extends HTMLElement {
content: DocumentFragment;
}
declare var HTMLTemplateElement: {
prototype: HTMLTemplateElement;
new(): HTMLTemplateElement;
}
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface ErrorEventHandler {
+11 -2
View File
@@ -1224,7 +1224,7 @@ declare namespace Reflect {
function isExtensible(target: any): boolean;
function ownKeys(target: any): Array<PropertyKey>;
function preventExtensions(target: any): boolean;
function set(target: any, propertyKey: PropertyKey, value: any, receiver? :any): boolean;
function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
function setPrototypeOf(target: any, proto: any): boolean;
}
@@ -1272,7 +1272,16 @@ interface PromiseConstructor {
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
all<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>]): Promise<[T1, T2, T3, T4]>;
all<T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;
all<T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
all<T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
all<T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
all<TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
+14 -3
View File
@@ -311,7 +311,7 @@ interface IDBDatabase extends EventTarget {
onerror: (ev: Event) => any;
version: string;
close(): void;
createObjectStore(name: string, optionalParameters?: any): IDBObjectStore;
createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore;
deleteObjectStore(name: string): void;
transaction(storeNames: any, mode?: string): IDBTransaction;
addEventListener(type: "abort", listener: (ev: Event) => any, useCapture?: boolean): void;
@@ -336,10 +336,11 @@ declare var IDBFactory: {
}
interface IDBIndex {
keyPath: string;
keyPath: string | string[];
name: string;
objectStore: IDBObjectStore;
unique: boolean;
multiEntry: boolean;
count(key?: any): IDBRequest;
get(key: any): IDBRequest;
getKey(key: any): IDBRequest;
@@ -376,7 +377,7 @@ interface IDBObjectStore {
add(value: any, key?: any): IDBRequest;
clear(): IDBRequest;
count(key?: any): IDBRequest;
createIndex(name: string, keyPath: string, optionalParameters?: any): IDBIndex;
createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;
delete(key: any): IDBRequest;
deleteIndex(indexName: string): void;
get(key: any): IDBRequest;
@@ -892,6 +893,16 @@ interface WorkerUtils extends Object, WindowBase64 {
setTimeout(handler: any, timeout?: any, ...args: any[]): number;
}
interface IDBObjectStoreParameters {
keyPath?: string | string[];
autoIncrement?: boolean;
}
interface IDBIndexParameters {
unique?: boolean;
multiEntry?: boolean;
}
interface BlobPropertyBag {
type?: string;
endings?: string;
+34 -47
View File
@@ -31,8 +31,8 @@ namespace ts.formatting {
* the first token in line so it should be indented
*/
interface DynamicIndentation {
getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind): number;
getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number): number;
getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind, container: Node): number;
getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number, container: Node): number;
/**
* Indentation for open and close tokens of the node if it is block or another node that needs special indentation
* ... {
@@ -54,7 +54,7 @@ namespace ts.formatting {
* so bar inherits indentation from foo and bar.delta will be 4
*
*/
getDelta(): number;
getDelta(child: TextRangeWithKind): number;
/**
* Formatter calls this function when rule adds or deletes new lines from the text
* so indentation scope can adjust values of indentation and delta.
@@ -282,19 +282,19 @@ namespace ts.formatting {
*/
function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
let previousLine = Constants.Unknown;
let childKind = SyntaxKind.Unknown;
let child: Node;
while (n) {
let line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
if (previousLine !== Constants.Unknown && line !== previousLine) {
break;
}
if (SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
if (SmartIndenter.shouldIndentChildNode(n, child)) {
return options.IndentSize;
}
previousLine = line;
childKind = n.kind;
child = n;
n = n.parent;
}
return 0;
@@ -386,34 +386,7 @@ namespace ts.formatting {
effectiveParentStartLine: number): Indentation {
let indentation = inheritedIndentation;
if (indentation === Constants.Unknown) {
if (isSomeBlock(node.kind)) {
// blocks should be indented in
// - other blocks
// - source file
// - switch\default clauses
if (isSomeBlock(parent.kind) ||
parent.kind === SyntaxKind.SourceFile ||
parent.kind === SyntaxKind.CaseClause ||
parent.kind === SyntaxKind.DefaultClause) {
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
}
else {
indentation = parentDynamicIndentation.getIndentation();
}
}
else {
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
indentation = parentDynamicIndentation.getIndentation();
}
else {
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
}
}
}
var delta = SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown) ? options.IndentSize : 0;
var delta = SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0;
if (effectiveParentStartLine === startLine) {
// if node is located on the same line with the parent
@@ -422,8 +395,17 @@ namespace ts.formatting {
indentation = startLine === lastIndentedLine
? indentationOnLastIndentedLine
: parentDynamicIndentation.getIndentation();
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta);
}
else if (indentation === Constants.Unknown) {
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
indentation = parentDynamicIndentation.getIndentation();
}
else {
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node);
}
}
return {
indentation,
delta
@@ -455,7 +437,7 @@ namespace ts.formatting {
function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation {
return {
getIndentationForComment: (kind, tokenIndentation) => {
getIndentationForComment: (kind, tokenIndentation, container) => {
switch (kind) {
// preceding comment to the token that closes the indentation scope inherits the indentation from the scope
// .. {
@@ -464,11 +446,11 @@ namespace ts.formatting {
case SyntaxKind.CloseBraceToken:
case SyntaxKind.CloseBracketToken:
case SyntaxKind.CloseParenToken:
return indentation + delta;
return indentation + getEffectiveDelta(delta, container);
}
return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation;
},
getIndentationForToken: (line, kind) => {
getIndentationForToken: (line, kind, container) => {
if (nodeStartLine !== line && node.decorators) {
if (kind === getFirstNonDecoratorTokenOfNode(node)) {
// if this token is the first token following the list of decorators, we do not need to indent
@@ -489,13 +471,13 @@ namespace ts.formatting {
return indentation;
default:
// if token line equals to the line of containing node (this is a first token in the node) - use node indentation
return nodeStartLine !== line ? indentation + delta : indentation;
return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation;
}
},
getIndentation: () => indentation,
getDelta: () => delta,
getDelta: child => getEffectiveDelta(delta, child),
recomputeIndentation: lineAdded => {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
if (lineAdded) {
indentation += options.IndentSize;
}
@@ -503,14 +485,19 @@ namespace ts.formatting {
indentation -= options.IndentSize;
}
if (SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown)) {
if (SmartIndenter.shouldIndentChildNode(node)) {
delta = options.IndentSize;
}
else {
delta = 0;
}
}
},
}
}
function getEffectiveDelta(delta: number, child: TextRangeWithKind) {
// Delta value should be zero when the node explicitly prevents indentation of the child node
return SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0;
}
}
@@ -610,7 +597,7 @@ namespace ts.formatting {
// if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
let tokenInfo = formattingScanner.readTokenInfo(child);
Debug.assert(tokenInfo.token.end === child.end);
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child);
return inheritedIndentation;
}
@@ -679,7 +666,7 @@ namespace ts.formatting {
}
}
function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation): void {
function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container?: Node): void {
Debug.assert(rangeContainsRange(parent, currentTokenInfo.token));
let lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
@@ -720,11 +707,11 @@ namespace ts.formatting {
if (indentToken) {
let tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ?
dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind) :
dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) :
Constants.Unknown;
if (currentTokenInfo.leadingTrivia) {
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation);
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container);
let indentNextTokenOrTrivia = true;
for (let triviaItem of currentTokenInfo.leadingTrivia) {
+7 -7
View File
@@ -123,6 +123,7 @@ namespace ts.formatting {
public SpaceAfterModuleName: Rule;
// Lambda expressions
public SpaceBeforeArrow: Rule;
public SpaceAfterArrow: Rule;
// Optional parameters and let args
@@ -254,7 +255,7 @@ namespace ts.formatting {
// No space before and after indexer
this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete));
this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete));
// Place a space before open brace in a function declaration
this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments;
@@ -342,6 +343,7 @@ namespace ts.formatting {
this.SpaceAfterModuleName = new Rule(RuleDescriptor.create1(SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsModuleDeclContext), RuleAction.Space));
// Lambda expressions
this.SpaceBeforeArrow = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.EqualsGreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.SpaceAfterArrow = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsGreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
// Optional parameters and let args
@@ -379,8 +381,7 @@ namespace ts.formatting {
this.NoSpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
// These rules are higher in priority than user-configurable rules.
this.HighPriorityCommonRules =
[
this.HighPriorityCommonRules = [
this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator,
this.NoSpaceAfterQuestionMark,
@@ -411,7 +412,7 @@ namespace ts.formatting {
this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
this.SpaceAfterModuleName,
this.SpaceAfterArrow,
this.SpaceBeforeArrow, this.SpaceAfterArrow,
this.NoSpaceAfterEllipsis,
this.NoSpaceAfterOptionalParameters,
this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
@@ -427,8 +428,7 @@ namespace ts.formatting {
];
// These rules are lower in priority than user-configurable rules.
this.LowPriorityCommonRules =
[
this.LowPriorityCommonRules = [
this.NoSpaceBeforeSemicolon,
this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
this.NoSpaceBeforeComma,
@@ -732,7 +732,7 @@ namespace ts.formatting {
}
static IsStartOfVariableDeclarationList(context: FormattingContext): boolean {
return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList &&
return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList &&
context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
}
+17 -11
View File
@@ -68,7 +68,7 @@ namespace ts.formatting {
let indentationDelta: number;
while (current) {
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : SyntaxKind.Unknown)) {
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
@@ -153,7 +153,7 @@ namespace ts.formatting {
}
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) {
indentationDelta += options.IndentSize;
}
@@ -461,16 +461,15 @@ namespace ts.formatting {
case SyntaxKind.ParenthesizedType:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.NamedImports:
return true;
}
return false;
}
export function shouldIndentChildNode(parent: SyntaxKind, child: SyntaxKind): boolean {
if (nodeContentIsAlwaysIndented(parent)) {
return true;
}
switch (parent) {
export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean) {
let childKind = child ? child.kind : SyntaxKind.Unknown;
switch (parent.kind) {
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForInStatement:
@@ -484,10 +483,17 @@ namespace ts.formatting {
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return child !== SyntaxKind.Block;
default:
return false;
return childKind !== SyntaxKind.Block;
}
// No explicit rule for given nodes so the result will follow the default value argument
return indentByDefault;
}
/*
Function returns true when the parent node should indent the given child by an explicit rule
*/
export function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean {
return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, false);
}
}
}
+2 -1
View File
@@ -3751,7 +3751,8 @@ namespace ts {
// Ignore omitted expressions for missing members
if (m.kind !== SyntaxKind.PropertyAssignment &&
m.kind !== SyntaxKind.ShorthandPropertyAssignment &&
m.kind !== SyntaxKind.BindingElement) {
m.kind !== SyntaxKind.BindingElement &&
m.kind !== SyntaxKind.MethodDeclaration) {
continue;
}