Merge branch 'master' into glob2

This commit is contained in:
Ron Buckton
2015-12-07 15:15:22 -08:00
257 changed files with 3300 additions and 846 deletions
+213 -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);
@@ -1875,7 +1948,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);
}
@@ -1887,7 +1960,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);
}
@@ -1901,15 +1974,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();
}
@@ -1950,7 +2020,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();
}
@@ -2070,7 +2140,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
@@ -2938,10 +3013,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;
@@ -3375,11 +3446,11 @@ namespace ts {
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
if (!hasClassBaseType(classType)) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 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, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
@@ -3597,7 +3668,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;
@@ -3605,8 +3676,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);
@@ -5073,9 +5144,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)) {
@@ -5206,17 +5274,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
@@ -5442,20 +5499,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;
}
}
@@ -5765,26 +5828,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]);
@@ -6092,14 +6148,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
@@ -6183,9 +6250,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;
}
@@ -6258,9 +6328,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;
}
}
@@ -6268,29 +6338,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[] {
@@ -14134,8 +14192,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) {
@@ -15270,10 +15349,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);
@@ -15411,6 +15492,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:
@@ -15967,13 +16053,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
@@ -16172,7 +16272,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".
@@ -16186,7 +16286,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);
}
}
+20 -1
View File
@@ -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
@@ -1732,6 +1747,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
+47 -41
View File
@@ -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();
}
@@ -4530,7 +4531,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
const isAsync = isAsyncFunctionLike(node);
if (isAsync && languageVersion === ScriptTarget.ES6) {
if (isAsync) {
emitAsyncFunctionBodyForES6(node);
}
else {
@@ -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);
@@ -7819,6 +7824,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
const shebang = getShebang(currentText);
if (shebang) {
write(shebang);
writeLine();
}
}
}
+38 -17
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 {
@@ -4923,15 +4927,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) {
@@ -4976,7 +4996,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) {
@@ -5310,16 +5330,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 {
+9 -9
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));
+52
View File
@@ -49,6 +49,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 {
@@ -208,6 +223,7 @@ namespace ts {
}
};
}
function getNodeSystem(): System {
const _fs = require("fs");
const _path = require("path");
@@ -494,6 +510,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();
}
@@ -502,8 +549,13 @@ namespace ts {
// process.browser check excludes webpack and browserify
return getNodeSystem();
}
else if (typeof ChakraHost !== "undefined") {
return getChakraSystem();
}
else {
return undefined; // Unsupported host
}
})();
}
+1 -1
View File
@@ -1785,7 +1785,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;
+5 -3
View File
@@ -1889,8 +1889,10 @@ namespace ts {
* Resolves a local path to a path which is absolute to the base of the emit
*/
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string {
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
const relativePath = getRelativePathToDirectoryOrUrl(dir, fileName, dir, f => host.getCanonicalFileName(f), /*isAbsolutePathAnUrl*/ false);
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
const relativePath = getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
return removeFileExtension(relativePath);
}
@@ -2398,7 +2400,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;
+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
+1
View File
@@ -461,6 +461,7 @@ namespace ts.formatting {
case SyntaxKind.ParenthesizedType:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.NamedImports:
return true;
}
return 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;
}