diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index b66497fc40d59..82cfd59a5d68e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -519,17 +519,17 @@ module ts { bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); break; case SyntaxKind.InterfaceDeclaration: - bindDeclaration(node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes, /*isBlockScopeContainer*/ false); + bindBlockScopedDeclaration(node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); break; case SyntaxKind.TypeAliasDeclaration: - bindDeclaration(node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false); + bindBlockScopedDeclaration(node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); break; case SyntaxKind.EnumDeclaration: if (isConst(node)) { - bindDeclaration(node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes, /*isBlockScopeContainer*/ false); + bindBlockScopedDeclaration(node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes); } else { - bindDeclaration(node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes, /*isBlockScopeContainer*/ false); + bindBlockScopedDeclaration(node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes); } break; case SyntaxKind.ModuleDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76ec977491ee2..759b235ad0a9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -342,7 +342,15 @@ module ts { // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = getSymbol(location.locals, name, meaning)) { - break loop; + // Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + if (!(meaning & SymbolFlags.Type) || + !(result.flags & (SymbolFlags.Type & ~SymbolFlags.TypeParameter)) || + !isFunctionLike(location) || + lastLocation === (location).body) { + break loop; + } + result = undefined; } } switch (location.kind) { @@ -1526,17 +1534,55 @@ module ts { } } + function writeSymbolTypeReference(symbol: Symbol, typeArguments: Type[], pos: number, end: number) { + // Unnamed function expressions, arrow functions, and unnamed class expressions have reserved names that + // we don't want to display + if (!isReservedMemberName(symbol.name)) { + buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type); + } + if (pos < end) { + writePunctuation(writer, SyntaxKind.LessThanToken); + writeType(typeArguments[pos++], TypeFormatFlags.None); + while (pos < end) { + writePunctuation(writer, SyntaxKind.CommaToken); + writeSpace(writer); + writeType(typeArguments[pos++], TypeFormatFlags.None); + } + writePunctuation(writer, SyntaxKind.GreaterThanToken); + } + } + function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) { + let typeArguments = type.typeArguments; if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) { - writeType(type.typeArguments[0], TypeFormatFlags.InElementType); + writeType(typeArguments[0], TypeFormatFlags.InElementType); writePunctuation(writer, SyntaxKind.OpenBracketToken); writePunctuation(writer, SyntaxKind.CloseBracketToken); } else { - buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, SymbolFlags.Type); - writePunctuation(writer, SyntaxKind.LessThanToken); - writeTypeList(type.typeArguments, /*union*/ false); - writePunctuation(writer, SyntaxKind.GreaterThanToken); + // Write the type reference in the format f.g.C where A and B are type arguments + // for outer type parameters, and f and g are the respective declaring containers of those + // type parameters. + let outerTypeParameters = type.target.outerTypeParameters; + let i = 0; + if (outerTypeParameters) { + let length = outerTypeParameters.length; + while (i < length) { + // Find group of type arguments for type parameters with the same declaring container. + let start = i; + let parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]); + do { + i++; + } while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); + // When type parameters are their own type arguments for the whole group (i.e. we have + // the default outer type arguments), we don't show the group. + if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) { + writeSymbolTypeReference(parent, typeArguments, start, i); + writePunctuation(writer, SyntaxKind.DotToken); + } + } + } + writeSymbolTypeReference(type.symbol, typeArguments, i, typeArguments.length); } } @@ -1732,7 +1778,7 @@ module ts { function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) { let targetSymbol = getTargetSymbol(symbol); if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) { - buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags); + buildDisplayForTypeParametersAndDelimiters(getLocalTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags); } } @@ -2469,30 +2515,68 @@ module ts { } } - // Return combined list of type parameters from all declarations of a class or interface. Elsewhere we check they're all - // the same, but even if they're not we still need the complete list to ensure instantiations supply type arguments - // for all type parameters. - function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { + // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. + // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set + // in-place and returns the same array. + function appendTypeParameters(typeParameters: TypeParameter[], declarations: TypeParameterDeclaration[]): TypeParameter[] { + for (let declaration of declarations) { + let tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)); + if (!typeParameters) { + typeParameters = [tp]; + } + else if (!contains(typeParameters, tp)) { + typeParameters.push(tp); + } + } + return typeParameters; + } + + // Appends the outer type parameters of a node to a set of type parameters and returns the resulting set. The function + // allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set in-place and + // returns the same array. + function appendOuterTypeParameters(typeParameters: TypeParameter[], node: Node): TypeParameter[]{ + while (true) { + node = node.parent; + if (!node) { + return typeParameters; + } + if (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.FunctionDeclaration || + node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.MethodDeclaration || + node.kind === SyntaxKind.ArrowFunction) { + let declarations = (node).typeParameters; + if (declarations) { + return appendTypeParameters(appendOuterTypeParameters(typeParameters, node), declarations); + } + } + } + } + + // The outer type parameters are those defined by enclosing generic classes, methods, or functions. + function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { + var kind = symbol.flags & SymbolFlags.Class ? SyntaxKind.ClassDeclaration : SyntaxKind.InterfaceDeclaration; + return appendOuterTypeParameters(undefined, getDeclarationOfKind(symbol, kind)); + } + + // The local type parameters are the combined set of type parameters from all declarations of the class or interface. + function getLocalTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { let result: TypeParameter[]; - forEach(symbol.declarations, node => { + for (let node of symbol.declarations) { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration) { let declaration = node; - if (declaration.typeParameters && declaration.typeParameters.length) { - forEach(declaration.typeParameters, node => { - let tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); - if (!result) { - result = [tp]; - } - else if (!contains(result, tp)) { - result.push(tp); - } - }); + if (declaration.typeParameters) { + result = appendTypeParameters(result, declaration.typeParameters); } } - }); + } return result; } + // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus + // its locally declared type parameters. + function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { + return concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterface(symbol)); + } + function getBaseTypes(type: InterfaceType): ObjectType[] { let typeWithBaseTypes = type; if (!typeWithBaseTypes.baseTypes) { @@ -2562,10 +2646,13 @@ module ts { if (!links.declaredType) { let kind = symbol.flags & SymbolFlags.Class ? TypeFlags.Class : TypeFlags.Interface; let type = links.declaredType = createObjectType(kind, symbol); - let typeParameters = getTypeParametersOfClassOrInterface(symbol); - if (typeParameters) { + let outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); + let localTypeParameters = getLocalTypeParametersOfClassOrInterface(symbol); + if (outerTypeParameters || localTypeParameters) { type.flags |= TypeFlags.Reference; - type.typeParameters = typeParameters; + type.typeParameters = concatenate(outerTypeParameters, localTypeParameters); + type.outerTypeParameters = outerTypeParameters; + type.localTypeParameters = localTypeParameters; (type).instantiations = {}; (type).instantiations[getTypeListId(type.typeParameters)] = type; (type).target = type; @@ -2755,12 +2842,12 @@ module ts { return map(baseSignatures, baseSignature => { let signature = baseType.flags & TypeFlags.Reference ? getSignatureInstantiation(baseSignature, (baseType).typeArguments) : cloneSignature(baseSignature); - signature.typeParameters = classType.typeParameters; + signature.typeParameters = classType.localTypeParameters; signature.resolvedReturnType = classType; return signature; }); } - return [createSignature(undefined, classType.typeParameters, emptyArray, classType, 0, false, false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, false, false)]; } function createTupleTypeMemberSymbols(memberTypes: Type[]): SymbolTable { @@ -3109,7 +3196,7 @@ module ts { let links = getNodeLinks(declaration); if (!links.resolvedSignature) { let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface((declaration.parent).symbol) : undefined; - let typeParameters = classType ? classType.typeParameters : + let typeParameters = classType ? classType.localTypeParameters : declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined; let parameters: Symbol[] = []; let hasStringLiterals = false; @@ -3311,6 +3398,10 @@ module ts { return type.constraint === noConstraintType ? undefined : type.constraint; } + function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol { + return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter).parent); + } + function getTypeListId(types: Type[]) { switch (types.length) { case 1: @@ -3426,12 +3517,22 @@ module ts { else { type = getDeclaredTypeOfSymbol(symbol); if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { - let typeParameters = (type).typeParameters; - if (node.typeArguments && node.typeArguments.length === typeParameters.length) { - type = createTypeReference(type, map(node.typeArguments, getTypeFromTypeNode)); + // In a type reference, the outer type parameters of the referenced class or interface are automatically + // supplied as type arguments and the type reference only specifies arguments for the local type parameters + // of the class or interface. + let localTypeParameters = (type).localTypeParameters; + let expectedTypeArgCount = localTypeParameters ? localTypeParameters.length : 0; + let typeArgCount = node.typeArguments ? node.typeArguments.length : 0; + if (typeArgCount === expectedTypeArgCount) { + // When no type arguments are expected we already have the right type because all outer type parameters + // have themselves as default type arguments. + if (typeArgCount) { + type = createTypeReference(type, concatenate((type).outerTypeParameters, + map(node.typeArguments, getTypeFromTypeNode))); + } } else { - error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length); + error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), expectedTypeArgCount); type = undefined; } } @@ -3908,7 +4009,7 @@ module ts { return mapper(type); } if (type.flags & TypeFlags.Anonymous) { - return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) ? + return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) ? instantiateAnonymousType(type, mapper) : type; } if (type.flags & TypeFlags.Reference) { @@ -9140,7 +9241,6 @@ module ts { function checkFunctionDeclaration(node: FunctionDeclaration): void { if (produceDiagnostics) { checkFunctionLikeDeclaration(node) || - checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node); @@ -9511,7 +9611,7 @@ module ts { function checkVariableStatement(node: VariableStatement) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node); + checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node); forEach(node.declarationList.declarations, checkSourceElement); } @@ -10223,10 +10323,6 @@ module ts { function checkClassDeclaration(node: ClassDeclaration) { checkGrammarDeclarationNameInStrictMode(node); // Grammar checking - if (node.parent.kind !== SyntaxKind.ModuleBlock && node.parent.kind !== SyntaxKind.SourceFile) { - grammarErrorOnNode(node, Diagnostics.class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration); - } - if (!node.name && !(node.flags & NodeFlags.Default)) { grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } @@ -12395,19 +12491,28 @@ module ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: case SyntaxKind.IndexSignature: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ModuleDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.VariableStatement: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.ImportDeclaration: case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ExportDeclaration: case SyntaxKind.ExportAssignment: case SyntaxKind.Parameter: break; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.TypeAliasDeclaration: + if (node.modifiers && node.parent.kind !== SyntaxKind.ModuleBlock && node.parent.kind !== SyntaxKind.SourceFile) { + return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here); + } + break; + case SyntaxKind.EnumDeclaration: + if (node.modifiers && (node.modifiers.length > 1 || node.modifiers[0].kind !== SyntaxKind.ConstKeyword) && + node.parent.kind !== SyntaxKind.ModuleBlock && node.parent.kind !== SyntaxKind.SourceFile) { + return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here); + } + break; default: return false; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f5719033a2a31..281bfa36ece63 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -129,6 +129,16 @@ module ts { } } + export function rangeEquals(array1: T[], array2: T[], pos: number, end: number) { + while (pos < end) { + if (array1[pos] !== array2[pos]) { + return false; + } + pos++; + } + return true; + } + /** * Returns the last element of an array if non-empty, undefined otherwise. */ diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 5212f062eebdd..6e73d28bdddd1 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -548,6 +548,5 @@ module ts { decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." }, Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." }, class_expressions_are_not_currently_supported: { code: 9003, category: DiagnosticCategory.Error, key: "'class' expressions are not currently supported." }, - class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration: { code: 9004, category: DiagnosticCategory.Error, key: "'class' declarations are only supported directly inside a module or as a top level declaration." }, }; } \ No newline at end of file diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2aa5bdf298d10..d5764605d51bb 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2185,9 +2185,5 @@ "'class' expressions are not currently supported.": { "category": "Error", "code": 9003 - }, - "'class' declarations are only supported directly inside a module or as a top level declaration.": { - "category": "Error", - "code": 9004 } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d6d6f0d14daec..4a46e375f87f3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -401,7 +401,7 @@ module ts { module Parser { // Share a single scanner across all calls to parse a source file. This helps speed things // up by avoiding the cost of creating/compiling scanners over and over again. - const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); const disallowInAndDecoratorContext = ParserContextFlags.DisallowIn | ParserContextFlags.Decorator; let sourceFile: SourceFile; @@ -493,6 +493,13 @@ module ts { // attached to the EOF token. let parseErrorBeforeNextFinishedNode: boolean = false; + export const enum StatementFlags { + None = 0, + Statement = 1, + ModuleElement = 2, + StatementOrModuleElement = Statement | ModuleElement + } + export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile { initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); @@ -847,7 +854,7 @@ module ts { // was in immediately prior to invoking the callback. The result of invoking the callback // is returned from this function. function lookAhead(callback: () => T): T { - return speculationHelper(callback, /*isLookAhead:*/ true); + return speculationHelper(callback, /*isLookAhead*/ true); } // Invokes the provided callback. If the callback returns something falsy, then it restores @@ -855,7 +862,7 @@ module ts { // callback returns something truthy, then the parser state is not rolled back. The result // of invoking the callback is returned from this function. function tryParse(callback: () => T): T { - return speculationHelper(callback, /*isLookAhead:*/ false); + return speculationHelper(callback, /*isLookAhead*/ false); } // Ignore strict mode flag because we will report an error in type checker instead. @@ -1004,7 +1011,7 @@ module ts { return finishNode(node); } - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition:*/ false, diagnosticMessage || Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics.Identifier_expected); } function parseIdentifier(diagnosticMessage?: DiagnosticMessage): Identifier { @@ -1023,7 +1030,7 @@ module ts { function parsePropertyNameWorker(allowComputedPropertyNames: boolean): DeclarationName { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { - return parseLiteralNode(/*internName:*/ true); + return parseLiteralNode(/*internName*/ true); } if (allowComputedPropertyNames && token === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); @@ -1121,10 +1128,17 @@ module ts { switch (parsingContext) { case ParsingContext.SourceElements: case ParsingContext.ModuleElements: - return isSourceElement(inErrorRecovery); + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfModuleElement(); case ParsingContext.BlockStatements: case ParsingContext.SwitchClauseStatements: - return isStartOfStatement(inErrorRecovery); + // During error recovery we don't treat empty statements as statements + return !(token === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement(); case ParsingContext.SwitchClauses: return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword; case ParsingContext.TypeMembers: @@ -1805,7 +1819,7 @@ module ts { // Report that we need an identifier. However, report it right after the dot, // and not on the next token. This is because the next token might actually // be an identifier and the error woudl be quite confusing. - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken:*/ true, Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken*/ true, Diagnostics.Identifier_expected); } } @@ -1843,7 +1857,7 @@ module ts { literal = parseLiteralNode(); } else { - literal = parseExpectedToken(SyntaxKind.TemplateTail, /*reportAtCurrentPosition:*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)); + literal = parseExpectedToken(SyntaxKind.TemplateTail, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)); } span.literal = literal; @@ -1936,7 +1950,7 @@ module ts { function parseParameterType(): TypeNode { if (parseOptional(SyntaxKind.ColonToken)) { return token === SyntaxKind.StringLiteral - ? parseLiteralNode(/*internName:*/ true) + ? parseLiteralNode(/*internName*/ true) : parseType(); } @@ -2077,7 +2091,7 @@ module ts { if (kind === SyntaxKind.ConstructSignature) { parseExpected(SyntaxKind.NewKeyword); } - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ false, node); parseTypeMemberSemicolon(); return finishNode(node); } @@ -2167,7 +2181,7 @@ module ts { // Method signatues don't exist in expression contexts. So they have neither // [Yield] nor [GeneratorParameter] - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ false, method); parseTypeMemberSemicolon(); return finishNode(method); } @@ -2224,7 +2238,7 @@ module ts { case SyntaxKind.OpenBracketToken: // Indexer or computed property return isIndexSignature() - ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined) + ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined) : parsePropertyOrMethodSignature(); case SyntaxKind.NewKeyword: if (lookAhead(isStartOfConstructSignature)) { @@ -2306,7 +2320,7 @@ module ts { if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); } - fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node); + fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ false, node); return finishNode(node); } @@ -2615,7 +2629,7 @@ module ts { // Otherwise, we try to parse out the conditional expression bit. We want to allow any // binary expression here, so we pass in the 'lowest' precedence here so that it matches // and consumes anything. - let expr = parseBinaryExpressionOrHigher(/*precedence:*/ 0); + let expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single @@ -2677,12 +2691,6 @@ module ts { return !scanner.hasPrecedingLineBreak() && isIdentifier() } - function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() { - nextToken(); - return !scanner.hasPrecedingLineBreak() && - (isIdentifier() || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken); - } - function parseYieldExpression(): YieldExpression { let node = createNode(SyntaxKind.YieldExpression); @@ -2737,7 +2745,7 @@ module ts { // it out, but don't allow any ambiguity, and return 'undefined' if this could be an // expression instead. let arrowFunction = triState === Tristate.True - ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ true) + ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead); if (!arrowFunction) { @@ -2748,7 +2756,7 @@ module ts { // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. var lastToken = token; - arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition:*/false, Diagnostics._0_expected, "=>"); + arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/false, Diagnostics._0_expected, "=>"); arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) ? parseArrowFunctionExpressionBody() : parseIdentifier(); @@ -2846,7 +2854,7 @@ module ts { } function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction { - return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ false); + return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction { @@ -2858,7 +2866,7 @@ module ts { // a => (b => c) // And think that "(b =>" was actually a parenthesized arrow function with a missing // close paren. - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ !allowAmbiguity, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ !allowAmbiguity, node); // If we couldn't get parameters, we definitely could not parse out an arrow function. if (!node.parameters) { @@ -2883,14 +2891,14 @@ module ts { function parseArrowFunctionExpressionBody(): Block | Expression { if (token === SyntaxKind.OpenBraceToken) { - return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false); + return parseFunctionBlock(/*allowYield*/ false, /*ignoreMissingOpenBrace*/ false); } - if (isStartOfStatement(/*inErrorRecovery:*/ true) && - !isStartOfExpressionStatement() && + if (token !== SyntaxKind.SemicolonToken && token !== SyntaxKind.FunctionKeyword && - token !== SyntaxKind.ClassKeyword) { - + token !== SyntaxKind.ClassKeyword && + isStartOfStatement() && + !isStartOfExpressionStatement()) { // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) // // Here we try to recover from a potential error situation in the case where the @@ -2905,7 +2913,7 @@ module ts { // up preemptively closing the containing construct. // // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error. - return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true); + return parseFunctionBlock(/*allowYield*/ false, /*ignoreMissingOpenBrace*/ true); } return parseAssignmentExpressionOrHigher(); @@ -2924,7 +2932,7 @@ module ts { node.condition = leftOperand; node.questionToken = questionToken; node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher); - node.colonToken = parseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition:*/ false, + node.colonToken = parseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)); node.whenFalse = parseAssignmentExpressionOrHigher(); return finishNode(node); @@ -3188,8 +3196,8 @@ module ts { // If it wasn't then just try to parse out a '.' and report an error. let node = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); node.expression = expression; - node.dotToken = parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition:*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(/*allowIdentifierNames:*/ true); + node.dotToken = parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); return finishNode(node); } @@ -3209,7 +3217,7 @@ module ts { let propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; propertyAccess.dotToken = dotToken; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames:*/ true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); continue; } @@ -3472,7 +3480,7 @@ module ts { node.flags |= NodeFlags.MultiLine; } - node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimeter:*/ true); + node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimeter*/ true); parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } @@ -3490,8 +3498,8 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node); - node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ !!node.asteriskToken, /*requireCompleteParameterList*/ false, node); + node.body = parseFunctionBlock(/*allowYield*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false); if (saveDecoratorContext) { setDecoratorContext(true); } @@ -3601,7 +3609,7 @@ module ts { let initializer: VariableDeclarationList | Expression = undefined; if (token !== SyntaxKind.SemicolonToken) { if (token === SyntaxKind.VarKeyword || token === SyntaxKind.LetKeyword || token === SyntaxKind.ConstKeyword) { - initializer = parseVariableDeclarationList(/*inForStatementInitializer:*/ true); + initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); } else { initializer = disallowInAnd(parseExpression); @@ -3731,14 +3739,14 @@ module ts { let node = createNode(SyntaxKind.TryStatement); parseExpected(SyntaxKind.TryKeyword); - node.tryBlock = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode*/ false); + node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false); node.catchClause = token === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. if (!node.catchClause || token === SyntaxKind.FinallyKeyword) { parseExpected(SyntaxKind.FinallyKeyword); - node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode*/ false); + node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false); } return finishNode(node); @@ -3752,7 +3760,7 @@ module ts { } parseExpected(SyntaxKind.CloseParenToken); - result.block = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false); + result.block = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false); return finishNode(result); } @@ -3784,34 +3792,72 @@ module ts { } } - function isStartOfStatement(inErrorRecovery: boolean): boolean { - // Functions, variable statements and classes are allowed as a statement. But as per - // the grammar, they also allow modifiers. So we have to check for those statements - // that might be following modifiers.This ensures that things work properly when - // incrementally parsing as the parser will produce the same FunctionDeclaraiton, - // VariableStatement or ClassDeclaration, if it has the same text regardless of whether - // it is inside a block or not. - if (isModifier(token)) { - let result = lookAhead(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers); - if (result) { - return true; + function isIdentifierOrKeyword() { + return token >= SyntaxKind.Identifier; + } + + function nextTokenIsIdentifierOrKeywordOnSameLine() { + nextToken(); + return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak(); + } + + function parseDeclarationFlags(): StatementFlags { + while (true) { + switch (token) { + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: + return StatementFlags.Statement; + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.TypeKeyword: + nextToken(); + return isIdentifierOrKeyword() ? StatementFlags.Statement : StatementFlags.None; + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + nextToken(); + return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral ? StatementFlags.ModuleElement : StatementFlags.None; + case SyntaxKind.ImportKeyword: + nextToken(); + return token === SyntaxKind.StringLiteral || token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBraceToken || isIdentifierOrKeyword() ? + StatementFlags.ModuleElement : StatementFlags.None; + case SyntaxKind.ExportKeyword: + nextToken(); + if (token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword) { + return StatementFlags.ModuleElement; + } + continue; + case SyntaxKind.DeclareKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + nextToken(); + continue; + default: + return StatementFlags.None; } } + } + + function getDeclarationFlags(): StatementFlags { + return lookAhead(parseDeclarationFlags); + } + function getStatementFlags(): StatementFlags { switch (token) { + case SyntaxKind.AtToken: case SyntaxKind.SemicolonToken: - // If we're in error recovery, then we don't want to treat ';' as an empty statement. - // The problem is that ';' can show up in far too many contexts, and if we see one - // and assume it's a statement, then we may bail out inappropriately from whatever - // we're parsing. For example, if we have a semicolon in the middle of a class, then - // we really don't want to assume the class is over and we're on a statement in the - // outer module. We just want to consume and move on. - return !inErrorRecovery; case SyntaxKind.OpenBraceToken: case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: case SyntaxKind.FunctionKeyword: case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: case SyntaxKind.IfKeyword: case SyntaxKind.DoKeyword: case SyntaxKind.WhileKeyword: @@ -3828,62 +3874,84 @@ module ts { // however, we say they are here so that we may gracefully parse them and error later. case SyntaxKind.CatchKeyword: case SyntaxKind.FinallyKeyword: - return true; + return StatementFlags.Statement; + case SyntaxKind.ConstKeyword: - // const keyword can precede enum keyword when defining constant enums - // 'const enum' do not start statement. - // In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier - let isConstEnum = lookAhead(nextTokenIsEnumKeyword); - return !isConstEnum; + case SyntaxKind.ExportKeyword: + case SyntaxKind.ImportKeyword: + return getDeclarationFlags(); + + case SyntaxKind.DeclareKeyword: case SyntaxKind.InterfaceKeyword: case SyntaxKind.ModuleKeyword: case SyntaxKind.NamespaceKeyword: - case SyntaxKind.EnumKeyword: case SyntaxKind.TypeKeyword: - // When followed by an identifier, these do not start a statement but might - // instead be following declarations - if (isDeclarationStart()) { - return false; - } + // When these don't start a declaration, they're an identifier in an expression statement + return getDeclarationFlags() || StatementFlags.Statement; case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.StaticKeyword: - // When followed by an identifier or keyword, these do not start a statement but - // might instead be following type members - if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) { - return false; - } + // When these don't start a declaration, they may be the start of a class member if an identifier + // immediately follows. Otherwise they're an identifier in an expression statement. + return getDeclarationFlags() || + (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? StatementFlags.None : StatementFlags.Statement); + default: - return isStartOfExpression(); + return isStartOfExpression() ? StatementFlags.Statement : StatementFlags.None; } } - function nextTokenIsEnumKeyword() { - nextToken(); - return token === SyntaxKind.EnumKeyword + function isStartOfStatement(): boolean { + return (getStatementFlags() & StatementFlags.Statement) !== 0; } - function nextTokenIsIdentifierOrKeywordOnSameLine() { + function isStartOfModuleElement(): boolean { + return (getStatementFlags() & StatementFlags.StatementOrModuleElement) !== 0; + } + + function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() { nextToken(); - return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak(); + return !scanner.hasPrecedingLineBreak() && + (isIdentifier() || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken); + } + + function isLetDeclaration() { + // It is let declaration if in strict mode or next token is identifier\open bracket\open curly on same line. + // otherwise it needs to be treated like identifier + return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine); } function parseStatement(): Statement { + return parseModuleElementOfKind(StatementFlags.Statement); + } + + function parseModuleElement(): ModuleElement { + return parseModuleElementOfKind(StatementFlags.StatementOrModuleElement); + } + + function parseSourceElement(): ModuleElement { + return parseModuleElementOfKind(StatementFlags.StatementOrModuleElement); + } + + function parseModuleElementOfKind(flags: StatementFlags): ModuleElement { switch (token) { + case SyntaxKind.SemicolonToken: + return parseEmptyStatement(); case SyntaxKind.OpenBraceToken: - return parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false); + return parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false); case SyntaxKind.VarKeyword: - case SyntaxKind.ConstKeyword: - // const here should always be parsed as const declaration because of check in 'isStatement' - return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined); + return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined); + case SyntaxKind.LetKeyword: + if (isLetDeclaration()) { + return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined); + } + break; case SyntaxKind.FunctionKeyword: - return parseFunctionDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined); + return parseFunctionDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined); case SyntaxKind.ClassKeyword: - return parseClassDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined); - case SyntaxKind.SemicolonToken: - return parseEmptyStatement(); + return parseClassDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined); case SyntaxKind.IfKeyword: return parseIfStatement(); case SyntaxKind.DoKeyword: @@ -3911,61 +3979,69 @@ module ts { return parseTryStatement(); case SyntaxKind.DebuggerKeyword: return parseDebuggerStatement(); - case SyntaxKind.LetKeyword: - // If let follows identifier on the same line, it is declaration parse it as variable statement - if (isLetDeclaration()) { - return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined); - } - // Else parse it like identifier - fall through - default: - // Functions and variable statements are allowed as a statement. But as per - // the grammar, they also allow modifiers. So we have to check for those - // statements that might be following modifiers. This ensures that things - // work properly when incrementally parsing as the parser will produce the - // same FunctionDeclaraiton or VariableStatement if it has the same text - // regardless of whether it is inside a block or not. - // Even though variable statements and function declarations cannot have decorators, - // we parse them here to provide better error recovery. - if (isModifier(token) || token === SyntaxKind.AtToken) { - let result = tryParse(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers); - if (result) { - return result; - } + case SyntaxKind.AtToken: + return parseDeclaration(); + case SyntaxKind.ConstKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.ImportKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.TypeKeyword: + if (getDeclarationFlags() & flags) { + return parseDeclaration(); } - - return parseExpressionOrLabeledStatement(); + break; } + return parseExpressionOrLabeledStatement(); } - function parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers(): FunctionDeclaration | VariableStatement | ClassDeclaration { - let start = scanner.getStartPos(); + function parseDeclaration(): ModuleElement { + let fullStart = getNodePos(); let decorators = parseDecorators(); let modifiers = parseModifiers(); switch (token) { - case SyntaxKind.ConstKeyword: - let nextTokenIsEnum = lookAhead(nextTokenIsEnumKeyword) - if (nextTokenIsEnum) { - return undefined; - } - return parseVariableStatement(start, decorators, modifiers); - - case SyntaxKind.LetKeyword: - if (!isLetDeclaration()) { - return undefined; - } - return parseVariableStatement(start, decorators, modifiers); - case SyntaxKind.VarKeyword: - return parseVariableStatement(start, decorators, modifiers); - + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + return parseVariableStatement(fullStart, decorators, modifiers); case SyntaxKind.FunctionKeyword: - return parseFunctionDeclaration(start, decorators, modifiers); - + return parseFunctionDeclaration(fullStart, decorators, modifiers); case SyntaxKind.ClassKeyword: - return parseClassDeclaration(start, decorators, modifiers); + return parseClassDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.InterfaceKeyword: + return parseInterfaceDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.TypeKeyword: + return parseTypeAliasDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.EnumKeyword: + return parseEnumDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + return parseModuleDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ImportKeyword: + return parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers); + case SyntaxKind.ExportKeyword: + nextToken(); + return token === SyntaxKind.DefaultKeyword || token === SyntaxKind.EqualsToken ? + parseExportAssignment(fullStart, decorators, modifiers) : + parseExportDeclaration(fullStart, decorators, modifiers); + default: + if (decorators) { + // We reached this point because we encountered decorators and/or modifiers and assumed a declaration + // would follow. For recovery and error reporting purposes, return an incomplete declaration. + let node = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + node.pos = fullStart; + node.decorators = decorators; + setModifiers(node, modifiers); + return finishNode(node); + } } - - return undefined; } function parseFunctionBlockOrSemicolon(isGenerator: boolean, diagnosticMessage?: DiagnosticMessage): Block { @@ -3974,7 +4050,7 @@ module ts { return; } - return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage); + return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace*/ false, diagnosticMessage); } // DECLARATIONS @@ -4097,7 +4173,7 @@ module ts { let node = createNode(SyntaxKind.VariableStatement, fullStart); node.decorators = decorators; setModifiers(node, modifiers); - node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer:*/ false); + node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); return finishNode(node); } @@ -4109,7 +4185,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier(); - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ !!node.asteriskToken, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, Diagnostics.or_expected); return finishNode(node); } @@ -4119,8 +4195,8 @@ module ts { node.decorators = decorators; setModifiers(node, modifiers); parseExpected(SyntaxKind.ConstructorKeyword); - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node); - node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false, Diagnostics.or_expected); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ false, node); + node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, Diagnostics.or_expected); return finishNode(node); } @@ -4131,7 +4207,7 @@ module ts { method.asteriskToken = asteriskToken; method.name = name; method.questionToken = questionToken; - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, /*requireCompleteParameterList:*/ false, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ !!asteriskToken, /*requireCompleteParameterList*/ false, method); method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage); return finishNode(method); } @@ -4185,8 +4261,8 @@ module ts { node.decorators = decorators; setModifiers(node, modifiers); node.name = parsePropertyName(); - fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node); - node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*requireCompleteParameterList*/ false, node); + node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false); return finishNode(node); } @@ -4365,9 +4441,9 @@ module ts { function parseClassExpression(): ClassExpression { return parseClassDeclarationOrExpression( - /*fullStart:*/ scanner.getStartPos(), - /*decorators:*/ undefined, - /*modifiers:*/ undefined, + /*fullStart*/ scanner.getStartPos(), + /*decorators*/ undefined, + /*modifiers*/ undefined, SyntaxKind.ClassExpression); } @@ -4386,7 +4462,7 @@ module ts { parseExpected(SyntaxKind.ClassKeyword); node.name = parseOptionalIdentifier(); node.typeParameters = parseTypeParameters(); - node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ true); + node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ true); if (parseExpected(SyntaxKind.OpenBraceToken)) { // ClassTail[Yield,GeneratorParameter] : See 14.5 @@ -4422,7 +4498,7 @@ module ts { } function parseHeritageClausesWorker() { - return parseList(ParsingContext.HeritageClauses, /*checkForStrictMode:*/ false, parseHeritageClause); + return parseList(ParsingContext.HeritageClauses, /*checkForStrictMode*/ false, parseHeritageClause); } function parseHeritageClause() { @@ -4462,7 +4538,7 @@ module ts { parseExpected(SyntaxKind.InterfaceKeyword); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); - node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ false); + node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ false); node.members = parseObjectTypeMembers(); return finishNode(node); } @@ -4525,7 +4601,7 @@ module ts { node.flags |= flags; node.name = parseIdentifier(); node.body = parseOptional(SyntaxKind.DotToken) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers:*/undefined, NodeFlags.Export) + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.Export) : parseModuleBlock(); return finishNode(node); } @@ -4534,7 +4610,7 @@ module ts { let node = createNode(SyntaxKind.ModuleDeclaration, fullStart); node.decorators = decorators; setModifiers(node, modifiers); - node.name = parseLiteralNode(/*internName:*/ true); + node.name = parseLiteralNode(/*internName*/ true); node.body = parseModuleBlock(); return finishNode(node); } @@ -4761,151 +4837,6 @@ module ts { return finishNode(node); } - function isLetDeclaration() { - // It is let declaration if in strict mode or next token is identifier\open bracket\open curly on same line. - // otherwise it needs to be treated like identifier - return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine); - } - - function isDeclarationStart(followsModifier?: boolean): boolean { - switch (token) { - case SyntaxKind.VarKeyword: - case SyntaxKind.ConstKeyword: - case SyntaxKind.FunctionKeyword: - return true; - case SyntaxKind.LetKeyword: - return isLetDeclaration(); - case SyntaxKind.ClassKeyword: - case SyntaxKind.InterfaceKeyword: - case SyntaxKind.EnumKeyword: - case SyntaxKind.TypeKeyword: - // Not true keywords so ensure an identifier follows - return lookAhead(nextTokenIsIdentifierOrKeyword); - case SyntaxKind.ImportKeyword: - // Not true keywords so ensure an identifier follows or is string literal or asterisk or open brace - return lookAhead(nextTokenCanFollowImportKeyword); - case SyntaxKind.ModuleKeyword: - case SyntaxKind.NamespaceKeyword: - // Not a true keyword so ensure an identifier or string literal follows - return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral); - case SyntaxKind.ExportKeyword: - // Check for export assignment or modifier on source element - return lookAhead(nextTokenCanFollowExportKeyword); - case SyntaxKind.DeclareKeyword: - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.StaticKeyword: - // Check for modifier on source element - return lookAhead(nextTokenIsDeclarationStart); - case SyntaxKind.AtToken: - // a lookahead here is too costly, and decorators are only valid on a declaration. - // We will assume we are parsing a declaration here and report an error later - return !followsModifier; - } - } - - function isIdentifierOrKeyword() { - return token >= SyntaxKind.Identifier; - } - - function nextTokenIsIdentifierOrKeyword() { - nextToken(); - return isIdentifierOrKeyword(); - } - - function nextTokenIsIdentifierOrKeywordOrStringLiteral() { - nextToken(); - return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral; - } - - function nextTokenCanFollowImportKeyword() { - nextToken(); - return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || - token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken; - } - - function nextTokenCanFollowExportKeyword() { - nextToken(); - return token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken || - token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword || isDeclarationStart(/*followsModifier*/ true); - } - - function nextTokenIsDeclarationStart() { - nextToken(); - return isDeclarationStart(/*followsModifier*/ true); - } - - function nextTokenIsAsKeyword() { - return nextToken() === SyntaxKind.AsKeyword; - } - - function parseDeclaration(): ModuleElement { - let fullStart = getNodePos(); - let decorators = parseDecorators(); - let modifiers = parseModifiers(); - if (token === SyntaxKind.ExportKeyword) { - nextToken(); - if (token === SyntaxKind.DefaultKeyword || token === SyntaxKind.EqualsToken) { - return parseExportAssignment(fullStart, decorators, modifiers); - } - if (token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken) { - return parseExportDeclaration(fullStart, decorators, modifiers); - } - } - - switch (token) { - case SyntaxKind.VarKeyword: - case SyntaxKind.LetKeyword: - case SyntaxKind.ConstKeyword: - return parseVariableStatement(fullStart, decorators, modifiers); - case SyntaxKind.FunctionKeyword: - return parseFunctionDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.ClassKeyword: - return parseClassDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.InterfaceKeyword: - return parseInterfaceDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.TypeKeyword: - return parseTypeAliasDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.EnumKeyword: - return parseEnumDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.ModuleKeyword: - case SyntaxKind.NamespaceKeyword: - return parseModuleDeclaration(fullStart, decorators, modifiers); - case SyntaxKind.ImportKeyword: - return parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers); - default: - if (decorators) { - // We reached this point because we encountered an AtToken and assumed a declaration would - // follow. For recovery and error reporting purposes, return an incomplete declaration. - let node = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); - node.pos = fullStart; - node.decorators = decorators; - setModifiers(node, modifiers); - return finishNode(node); - } - Debug.fail("Mismatch between isDeclarationStart and parseDeclaration"); - } - } - - function isSourceElement(inErrorRecovery: boolean): boolean { - return isDeclarationStart() || isStartOfStatement(inErrorRecovery); - } - - function parseSourceElement() { - return parseSourceElementOrModuleElement(); - } - - function parseModuleElement() { - return parseSourceElementOrModuleElement(); - } - - function parseSourceElementOrModuleElement(): ModuleElement { - return isDeclarationStart() - ? parseDeclaration() - : parseStatement(); - } - function processReferenceComments(sourceFile: SourceFile): void { let triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/false, sourceText); let referencedFiles: FileReference[] = []; @@ -5912,7 +5843,7 @@ module ts { if (child.pos > changeRangeOldEnd) { // Node is entirely past the change range. We need to move both its pos and // end, forward or backward appropriately. - moveElementEntirelyPastChangeRange(child, /*isArray:*/ false, delta, oldText, newText, aggressiveChecks); + moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); return; } @@ -5941,7 +5872,7 @@ module ts { if (array.pos > changeRangeOldEnd) { // Array is entirely after the change range. We need to move it, and move any of // its children. - moveElementEntirelyPastChangeRange(array, /*isArray:*/ true, delta, oldText, newText, aggressiveChecks); + moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); return; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3d52d096b0324..14e53ee8f728e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -917,7 +917,7 @@ module ts { _classElementBrand: any; } - export interface InterfaceDeclaration extends Declaration, ModuleElement { + export interface InterfaceDeclaration extends Declaration, Statement { name: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; @@ -929,7 +929,7 @@ module ts { types?: NodeArray; } - export interface TypeAliasDeclaration extends Declaration, ModuleElement { + export interface TypeAliasDeclaration extends Declaration, Statement { name: Identifier; type: TypeNode; } @@ -941,7 +941,7 @@ module ts { initializer?: Expression; } - export interface EnumDeclaration extends Declaration, ModuleElement { + export interface EnumDeclaration extends Declaration, Statement { name: Identifier; members: NodeArray; } @@ -1626,6 +1626,8 @@ module ts { // Class and interface types (TypeFlags.Class and TypeFlags.Interface) export interface InterfaceType extends ObjectType { typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) + outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none) + localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none) } export interface InterfaceTypeWithBaseTypes extends InterfaceType { diff --git a/tests/baselines/reference/classDeclarationBlockScoping1.errors.txt b/tests/baselines/reference/classDeclarationBlockScoping1.errors.txt deleted file mode 100644 index 4f15007bb2a03..0000000000000 --- a/tests/baselines/reference/classDeclarationBlockScoping1.errors.txt +++ /dev/null @@ -1,13 +0,0 @@ -tests/cases/compiler/classDeclarationBlockScoping1.ts(5,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - - -==== tests/cases/compiler/classDeclarationBlockScoping1.ts (1 errors) ==== - class C { - } - - { - class C { - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - } - } \ No newline at end of file diff --git a/tests/baselines/reference/classDeclarationBlockScoping1.symbols b/tests/baselines/reference/classDeclarationBlockScoping1.symbols new file mode 100644 index 0000000000000..645d327e256ff --- /dev/null +++ b/tests/baselines/reference/classDeclarationBlockScoping1.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/classDeclarationBlockScoping1.ts === +class C { +>C : Symbol(C, Decl(classDeclarationBlockScoping1.ts, 0, 0)) +} + +{ + class C { +>C : Symbol(C, Decl(classDeclarationBlockScoping1.ts, 3, 1)) + } +} diff --git a/tests/baselines/reference/classDeclarationBlockScoping1.types b/tests/baselines/reference/classDeclarationBlockScoping1.types new file mode 100644 index 0000000000000..9020ca4a23aff --- /dev/null +++ b/tests/baselines/reference/classDeclarationBlockScoping1.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/classDeclarationBlockScoping1.ts === +class C { +>C : C +} + +{ + class C { +>C : C + } +} diff --git a/tests/baselines/reference/classDeclarationBlockScoping2.errors.txt b/tests/baselines/reference/classDeclarationBlockScoping2.errors.txt deleted file mode 100644 index 2a9885e110b40..0000000000000 --- a/tests/baselines/reference/classDeclarationBlockScoping2.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/compiler/classDeclarationBlockScoping2.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. -tests/cases/compiler/classDeclarationBlockScoping2.ts(5,15): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - - -==== tests/cases/compiler/classDeclarationBlockScoping2.ts (2 errors) ==== - function f() { - class C {} - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - var c1 = C; - { - class C {} - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - var c2 = C; - } - return C === c1; - } \ No newline at end of file diff --git a/tests/baselines/reference/classDeclarationBlockScoping2.symbols b/tests/baselines/reference/classDeclarationBlockScoping2.symbols new file mode 100644 index 0000000000000..cece47c3ee765 --- /dev/null +++ b/tests/baselines/reference/classDeclarationBlockScoping2.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/classDeclarationBlockScoping2.ts === +function f() { +>f : Symbol(f, Decl(classDeclarationBlockScoping2.ts, 0, 0)) + + class C {} +>C : Symbol(C, Decl(classDeclarationBlockScoping2.ts, 0, 14)) + + var c1 = C; +>c1 : Symbol(c1, Decl(classDeclarationBlockScoping2.ts, 2, 7)) +>C : Symbol(C, Decl(classDeclarationBlockScoping2.ts, 0, 14)) + { + class C {} +>C : Symbol(C, Decl(classDeclarationBlockScoping2.ts, 3, 5)) + + var c2 = C; +>c2 : Symbol(c2, Decl(classDeclarationBlockScoping2.ts, 5, 11)) +>C : Symbol(C, Decl(classDeclarationBlockScoping2.ts, 3, 5)) + } + return C === c1; +>C : Symbol(C, Decl(classDeclarationBlockScoping2.ts, 0, 14)) +>c1 : Symbol(c1, Decl(classDeclarationBlockScoping2.ts, 2, 7)) +} diff --git a/tests/baselines/reference/classDeclarationBlockScoping2.types b/tests/baselines/reference/classDeclarationBlockScoping2.types new file mode 100644 index 0000000000000..0431d4dd2fd9c --- /dev/null +++ b/tests/baselines/reference/classDeclarationBlockScoping2.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/classDeclarationBlockScoping2.ts === +function f() { +>f : () => boolean + + class C {} +>C : C + + var c1 = C; +>c1 : typeof C +>C : typeof C + { + class C {} +>C : C + + var c2 = C; +>c2 : typeof C +>C : typeof C + } + return C === c1; +>C === c1 : boolean +>C : typeof C +>c1 : typeof C +} diff --git a/tests/baselines/reference/classExpressionTest1.errors.txt b/tests/baselines/reference/classExpressionTest1.errors.txt deleted file mode 100644 index 4d7e1cda639c4..0000000000000 --- a/tests/baselines/reference/classExpressionTest1.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/compiler/classExpressionTest1.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - - -==== tests/cases/compiler/classExpressionTest1.ts (1 errors) ==== - function M() { - class C { - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - f() { - var t: T; - var x: X; - return { t, x }; - } - } - - var v = new C(); - return v.f(); - } \ No newline at end of file diff --git a/tests/baselines/reference/classExpressionTest1.symbols b/tests/baselines/reference/classExpressionTest1.symbols new file mode 100644 index 0000000000000..684ee3028957d --- /dev/null +++ b/tests/baselines/reference/classExpressionTest1.symbols @@ -0,0 +1,35 @@ +=== tests/cases/compiler/classExpressionTest1.ts === +function M() { +>M : Symbol(M, Decl(classExpressionTest1.ts, 0, 0)) + + class C { +>C : Symbol(C, Decl(classExpressionTest1.ts, 0, 14)) +>X : Symbol(X, Decl(classExpressionTest1.ts, 1, 12)) + + f() { +>f : Symbol(f, Decl(classExpressionTest1.ts, 1, 16)) +>T : Symbol(T, Decl(classExpressionTest1.ts, 2, 10)) + + var t: T; +>t : Symbol(t, Decl(classExpressionTest1.ts, 3, 15)) +>T : Symbol(T, Decl(classExpressionTest1.ts, 2, 10)) + + var x: X; +>x : Symbol(x, Decl(classExpressionTest1.ts, 4, 15)) +>X : Symbol(X, Decl(classExpressionTest1.ts, 1, 12)) + + return { t, x }; +>t : Symbol(t, Decl(classExpressionTest1.ts, 5, 20)) +>x : Symbol(x, Decl(classExpressionTest1.ts, 5, 23)) + } + } + + var v = new C(); +>v : Symbol(v, Decl(classExpressionTest1.ts, 9, 7)) +>C : Symbol(C, Decl(classExpressionTest1.ts, 0, 14)) + + return v.f(); +>v.f : Symbol(C.f, Decl(classExpressionTest1.ts, 1, 16)) +>v : Symbol(v, Decl(classExpressionTest1.ts, 9, 7)) +>f : Symbol(C.f, Decl(classExpressionTest1.ts, 1, 16)) +} diff --git a/tests/baselines/reference/classExpressionTest1.types b/tests/baselines/reference/classExpressionTest1.types new file mode 100644 index 0000000000000..bf1ae0f2f7d11 --- /dev/null +++ b/tests/baselines/reference/classExpressionTest1.types @@ -0,0 +1,38 @@ +=== tests/cases/compiler/classExpressionTest1.ts === +function M() { +>M : () => { t: string; x: number; } + + class C { +>C : C +>X : X + + f() { +>f : () => { t: T; x: X; } +>T : T + + var t: T; +>t : T +>T : T + + var x: X; +>x : X +>X : X + + return { t, x }; +>{ t, x } : { t: T; x: X; } +>t : T +>x : X + } + } + + var v = new C(); +>v : C +>new C() : C +>C : typeof C + + return v.f(); +>v.f() : { t: string; x: number; } +>v.f : () => { t: T; x: number; } +>v : C +>f : () => { t: T; x: number; } +} diff --git a/tests/baselines/reference/classInsideBlock.errors.txt b/tests/baselines/reference/classInsideBlock.errors.txt deleted file mode 100644 index 369e77735e25a..0000000000000 --- a/tests/baselines/reference/classInsideBlock.errors.txt +++ /dev/null @@ -1,9 +0,0 @@ -tests/cases/conformance/classes/classDeclarations/classInsideBlock.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - - -==== tests/cases/conformance/classes/classDeclarations/classInsideBlock.ts (1 errors) ==== - function foo() { - class C { } - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. - } \ No newline at end of file diff --git a/tests/baselines/reference/classInsideBlock.symbols b/tests/baselines/reference/classInsideBlock.symbols new file mode 100644 index 0000000000000..5f96dd1b75121 --- /dev/null +++ b/tests/baselines/reference/classInsideBlock.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/classes/classDeclarations/classInsideBlock.ts === +function foo() { +>foo : Symbol(foo, Decl(classInsideBlock.ts, 0, 0)) + + class C { } +>C : Symbol(C, Decl(classInsideBlock.ts, 0, 16)) +} diff --git a/tests/baselines/reference/classInsideBlock.types b/tests/baselines/reference/classInsideBlock.types new file mode 100644 index 0000000000000..7db5653c4758e --- /dev/null +++ b/tests/baselines/reference/classInsideBlock.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/classes/classDeclarations/classInsideBlock.ts === +function foo() { +>foo : () => void + + class C { } +>C : C +} diff --git a/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt b/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt index 94e246f8972b3..f6240f5e697a3 100644 --- a/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt +++ b/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt @@ -4,12 +4,11 @@ tests/cases/compiler/functionsWithModifiersInBlocks1.ts(2,25): error TS1184: An tests/cases/compiler/functionsWithModifiersInBlocks1.ts(3,4): error TS1184: Modifiers cannot appear here. tests/cases/compiler/functionsWithModifiersInBlocks1.ts(3,20): error TS2393: Duplicate function implementation. tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,4): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,12): error TS1029: 'export' modifier must precede 'declare' modifier. tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,28): error TS2393: Duplicate function implementation. tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,32): error TS1184: An implementation cannot be declared in ambient contexts. -==== tests/cases/compiler/functionsWithModifiersInBlocks1.ts (9 errors) ==== +==== tests/cases/compiler/functionsWithModifiersInBlocks1.ts (8 errors) ==== { declare function f() { } ~~~~~~~ @@ -26,8 +25,6 @@ tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,32): error TS1184: An declare export function f() { } ~~~~~~~ !!! error TS1184: Modifiers cannot appear here. - ~~~~~~ -!!! error TS1029: 'export' modifier must precede 'declare' modifier. ~ !!! error TS2393: Duplicate function implementation. ~ diff --git a/tests/baselines/reference/generatorTypeCheck39.errors.txt b/tests/baselines/reference/generatorTypeCheck39.errors.txt index e44812cef0d04..eb89fa23291a8 100644 --- a/tests/baselines/reference/generatorTypeCheck39.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck39.errors.txt @@ -1,27 +1,18 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,5): error TS1129: Statement expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,6): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,16): error TS2304: Cannot find name 'yield'. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,22): error TS1005: ',' expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(9,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,16): error TS1163: A 'yield' expression is only allowed in a generator body. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(7,13): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts (5 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts (2 errors) ==== function decorator(x: any) { return y => { }; } function* g() { @decorator(yield 0) - ~ -!!! error TS1129: Statement expected. - ~~~~~~~~~~~~~~~~~~ -!!! error TS2346: Supplied parameters do not match any signature of call target. ~~~~~ -!!! error TS2304: Cannot find name 'yield'. - ~ -!!! error TS1005: ',' expected. +!!! error TS1163: A 'yield' expression is only allowed in a generator body. class C { x = yield 0; + ~~~~~ +!!! error TS1163: A 'yield' expression is only allowed in a generator body. } - } - ~ -!!! error TS1128: Declaration or statement expected. \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck39.js b/tests/baselines/reference/generatorTypeCheck39.js index 0fbf5e2cfe691..e6d25045a7ee6 100644 --- a/tests/baselines/reference/generatorTypeCheck39.js +++ b/tests/baselines/reference/generatorTypeCheck39.js @@ -21,12 +21,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, function decorator(x) { return y => { }; } -function* g() { } -let C = class { - constructor() { - this.x = yield 0; - } -}; -C = __decorate([ - decorator(yield, 0) -], C); +function* g() { + let C = class { + constructor() { + this.x = yield 0; + } + }; + C = __decorate([ + decorator(yield 0) + ], C); +} diff --git a/tests/baselines/reference/generatorTypeCheck40.errors.txt b/tests/baselines/reference/generatorTypeCheck40.errors.txt index 4d3880ad4aa2f..9d9676e5d281e 100644 --- a/tests/baselines/reference/generatorTypeCheck40.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck40.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts(2,21): error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck40.ts (1 errors) ==== function* g() { class C extends (yield 0) { } - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. ~~~~~~~~~ !!! error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses. } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck57.errors.txt b/tests/baselines/reference/generatorTypeCheck57.errors.txt index c2fe00d736583..aa39e534d62c8 100644 --- a/tests/baselines/reference/generatorTypeCheck57.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck57.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts(3,13): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts (1 errors) ==== function* g() { class C { - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. x = yield 0; ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. diff --git a/tests/baselines/reference/generatorTypeCheck58.errors.txt b/tests/baselines/reference/generatorTypeCheck58.errors.txt index bc8ed7694108c..7407c83b34bef 100644 --- a/tests/baselines/reference/generatorTypeCheck58.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck58.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts(3,20): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts (1 errors) ==== function* g() { class C { - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. static x = yield 0; ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. diff --git a/tests/baselines/reference/generatorTypeCheck59.errors.txt b/tests/baselines/reference/generatorTypeCheck59.errors.txt index 3368b79d9915a..7f2c9b87529df 100644 --- a/tests/baselines/reference/generatorTypeCheck59.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck59.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(3,11): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts (1 errors) ==== function* g() { class C { - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. @(yield "") ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. diff --git a/tests/baselines/reference/generatorTypeCheck60.errors.txt b/tests/baselines/reference/generatorTypeCheck60.errors.txt index 39724d9ac6d1f..d8e5d640bb1ae 100644 --- a/tests/baselines/reference/generatorTypeCheck60.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck60.errors.txt @@ -1,12 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,21): error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts (2 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts (1 errors) ==== function* g() { class C extends (yield) {}; - ~ -!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration. ~~~~~~~ !!! error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses. } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck61.errors.txt b/tests/baselines/reference/generatorTypeCheck61.errors.txt index 3c9f3819d61f3..87e844dbfb673 100644 --- a/tests/baselines/reference/generatorTypeCheck61.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck61.errors.txt @@ -1,22 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,5): error TS1129: Statement expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,12): error TS1146: Declaration expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,13): error TS1005: ')' expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,14): error TS1005: ';' expected. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(4,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,7): error TS1163: A 'yield' expression is only allowed in a generator body. -==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts (5 errors) ==== +==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts (1 errors) ==== function * g() { @(yield 0) - ~ -!!! error TS1129: Statement expected. - -!!! error TS1146: Declaration expected. - ~ -!!! error TS1005: ')' expected. - ~ -!!! error TS1005: ';' expected. + ~~~~~ +!!! error TS1163: A 'yield' expression is only allowed in a generator body. class C {}; - } - ~ -!!! error TS1128: Declaration or statement expected. \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck61.js b/tests/baselines/reference/generatorTypeCheck61.js index 591e52f269e5e..9e2f067f9fb59 100644 --- a/tests/baselines/reference/generatorTypeCheck61.js +++ b/tests/baselines/reference/generatorTypeCheck61.js @@ -5,8 +5,19 @@ function * g() { } //// [generatorTypeCheck61.js] -function* g() { } -0; -class C { +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); + switch (arguments.length) { + case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); + case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); + case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); + } +}; +function* g() { + let C = class { + }; + C = __decorate([ + (yield 0) + ], C); + ; } -; diff --git a/tests/baselines/reference/localTypes1.js b/tests/baselines/reference/localTypes1.js new file mode 100644 index 0000000000000..d1c3758920e66 --- /dev/null +++ b/tests/baselines/reference/localTypes1.js @@ -0,0 +1,325 @@ +//// [localTypes1.ts] + +function f1() { + enum E { + A, B, C + } + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; +} + +function f2() { + function g() { + enum E { + A, B, C + } + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; + } + return g(); +} + +function f3(b: boolean) { + if (true) { + enum E { + A, B, C + } + if (b) { + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; + } + else { + class A { + x: E; + } + interface J { + x: E; + } + type C = J[]; + let c: C = [new A()]; + c[0].x = E.B; + return c; + } + } +} + +function f5() { + var z1 = function () { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } + var z2 = () => { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } +} + +class A { + constructor() { + enum E { + A, B, C + } + class C { + x: E; + } + } + m() { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } + get p() { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } +} + +function f6() { + class A { + a: string; + } + function g() { + class B extends A { + b: string; + } + function h() { + class C extends B { + c: string; + } + var x = new C(); + x.a = "a"; + x.b = "b"; + x.c = "c"; + return x; + } + return h(); + } + return g(); +} + + +//// [localTypes1.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +function f1() { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + var a = [new C()]; + a[0].x = E.B; + return a; +} +function f2() { + function g() { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + var a = [new C()]; + a[0].x = E.B; + return a; + } + return g(); +} +function f3(b) { + if (true) { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + if (b) { + var C = (function () { + function C() { + } + return C; + })(); + var a = [new C()]; + a[0].x = E.B; + return a; + } + else { + var A = (function () { + function A() { + } + return A; + })(); + var c = [new A()]; + c[0].x = E.B; + return c; + } + } +} +function f5() { + var z1 = function () { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + return new C(); + }; + var z2 = function () { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + return new C(); + }; +} +var A = (function () { + function A() { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + } + A.prototype.m = function () { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + return new C(); + }; + Object.defineProperty(A.prototype, "p", { + get: function () { + var E; + (function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; + })(E || (E = {})); + var C = (function () { + function C() { + } + return C; + })(); + return new C(); + }, + enumerable: true, + configurable: true + }); + return A; +})(); +function f6() { + var A = (function () { + function A() { + } + return A; + })(); + function g() { + var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + return B; + })(A); + function h() { + var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + return C; + })(B); + var x = new C(); + x.a = "a"; + x.b = "b"; + x.c = "c"; + return x; + } + return h(); + } + return g(); +} diff --git a/tests/baselines/reference/localTypes1.symbols b/tests/baselines/reference/localTypes1.symbols new file mode 100644 index 0000000000000..53d4191ae6197 --- /dev/null +++ b/tests/baselines/reference/localTypes1.symbols @@ -0,0 +1,357 @@ +=== tests/cases/conformance/types/localTypes/localTypes1.ts === + +function f1() { +>f1 : Symbol(f1, Decl(localTypes1.ts, 0, 0)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 1, 15)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 2, 12)) +>B : Symbol(E.B, Decl(localTypes1.ts, 3, 10)) +>C : Symbol(E.C, Decl(localTypes1.ts, 3, 13)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 4, 5)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 5, 13)) +>E : Symbol(E, Decl(localTypes1.ts, 1, 15)) + } + interface I { +>I : Symbol(I, Decl(localTypes1.ts, 7, 5)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 8, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 1, 15)) + } + type A = I[]; +>A : Symbol(A, Decl(localTypes1.ts, 10, 5)) +>I : Symbol(I, Decl(localTypes1.ts, 7, 5)) + + let a: A = [new C()]; +>a : Symbol(a, Decl(localTypes1.ts, 12, 7)) +>A : Symbol(A, Decl(localTypes1.ts, 10, 5)) +>C : Symbol(C, Decl(localTypes1.ts, 4, 5)) + + a[0].x = E.B; +>a[0].x : Symbol(I.x, Decl(localTypes1.ts, 8, 17)) +>a : Symbol(a, Decl(localTypes1.ts, 12, 7)) +>x : Symbol(I.x, Decl(localTypes1.ts, 8, 17)) +>E.B : Symbol(E.B, Decl(localTypes1.ts, 3, 10)) +>E : Symbol(E, Decl(localTypes1.ts, 1, 15)) +>B : Symbol(E.B, Decl(localTypes1.ts, 3, 10)) + + return a; +>a : Symbol(a, Decl(localTypes1.ts, 12, 7)) +} + +function f2() { +>f2 : Symbol(f2, Decl(localTypes1.ts, 15, 1)) + + function g() { +>g : Symbol(g, Decl(localTypes1.ts, 17, 15)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 18, 18)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 19, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 20, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 20, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 21, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 22, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 18, 18)) + } + interface I { +>I : Symbol(I, Decl(localTypes1.ts, 24, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 25, 21)) +>E : Symbol(E, Decl(localTypes1.ts, 18, 18)) + } + type A = I[]; +>A : Symbol(A, Decl(localTypes1.ts, 27, 9)) +>I : Symbol(I, Decl(localTypes1.ts, 24, 9)) + + let a: A = [new C()]; +>a : Symbol(a, Decl(localTypes1.ts, 29, 11)) +>A : Symbol(A, Decl(localTypes1.ts, 27, 9)) +>C : Symbol(C, Decl(localTypes1.ts, 21, 9)) + + a[0].x = E.B; +>a[0].x : Symbol(I.x, Decl(localTypes1.ts, 25, 21)) +>a : Symbol(a, Decl(localTypes1.ts, 29, 11)) +>x : Symbol(I.x, Decl(localTypes1.ts, 25, 21)) +>E.B : Symbol(E.B, Decl(localTypes1.ts, 20, 14)) +>E : Symbol(E, Decl(localTypes1.ts, 18, 18)) +>B : Symbol(E.B, Decl(localTypes1.ts, 20, 14)) + + return a; +>a : Symbol(a, Decl(localTypes1.ts, 29, 11)) + } + return g(); +>g : Symbol(g, Decl(localTypes1.ts, 17, 15)) +} + +function f3(b: boolean) { +>f3 : Symbol(f3, Decl(localTypes1.ts, 34, 1)) +>b : Symbol(b, Decl(localTypes1.ts, 36, 12)) + + if (true) { + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 38, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 39, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 39, 17)) + } + if (b) { +>b : Symbol(b, Decl(localTypes1.ts, 36, 12)) + + class C { +>C : Symbol(C, Decl(localTypes1.ts, 41, 16)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 42, 21)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) + } + interface I { +>I : Symbol(I, Decl(localTypes1.ts, 44, 13)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 45, 25)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) + } + type A = I[]; +>A : Symbol(A, Decl(localTypes1.ts, 47, 13)) +>I : Symbol(I, Decl(localTypes1.ts, 44, 13)) + + let a: A = [new C()]; +>a : Symbol(a, Decl(localTypes1.ts, 49, 15)) +>A : Symbol(A, Decl(localTypes1.ts, 47, 13)) +>C : Symbol(C, Decl(localTypes1.ts, 41, 16)) + + a[0].x = E.B; +>a[0].x : Symbol(I.x, Decl(localTypes1.ts, 45, 25)) +>a : Symbol(a, Decl(localTypes1.ts, 49, 15)) +>x : Symbol(I.x, Decl(localTypes1.ts, 45, 25)) +>E.B : Symbol(E.B, Decl(localTypes1.ts, 39, 14)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) +>B : Symbol(E.B, Decl(localTypes1.ts, 39, 14)) + + return a; +>a : Symbol(a, Decl(localTypes1.ts, 49, 15)) + } + else { + class A { +>A : Symbol(A, Decl(localTypes1.ts, 53, 14)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 54, 21)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) + } + interface J { +>J : Symbol(J, Decl(localTypes1.ts, 56, 13)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 57, 25)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) + } + type C = J[]; +>C : Symbol(C, Decl(localTypes1.ts, 59, 13)) +>J : Symbol(J, Decl(localTypes1.ts, 56, 13)) + + let c: C = [new A()]; +>c : Symbol(c, Decl(localTypes1.ts, 61, 15)) +>C : Symbol(C, Decl(localTypes1.ts, 59, 13)) +>A : Symbol(A, Decl(localTypes1.ts, 53, 14)) + + c[0].x = E.B; +>c[0].x : Symbol(J.x, Decl(localTypes1.ts, 57, 25)) +>c : Symbol(c, Decl(localTypes1.ts, 61, 15)) +>x : Symbol(J.x, Decl(localTypes1.ts, 57, 25)) +>E.B : Symbol(E.B, Decl(localTypes1.ts, 39, 14)) +>E : Symbol(E, Decl(localTypes1.ts, 37, 15)) +>B : Symbol(E.B, Decl(localTypes1.ts, 39, 14)) + + return c; +>c : Symbol(c, Decl(localTypes1.ts, 61, 15)) + } + } +} + +function f5() { +>f5 : Symbol(f5, Decl(localTypes1.ts, 66, 1)) + + var z1 = function () { +>z1 : Symbol(z1, Decl(localTypes1.ts, 69, 7)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 69, 26)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 70, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 71, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 71, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 72, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 73, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 69, 26)) + } + return new C(); +>C : Symbol(C, Decl(localTypes1.ts, 72, 9)) + } + var z2 = () => { +>z2 : Symbol(z2, Decl(localTypes1.ts, 78, 7)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 78, 20)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 79, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 80, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 80, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 81, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 82, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 78, 20)) + } + return new C(); +>C : Symbol(C, Decl(localTypes1.ts, 81, 9)) + } +} + +class A { +>A : Symbol(A, Decl(localTypes1.ts, 87, 1)) + + constructor() { + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 90, 19)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 91, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 92, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 92, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 93, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 94, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 90, 19)) + } + } + m() { +>m : Symbol(m, Decl(localTypes1.ts, 97, 5)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 98, 9)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 99, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 100, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 100, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 101, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 102, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 98, 9)) + } + return new C(); +>C : Symbol(C, Decl(localTypes1.ts, 101, 9)) + } + get p() { +>p : Symbol(p, Decl(localTypes1.ts, 106, 5)) + + enum E { +>E : Symbol(E, Decl(localTypes1.ts, 107, 13)) + + A, B, C +>A : Symbol(E.A, Decl(localTypes1.ts, 108, 16)) +>B : Symbol(E.B, Decl(localTypes1.ts, 109, 14)) +>C : Symbol(E.C, Decl(localTypes1.ts, 109, 17)) + } + class C { +>C : Symbol(C, Decl(localTypes1.ts, 110, 9)) + + x: E; +>x : Symbol(x, Decl(localTypes1.ts, 111, 17)) +>E : Symbol(E, Decl(localTypes1.ts, 107, 13)) + } + return new C(); +>C : Symbol(C, Decl(localTypes1.ts, 110, 9)) + } +} + +function f6() { +>f6 : Symbol(f6, Decl(localTypes1.ts, 116, 1)) + + class A { +>A : Symbol(A, Decl(localTypes1.ts, 118, 15)) + + a: string; +>a : Symbol(a, Decl(localTypes1.ts, 119, 13)) + } + function g() { +>g : Symbol(g, Decl(localTypes1.ts, 121, 5)) + + class B extends A { +>B : Symbol(B, Decl(localTypes1.ts, 122, 18)) +>A : Symbol(A, Decl(localTypes1.ts, 118, 15)) + + b: string; +>b : Symbol(b, Decl(localTypes1.ts, 123, 27)) + } + function h() { +>h : Symbol(h, Decl(localTypes1.ts, 125, 9)) + + class C extends B { +>C : Symbol(C, Decl(localTypes1.ts, 126, 22)) +>B : Symbol(B, Decl(localTypes1.ts, 122, 18)) + + c: string; +>c : Symbol(c, Decl(localTypes1.ts, 127, 31)) + } + var x = new C(); +>x : Symbol(x, Decl(localTypes1.ts, 130, 15)) +>C : Symbol(C, Decl(localTypes1.ts, 126, 22)) + + x.a = "a"; +>x.a : Symbol(A.a, Decl(localTypes1.ts, 119, 13)) +>x : Symbol(x, Decl(localTypes1.ts, 130, 15)) +>a : Symbol(A.a, Decl(localTypes1.ts, 119, 13)) + + x.b = "b"; +>x.b : Symbol(B.b, Decl(localTypes1.ts, 123, 27)) +>x : Symbol(x, Decl(localTypes1.ts, 130, 15)) +>b : Symbol(B.b, Decl(localTypes1.ts, 123, 27)) + + x.c = "c"; +>x.c : Symbol(C.c, Decl(localTypes1.ts, 127, 31)) +>x : Symbol(x, Decl(localTypes1.ts, 130, 15)) +>c : Symbol(C.c, Decl(localTypes1.ts, 127, 31)) + + return x; +>x : Symbol(x, Decl(localTypes1.ts, 130, 15)) + } + return h(); +>h : Symbol(h, Decl(localTypes1.ts, 125, 9)) + } + return g(); +>g : Symbol(g, Decl(localTypes1.ts, 121, 5)) +} + diff --git a/tests/baselines/reference/localTypes1.types b/tests/baselines/reference/localTypes1.types new file mode 100644 index 0000000000000..1770a36edb7cc --- /dev/null +++ b/tests/baselines/reference/localTypes1.types @@ -0,0 +1,395 @@ +=== tests/cases/conformance/types/localTypes/localTypes1.ts === + +function f1() { +>f1 : () => I[] + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + interface I { +>I : I + + x: E; +>x : E +>E : E + } + type A = I[]; +>A : I[] +>I : I + + let a: A = [new C()]; +>a : I[] +>A : I[] +>[new C()] : C[] +>new C() : C +>C : typeof C + + a[0].x = E.B; +>a[0].x = E.B : E +>a[0].x : E +>a[0] : I +>a : I[] +>0 : number +>x : E +>E.B : E +>E : typeof E +>B : E + + return a; +>a : I[] +} + +function f2() { +>f2 : () => I[] + + function g() { +>g : () => I[] + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + interface I { +>I : I + + x: E; +>x : E +>E : E + } + type A = I[]; +>A : I[] +>I : I + + let a: A = [new C()]; +>a : I[] +>A : I[] +>[new C()] : C[] +>new C() : C +>C : typeof C + + a[0].x = E.B; +>a[0].x = E.B : E +>a[0].x : E +>a[0] : I +>a : I[] +>0 : number +>x : E +>E.B : E +>E : typeof E +>B : E + + return a; +>a : I[] + } + return g(); +>g() : I[] +>g : () => I[] +} + +function f3(b: boolean) { +>f3 : (b: boolean) => I[] +>b : boolean + + if (true) { +>true : boolean + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + if (b) { +>b : boolean + + class C { +>C : C + + x: E; +>x : E +>E : E + } + interface I { +>I : I + + x: E; +>x : E +>E : E + } + type A = I[]; +>A : I[] +>I : I + + let a: A = [new C()]; +>a : I[] +>A : I[] +>[new C()] : C[] +>new C() : C +>C : typeof C + + a[0].x = E.B; +>a[0].x = E.B : E +>a[0].x : E +>a[0] : I +>a : I[] +>0 : number +>x : E +>E.B : E +>E : typeof E +>B : E + + return a; +>a : I[] + } + else { + class A { +>A : A + + x: E; +>x : E +>E : E + } + interface J { +>J : J + + x: E; +>x : E +>E : E + } + type C = J[]; +>C : J[] +>J : J + + let c: C = [new A()]; +>c : J[] +>C : J[] +>[new A()] : A[] +>new A() : A +>A : typeof A + + c[0].x = E.B; +>c[0].x = E.B : E +>c[0].x : E +>c[0] : J +>c : J[] +>0 : number +>x : E +>E.B : E +>E : typeof E +>B : E + + return c; +>c : J[] + } + } +} + +function f5() { +>f5 : () => void + + var z1 = function () { +>z1 : () => C +>function () { enum E { A, B, C } class C { x: E; } return new C(); } : () => C + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + return new C(); +>new C() : C +>C : typeof C + } + var z2 = () => { +>z2 : () => C +>() => { enum E { A, B, C } class C { x: E; } return new C(); } : () => C + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + return new C(); +>new C() : C +>C : typeof C + } +} + +class A { +>A : A + + constructor() { + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + } + m() { +>m : () => C + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + return new C(); +>new C() : C +>C : typeof C + } + get p() { +>p : C + + enum E { +>E : E + + A, B, C +>A : E +>B : E +>C : E + } + class C { +>C : C + + x: E; +>x : E +>E : E + } + return new C(); +>new C() : C +>C : typeof C + } +} + +function f6() { +>f6 : () => C + + class A { +>A : A + + a: string; +>a : string + } + function g() { +>g : () => C + + class B extends A { +>B : B +>A : A + + b: string; +>b : string + } + function h() { +>h : () => C + + class C extends B { +>C : C +>B : B + + c: string; +>c : string + } + var x = new C(); +>x : C +>new C() : C +>C : typeof C + + x.a = "a"; +>x.a = "a" : string +>x.a : string +>x : C +>a : string +>"a" : string + + x.b = "b"; +>x.b = "b" : string +>x.b : string +>x : C +>b : string +>"b" : string + + x.c = "c"; +>x.c = "c" : string +>x.c : string +>x : C +>c : string +>"c" : string + + return x; +>x : C + } + return h(); +>h() : C +>h : () => C + } + return g(); +>g() : C +>g : () => C +} + diff --git a/tests/baselines/reference/localTypes2.js b/tests/baselines/reference/localTypes2.js new file mode 100644 index 0000000000000..a95844f0794ab --- /dev/null +++ b/tests/baselines/reference/localTypes2.js @@ -0,0 +1,92 @@ +//// [localTypes2.ts] +function f1() { + function f() { + class C { + constructor(public x: number, public y: number) { } + } + return C; + } + let C = f(); + let v = new C(10, 20); + let x = v.x; + let y = v.y; +} + +function f2() { + function f(x: number) { + class C { + public x = x; + constructor(public y: number) { } + } + return C; + } + let C = f(10); + let v = new C(20); + let x = v.x; + let y = v.y; +} + +function f3() { + function f(x: number, y: number) { + class C { + public x = x; + public y = y; + } + return C; + } + let C = f(10, 20); + let v = new C(); + let x = v.x; + let y = v.y; +} + + +//// [localTypes2.js] +function f1() { + function f() { + var C = (function () { + function C(x, y) { + this.x = x; + this.y = y; + } + return C; + })(); + return C; + } + var C = f(); + var v = new C(10, 20); + var x = v.x; + var y = v.y; +} +function f2() { + function f(x) { + var C = (function () { + function C(y) { + this.y = y; + this.x = x; + } + return C; + })(); + return C; + } + var C = f(10); + var v = new C(20); + var x = v.x; + var y = v.y; +} +function f3() { + function f(x, y) { + var C = (function () { + function C() { + this.x = x; + this.y = y; + } + return C; + })(); + return C; + } + var C = f(10, 20); + var v = new C(); + var x = v.x; + var y = v.y; +} diff --git a/tests/baselines/reference/localTypes2.symbols b/tests/baselines/reference/localTypes2.symbols new file mode 100644 index 0000000000000..3054c6f552d1c --- /dev/null +++ b/tests/baselines/reference/localTypes2.symbols @@ -0,0 +1,122 @@ +=== tests/cases/conformance/types/localTypes/localTypes2.ts === +function f1() { +>f1 : Symbol(f1, Decl(localTypes2.ts, 0, 0)) + + function f() { +>f : Symbol(f, Decl(localTypes2.ts, 0, 15)) + + class C { +>C : Symbol(C, Decl(localTypes2.ts, 1, 18)) + + constructor(public x: number, public y: number) { } +>x : Symbol(x, Decl(localTypes2.ts, 3, 24)) +>y : Symbol(y, Decl(localTypes2.ts, 3, 41)) + } + return C; +>C : Symbol(C, Decl(localTypes2.ts, 1, 18)) + } + let C = f(); +>C : Symbol(C, Decl(localTypes2.ts, 7, 7)) +>f : Symbol(f, Decl(localTypes2.ts, 0, 15)) + + let v = new C(10, 20); +>v : Symbol(v, Decl(localTypes2.ts, 8, 7)) +>C : Symbol(C, Decl(localTypes2.ts, 7, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes2.ts, 9, 7)) +>v.x : Symbol(C.x, Decl(localTypes2.ts, 3, 24)) +>v : Symbol(v, Decl(localTypes2.ts, 8, 7)) +>x : Symbol(C.x, Decl(localTypes2.ts, 3, 24)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes2.ts, 10, 7)) +>v.y : Symbol(C.y, Decl(localTypes2.ts, 3, 41)) +>v : Symbol(v, Decl(localTypes2.ts, 8, 7)) +>y : Symbol(C.y, Decl(localTypes2.ts, 3, 41)) +} + +function f2() { +>f2 : Symbol(f2, Decl(localTypes2.ts, 11, 1)) + + function f(x: number) { +>f : Symbol(f, Decl(localTypes2.ts, 13, 15)) +>x : Symbol(x, Decl(localTypes2.ts, 14, 15)) + + class C { +>C : Symbol(C, Decl(localTypes2.ts, 14, 27)) + + public x = x; +>x : Symbol(x, Decl(localTypes2.ts, 15, 17)) +>x : Symbol(x, Decl(localTypes2.ts, 14, 15)) + + constructor(public y: number) { } +>y : Symbol(y, Decl(localTypes2.ts, 17, 24)) + } + return C; +>C : Symbol(C, Decl(localTypes2.ts, 14, 27)) + } + let C = f(10); +>C : Symbol(C, Decl(localTypes2.ts, 21, 7)) +>f : Symbol(f, Decl(localTypes2.ts, 13, 15)) + + let v = new C(20); +>v : Symbol(v, Decl(localTypes2.ts, 22, 7)) +>C : Symbol(C, Decl(localTypes2.ts, 21, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes2.ts, 23, 7)) +>v.x : Symbol(C.x, Decl(localTypes2.ts, 15, 17)) +>v : Symbol(v, Decl(localTypes2.ts, 22, 7)) +>x : Symbol(C.x, Decl(localTypes2.ts, 15, 17)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes2.ts, 24, 7)) +>v.y : Symbol(C.y, Decl(localTypes2.ts, 17, 24)) +>v : Symbol(v, Decl(localTypes2.ts, 22, 7)) +>y : Symbol(C.y, Decl(localTypes2.ts, 17, 24)) +} + +function f3() { +>f3 : Symbol(f3, Decl(localTypes2.ts, 25, 1)) + + function f(x: number, y: number) { +>f : Symbol(f, Decl(localTypes2.ts, 27, 15)) +>x : Symbol(x, Decl(localTypes2.ts, 28, 15)) +>y : Symbol(y, Decl(localTypes2.ts, 28, 25)) + + class C { +>C : Symbol(C, Decl(localTypes2.ts, 28, 38)) + + public x = x; +>x : Symbol(x, Decl(localTypes2.ts, 29, 17)) +>x : Symbol(x, Decl(localTypes2.ts, 28, 15)) + + public y = y; +>y : Symbol(y, Decl(localTypes2.ts, 30, 25)) +>y : Symbol(y, Decl(localTypes2.ts, 28, 25)) + } + return C; +>C : Symbol(C, Decl(localTypes2.ts, 28, 38)) + } + let C = f(10, 20); +>C : Symbol(C, Decl(localTypes2.ts, 35, 7)) +>f : Symbol(f, Decl(localTypes2.ts, 27, 15)) + + let v = new C(); +>v : Symbol(v, Decl(localTypes2.ts, 36, 7)) +>C : Symbol(C, Decl(localTypes2.ts, 35, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes2.ts, 37, 7)) +>v.x : Symbol(C.x, Decl(localTypes2.ts, 29, 17)) +>v : Symbol(v, Decl(localTypes2.ts, 36, 7)) +>x : Symbol(C.x, Decl(localTypes2.ts, 29, 17)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes2.ts, 38, 7)) +>v.y : Symbol(C.y, Decl(localTypes2.ts, 30, 25)) +>v : Symbol(v, Decl(localTypes2.ts, 36, 7)) +>y : Symbol(C.y, Decl(localTypes2.ts, 30, 25)) +} + diff --git a/tests/baselines/reference/localTypes2.types b/tests/baselines/reference/localTypes2.types new file mode 100644 index 0000000000000..a6b85b7bb144e --- /dev/null +++ b/tests/baselines/reference/localTypes2.types @@ -0,0 +1,134 @@ +=== tests/cases/conformance/types/localTypes/localTypes2.ts === +function f1() { +>f1 : () => void + + function f() { +>f : () => typeof C + + class C { +>C : C + + constructor(public x: number, public y: number) { } +>x : number +>y : number + } + return C; +>C : typeof C + } + let C = f(); +>C : typeof C +>f() : typeof C +>f : () => typeof C + + let v = new C(10, 20); +>v : C +>new C(10, 20) : C +>C : typeof C +>10 : number +>20 : number + + let x = v.x; +>x : number +>v.x : number +>v : C +>x : number + + let y = v.y; +>y : number +>v.y : number +>v : C +>y : number +} + +function f2() { +>f2 : () => void + + function f(x: number) { +>f : (x: number) => typeof C +>x : number + + class C { +>C : C + + public x = x; +>x : number +>x : number + + constructor(public y: number) { } +>y : number + } + return C; +>C : typeof C + } + let C = f(10); +>C : typeof C +>f(10) : typeof C +>f : (x: number) => typeof C +>10 : number + + let v = new C(20); +>v : C +>new C(20) : C +>C : typeof C +>20 : number + + let x = v.x; +>x : number +>v.x : number +>v : C +>x : number + + let y = v.y; +>y : number +>v.y : number +>v : C +>y : number +} + +function f3() { +>f3 : () => void + + function f(x: number, y: number) { +>f : (x: number, y: number) => typeof C +>x : number +>y : number + + class C { +>C : C + + public x = x; +>x : number +>x : number + + public y = y; +>y : number +>y : number + } + return C; +>C : typeof C + } + let C = f(10, 20); +>C : typeof C +>f(10, 20) : typeof C +>f : (x: number, y: number) => typeof C +>10 : number +>20 : number + + let v = new C(); +>v : C +>new C() : C +>C : typeof C + + let x = v.x; +>x : number +>v.x : number +>v : C +>x : number + + let y = v.y; +>y : number +>v.y : number +>v : C +>y : number +} + diff --git a/tests/baselines/reference/localTypes3.js b/tests/baselines/reference/localTypes3.js new file mode 100644 index 0000000000000..2d40bc922b94b --- /dev/null +++ b/tests/baselines/reference/localTypes3.js @@ -0,0 +1,92 @@ +//// [localTypes3.ts] +function f1() { + function f() { + class C { + constructor(public x: X, public y: Y) { } + } + return C; + } + let C = f(); + let v = new C(10, "hello"); + let x = v.x; + let y = v.y; +} + +function f2() { + function f(x: X) { + class C { + public x = x; + constructor(public y: Y) { } + } + return C; + } + let C = f(10); + let v = new C("hello"); + let x = v.x; + let y = v.y; +} + +function f3() { + function f(x: X, y: Y) { + class C { + public x = x; + public y = y; + } + return C; + } + let C = f(10, "hello"); + let v = new C(); + let x = v.x; + let y = v.y; +} + + +//// [localTypes3.js] +function f1() { + function f() { + var C = (function () { + function C(x, y) { + this.x = x; + this.y = y; + } + return C; + })(); + return C; + } + var C = f(); + var v = new C(10, "hello"); + var x = v.x; + var y = v.y; +} +function f2() { + function f(x) { + var C = (function () { + function C(y) { + this.y = y; + this.x = x; + } + return C; + })(); + return C; + } + var C = f(10); + var v = new C("hello"); + var x = v.x; + var y = v.y; +} +function f3() { + function f(x, y) { + var C = (function () { + function C() { + this.x = x; + this.y = y; + } + return C; + })(); + return C; + } + var C = f(10, "hello"); + var v = new C(); + var x = v.x; + var y = v.y; +} diff --git a/tests/baselines/reference/localTypes3.symbols b/tests/baselines/reference/localTypes3.symbols new file mode 100644 index 0000000000000..fe7082e457754 --- /dev/null +++ b/tests/baselines/reference/localTypes3.symbols @@ -0,0 +1,134 @@ +=== tests/cases/conformance/types/localTypes/localTypes3.ts === +function f1() { +>f1 : Symbol(f1, Decl(localTypes3.ts, 0, 0)) + + function f() { +>f : Symbol(f, Decl(localTypes3.ts, 0, 15)) + + class C { +>C : Symbol(C, Decl(localTypes3.ts, 1, 18)) +>X : Symbol(X, Decl(localTypes3.ts, 2, 16)) +>Y : Symbol(Y, Decl(localTypes3.ts, 2, 18)) + + constructor(public x: X, public y: Y) { } +>x : Symbol(x, Decl(localTypes3.ts, 3, 24)) +>X : Symbol(X, Decl(localTypes3.ts, 2, 16)) +>y : Symbol(y, Decl(localTypes3.ts, 3, 36)) +>Y : Symbol(Y, Decl(localTypes3.ts, 2, 18)) + } + return C; +>C : Symbol(C, Decl(localTypes3.ts, 1, 18)) + } + let C = f(); +>C : Symbol(C, Decl(localTypes3.ts, 7, 7)) +>f : Symbol(f, Decl(localTypes3.ts, 0, 15)) + + let v = new C(10, "hello"); +>v : Symbol(v, Decl(localTypes3.ts, 8, 7)) +>C : Symbol(C, Decl(localTypes3.ts, 7, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes3.ts, 9, 7)) +>v.x : Symbol(C.x, Decl(localTypes3.ts, 3, 24)) +>v : Symbol(v, Decl(localTypes3.ts, 8, 7)) +>x : Symbol(C.x, Decl(localTypes3.ts, 3, 24)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes3.ts, 10, 7)) +>v.y : Symbol(C.y, Decl(localTypes3.ts, 3, 36)) +>v : Symbol(v, Decl(localTypes3.ts, 8, 7)) +>y : Symbol(C.y, Decl(localTypes3.ts, 3, 36)) +} + +function f2() { +>f2 : Symbol(f2, Decl(localTypes3.ts, 11, 1)) + + function f(x: X) { +>f : Symbol(f, Decl(localTypes3.ts, 13, 15)) +>X : Symbol(X, Decl(localTypes3.ts, 14, 15)) +>x : Symbol(x, Decl(localTypes3.ts, 14, 18)) +>X : Symbol(X, Decl(localTypes3.ts, 14, 15)) + + class C { +>C : Symbol(C, Decl(localTypes3.ts, 14, 25)) +>Y : Symbol(Y, Decl(localTypes3.ts, 15, 16)) + + public x = x; +>x : Symbol(x, Decl(localTypes3.ts, 15, 20)) +>x : Symbol(x, Decl(localTypes3.ts, 14, 18)) + + constructor(public y: Y) { } +>y : Symbol(y, Decl(localTypes3.ts, 17, 24)) +>Y : Symbol(Y, Decl(localTypes3.ts, 15, 16)) + } + return C; +>C : Symbol(C, Decl(localTypes3.ts, 14, 25)) + } + let C = f(10); +>C : Symbol(C, Decl(localTypes3.ts, 21, 7)) +>f : Symbol(f, Decl(localTypes3.ts, 13, 15)) + + let v = new C("hello"); +>v : Symbol(v, Decl(localTypes3.ts, 22, 7)) +>C : Symbol(C, Decl(localTypes3.ts, 21, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes3.ts, 23, 7)) +>v.x : Symbol(C.x, Decl(localTypes3.ts, 15, 20)) +>v : Symbol(v, Decl(localTypes3.ts, 22, 7)) +>x : Symbol(C.x, Decl(localTypes3.ts, 15, 20)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes3.ts, 24, 7)) +>v.y : Symbol(C.y, Decl(localTypes3.ts, 17, 24)) +>v : Symbol(v, Decl(localTypes3.ts, 22, 7)) +>y : Symbol(C.y, Decl(localTypes3.ts, 17, 24)) +} + +function f3() { +>f3 : Symbol(f3, Decl(localTypes3.ts, 25, 1)) + + function f(x: X, y: Y) { +>f : Symbol(f, Decl(localTypes3.ts, 27, 15)) +>X : Symbol(X, Decl(localTypes3.ts, 28, 15)) +>Y : Symbol(Y, Decl(localTypes3.ts, 28, 17)) +>x : Symbol(x, Decl(localTypes3.ts, 28, 21)) +>X : Symbol(X, Decl(localTypes3.ts, 28, 15)) +>y : Symbol(y, Decl(localTypes3.ts, 28, 26)) +>Y : Symbol(Y, Decl(localTypes3.ts, 28, 17)) + + class C { +>C : Symbol(C, Decl(localTypes3.ts, 28, 34)) + + public x = x; +>x : Symbol(x, Decl(localTypes3.ts, 29, 17)) +>x : Symbol(x, Decl(localTypes3.ts, 28, 21)) + + public y = y; +>y : Symbol(y, Decl(localTypes3.ts, 30, 25)) +>y : Symbol(y, Decl(localTypes3.ts, 28, 26)) + } + return C; +>C : Symbol(C, Decl(localTypes3.ts, 28, 34)) + } + let C = f(10, "hello"); +>C : Symbol(C, Decl(localTypes3.ts, 35, 7)) +>f : Symbol(f, Decl(localTypes3.ts, 27, 15)) + + let v = new C(); +>v : Symbol(v, Decl(localTypes3.ts, 36, 7)) +>C : Symbol(C, Decl(localTypes3.ts, 35, 7)) + + let x = v.x; +>x : Symbol(x, Decl(localTypes3.ts, 37, 7)) +>v.x : Symbol(C.x, Decl(localTypes3.ts, 29, 17)) +>v : Symbol(v, Decl(localTypes3.ts, 36, 7)) +>x : Symbol(C.x, Decl(localTypes3.ts, 29, 17)) + + let y = v.y; +>y : Symbol(y, Decl(localTypes3.ts, 38, 7)) +>v.y : Symbol(C.y, Decl(localTypes3.ts, 30, 25)) +>v : Symbol(v, Decl(localTypes3.ts, 36, 7)) +>y : Symbol(C.y, Decl(localTypes3.ts, 30, 25)) +} + diff --git a/tests/baselines/reference/localTypes3.types b/tests/baselines/reference/localTypes3.types new file mode 100644 index 0000000000000..551096468c57f --- /dev/null +++ b/tests/baselines/reference/localTypes3.types @@ -0,0 +1,146 @@ +=== tests/cases/conformance/types/localTypes/localTypes3.ts === +function f1() { +>f1 : () => void + + function f() { +>f : () => typeof C + + class C { +>C : C +>X : X +>Y : Y + + constructor(public x: X, public y: Y) { } +>x : X +>X : X +>y : Y +>Y : Y + } + return C; +>C : typeof C + } + let C = f(); +>C : typeof C +>f() : typeof C +>f : () => typeof C + + let v = new C(10, "hello"); +>v : C +>new C(10, "hello") : C +>C : typeof C +>10 : number +>"hello" : string + + let x = v.x; +>x : number +>v.x : number +>v : C +>x : number + + let y = v.y; +>y : string +>v.y : string +>v : C +>y : string +} + +function f2() { +>f2 : () => void + + function f(x: X) { +>f : (x: X) => typeof C +>X : X +>x : X +>X : X + + class C { +>C : C +>Y : Y + + public x = x; +>x : X +>x : X + + constructor(public y: Y) { } +>y : Y +>Y : Y + } + return C; +>C : typeof C + } + let C = f(10); +>C : typeof C +>f(10) : typeof C +>f : (x: X) => typeof C +>10 : number + + let v = new C("hello"); +>v : f.C +>new C("hello") : f.C +>C : typeof C +>"hello" : string + + let x = v.x; +>x : number +>v.x : number +>v : f.C +>x : number + + let y = v.y; +>y : string +>v.y : string +>v : f.C +>y : string +} + +function f3() { +>f3 : () => void + + function f(x: X, y: Y) { +>f : (x: X, y: Y) => typeof C +>X : X +>Y : Y +>x : X +>X : X +>y : Y +>Y : Y + + class C { +>C : C + + public x = x; +>x : X +>x : X + + public y = y; +>y : Y +>y : Y + } + return C; +>C : typeof C + } + let C = f(10, "hello"); +>C : typeof C +>f(10, "hello") : typeof C +>f : (x: X, y: Y) => typeof C +>10 : number +>"hello" : string + + let v = new C(); +>v : f.C +>new C() : f.C +>C : typeof C + + let x = v.x; +>x : number +>v.x : number +>v : f.C +>x : number + + let y = v.y; +>y : string +>v.y : string +>v : f.C +>y : string +} + diff --git a/tests/baselines/reference/localTypes4.errors.txt b/tests/baselines/reference/localTypes4.errors.txt new file mode 100644 index 0000000000000..cad9d30c933b0 --- /dev/null +++ b/tests/baselines/reference/localTypes4.errors.txt @@ -0,0 +1,53 @@ +tests/cases/conformance/types/localTypes/localTypes4.ts(10,19): error TS2304: Cannot find name 'T'. +tests/cases/conformance/types/localTypes/localTypes4.ts(10,23): error TS2304: Cannot find name 'T'. +tests/cases/conformance/types/localTypes/localTypes4.ts(18,16): error TS2300: Duplicate identifier 'T'. +tests/cases/conformance/types/localTypes/localTypes4.ts(19,19): error TS2300: Duplicate identifier 'T'. + + +==== tests/cases/conformance/types/localTypes/localTypes4.ts (4 errors) ==== + function f1() { + // Type parameters are in scope in parameters and return types + function f(x: T): T { + return undefined; + } + } + + function f2() { + // Local types are not in scope in parameters and return types + function f(x: T): T { + ~ +!!! error TS2304: Cannot find name 'T'. + ~ +!!! error TS2304: Cannot find name 'T'. + interface T { } + return undefined; + } + } + + function f3() { + // Type parameters and top-level local types are in same declaration space + function f() { + ~ +!!! error TS2300: Duplicate identifier 'T'. + interface T { } + ~ +!!! error TS2300: Duplicate identifier 'T'. + return undefined; + } + } + + function f4() { + // Local types are block scoped + interface T { x: number } + let v: T; + v.x = 10; + if (true) { + interface T { x: string } + let v: T; + v.x = "hello"; + } + else { + v.x = 20; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/localTypes4.js b/tests/baselines/reference/localTypes4.js new file mode 100644 index 0000000000000..8f51761a65af6 --- /dev/null +++ b/tests/baselines/reference/localTypes4.js @@ -0,0 +1,70 @@ +//// [localTypes4.ts] +function f1() { + // Type parameters are in scope in parameters and return types + function f(x: T): T { + return undefined; + } +} + +function f2() { + // Local types are not in scope in parameters and return types + function f(x: T): T { + interface T { } + return undefined; + } +} + +function f3() { + // Type parameters and top-level local types are in same declaration space + function f() { + interface T { } + return undefined; + } +} + +function f4() { + // Local types are block scoped + interface T { x: number } + let v: T; + v.x = 10; + if (true) { + interface T { x: string } + let v: T; + v.x = "hello"; + } + else { + v.x = 20; + } +} + + +//// [localTypes4.js] +function f1() { + // Type parameters are in scope in parameters and return types + function f(x) { + return undefined; + } +} +function f2() { + // Local types are not in scope in parameters and return types + function f(x) { + return undefined; + } +} +function f3() { + // Type parameters and top-level local types are in same declaration space + function f() { + return undefined; + } +} +function f4() { + var v; + v.x = 10; + if (true) { + var v_1; + v_1.x = "hello"; + } + else { + v.x = 20; + } +} diff --git a/tests/baselines/reference/localTypes5.js b/tests/baselines/reference/localTypes5.js new file mode 100644 index 0000000000000..872629276d2fc --- /dev/null +++ b/tests/baselines/reference/localTypes5.js @@ -0,0 +1,38 @@ +//// [localTypes5.ts] +function foo() { + class X { + m() { + return (function () { + class Y { + } + return new Y(); + })(); + } + } + var x = new X(); + return x.m(); +} +var x = foo(); + + +//// [localTypes5.js] +function foo() { + var X = (function () { + function X() { + } + X.prototype.m = function () { + return (function () { + var Y = (function () { + function Y() { + } + return Y; + })(); + return new Y(); + })(); + }; + return X; + })(); + var x = new X(); + return x.m(); +} +var x = foo(); diff --git a/tests/baselines/reference/localTypes5.symbols b/tests/baselines/reference/localTypes5.symbols new file mode 100644 index 0000000000000..4ffe53b3e5303 --- /dev/null +++ b/tests/baselines/reference/localTypes5.symbols @@ -0,0 +1,40 @@ +=== tests/cases/conformance/types/localTypes/localTypes5.ts === +function foo() { +>foo : Symbol(foo, Decl(localTypes5.ts, 0, 0)) +>A : Symbol(A, Decl(localTypes5.ts, 0, 13)) + + class X { +>X : Symbol(X, Decl(localTypes5.ts, 0, 19)) + + m() { +>m : Symbol(m, Decl(localTypes5.ts, 1, 13)) +>B : Symbol(B, Decl(localTypes5.ts, 2, 10)) +>C : Symbol(C, Decl(localTypes5.ts, 2, 12)) + + return (function () { +>D : Symbol(D, Decl(localTypes5.ts, 3, 30)) + + class Y { +>Y : Symbol(Y, Decl(localTypes5.ts, 3, 36)) +>E : Symbol(E, Decl(localTypes5.ts, 4, 24)) + } + return new Y(); +>Y : Symbol(Y, Decl(localTypes5.ts, 3, 36)) + + })(); +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) + } + } + var x = new X(); +>x : Symbol(x, Decl(localTypes5.ts, 10, 7)) +>X : Symbol(X, Decl(localTypes5.ts, 0, 19)) + + return x.m(); +>x.m : Symbol(X.m, Decl(localTypes5.ts, 1, 13)) +>x : Symbol(x, Decl(localTypes5.ts, 10, 7)) +>m : Symbol(X.m, Decl(localTypes5.ts, 1, 13)) +} +var x = foo(); +>x : Symbol(x, Decl(localTypes5.ts, 13, 3)) +>foo : Symbol(foo, Decl(localTypes5.ts, 0, 0)) + diff --git a/tests/baselines/reference/localTypes5.types b/tests/baselines/reference/localTypes5.types new file mode 100644 index 0000000000000..b12e362f75490 --- /dev/null +++ b/tests/baselines/reference/localTypes5.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/types/localTypes/localTypes5.ts === +function foo() { +>foo : () => X.m..Y +>A : A + + class X { +>X : X + + m() { +>m : () => .Y +>B : B +>C : C + + return (function () { +>(function () { class Y { } return new Y(); })() : .Y +>(function () { class Y { } return new Y(); }) : () => Y +>function () { class Y { } return new Y(); } : () => Y +>D : D + + class Y { +>Y : Y +>E : E + } + return new Y(); +>new Y() : Y +>Y : typeof Y + + })(); +>Date : Date + } + } + var x = new X(); +>x : X +>new X() : X +>X : typeof X + + return x.m(); +>x.m() : X.m..Y +>x.m : () => .Y +>x : X +>m : () => .Y +} +var x = foo(); +>x : foo.X.m..Y +>foo() : foo.X.m..Y +>foo : () => X.m..Y + diff --git a/tests/baselines/reference/withStatementErrors.errors.txt b/tests/baselines/reference/withStatementErrors.errors.txt index ba399f511976c..bfea39b5426d9 100644 --- a/tests/baselines/reference/withStatementErrors.errors.txt +++ b/tests/baselines/reference/withStatementErrors.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/withStatementErrors.ts(3,7): error TS2410: All symbols within a 'with' block will be resolved to 'any'. -tests/cases/compiler/withStatementErrors.ts(13,5): error TS1129: Statement expected. +tests/cases/compiler/withStatementErrors.ts(15,5): error TS1129: Statement expected. tests/cases/compiler/withStatementErrors.ts(17,1): error TS1128: Declaration or statement expected. @@ -19,10 +19,10 @@ tests/cases/compiler/withStatementErrors.ts(17,1): error TS1128: Declaration or class C {} // error interface I {} // error - ~~~~~~~~~ -!!! error TS1129: Statement expected. module M {} // error + ~~~~~~ +!!! error TS1129: Statement expected. } ~ diff --git a/tests/baselines/reference/withStatementErrors.js b/tests/baselines/reference/withStatementErrors.js index 43236c94d8dc7..65b4599946386 100644 --- a/tests/baselines/reference/withStatementErrors.js +++ b/tests/baselines/reference/withStatementErrors.js @@ -28,5 +28,5 @@ with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) { function C() { } return C; - })(); -} // error + })(); // error +} // error diff --git a/tests/cases/conformance/types/localTypes/localTypes1.ts b/tests/cases/conformance/types/localTypes/localTypes1.ts new file mode 100644 index 0000000000000..bceb9ad32cf93 --- /dev/null +++ b/tests/cases/conformance/types/localTypes/localTypes1.ts @@ -0,0 +1,141 @@ +// @target: es5 + +function f1() { + enum E { + A, B, C + } + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; +} + +function f2() { + function g() { + enum E { + A, B, C + } + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; + } + return g(); +} + +function f3(b: boolean) { + if (true) { + enum E { + A, B, C + } + if (b) { + class C { + x: E; + } + interface I { + x: E; + } + type A = I[]; + let a: A = [new C()]; + a[0].x = E.B; + return a; + } + else { + class A { + x: E; + } + interface J { + x: E; + } + type C = J[]; + let c: C = [new A()]; + c[0].x = E.B; + return c; + } + } +} + +function f5() { + var z1 = function () { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } + var z2 = () => { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } +} + +class A { + constructor() { + enum E { + A, B, C + } + class C { + x: E; + } + } + m() { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } + get p() { + enum E { + A, B, C + } + class C { + x: E; + } + return new C(); + } +} + +function f6() { + class A { + a: string; + } + function g() { + class B extends A { + b: string; + } + function h() { + class C extends B { + c: string; + } + var x = new C(); + x.a = "a"; + x.b = "b"; + x.c = "c"; + return x; + } + return h(); + } + return g(); +} diff --git a/tests/cases/conformance/types/localTypes/localTypes2.ts b/tests/cases/conformance/types/localTypes/localTypes2.ts new file mode 100644 index 0000000000000..79f1402c7022e --- /dev/null +++ b/tests/cases/conformance/types/localTypes/localTypes2.ts @@ -0,0 +1,40 @@ +function f1() { + function f() { + class C { + constructor(public x: number, public y: number) { } + } + return C; + } + let C = f(); + let v = new C(10, 20); + let x = v.x; + let y = v.y; +} + +function f2() { + function f(x: number) { + class C { + public x = x; + constructor(public y: number) { } + } + return C; + } + let C = f(10); + let v = new C(20); + let x = v.x; + let y = v.y; +} + +function f3() { + function f(x: number, y: number) { + class C { + public x = x; + public y = y; + } + return C; + } + let C = f(10, 20); + let v = new C(); + let x = v.x; + let y = v.y; +} diff --git a/tests/cases/conformance/types/localTypes/localTypes3.ts b/tests/cases/conformance/types/localTypes/localTypes3.ts new file mode 100644 index 0000000000000..5eb3cf2850664 --- /dev/null +++ b/tests/cases/conformance/types/localTypes/localTypes3.ts @@ -0,0 +1,40 @@ +function f1() { + function f() { + class C { + constructor(public x: X, public y: Y) { } + } + return C; + } + let C = f(); + let v = new C(10, "hello"); + let x = v.x; + let y = v.y; +} + +function f2() { + function f(x: X) { + class C { + public x = x; + constructor(public y: Y) { } + } + return C; + } + let C = f(10); + let v = new C("hello"); + let x = v.x; + let y = v.y; +} + +function f3() { + function f(x: X, y: Y) { + class C { + public x = x; + public y = y; + } + return C; + } + let C = f(10, "hello"); + let v = new C(); + let x = v.x; + let y = v.y; +} diff --git a/tests/cases/conformance/types/localTypes/localTypes4.ts b/tests/cases/conformance/types/localTypes/localTypes4.ts new file mode 100644 index 0000000000000..bd31e76a80f86 --- /dev/null +++ b/tests/cases/conformance/types/localTypes/localTypes4.ts @@ -0,0 +1,37 @@ +function f1() { + // Type parameters are in scope in parameters and return types + function f(x: T): T { + return undefined; + } +} + +function f2() { + // Local types are not in scope in parameters and return types + function f(x: T): T { + interface T { } + return undefined; + } +} + +function f3() { + // Type parameters and top-level local types are in same declaration space + function f() { + interface T { } + return undefined; + } +} + +function f4() { + // Local types are block scoped + interface T { x: number } + let v: T; + v.x = 10; + if (true) { + interface T { x: string } + let v: T; + v.x = "hello"; + } + else { + v.x = 20; + } +} diff --git a/tests/cases/conformance/types/localTypes/localTypes5.ts b/tests/cases/conformance/types/localTypes/localTypes5.ts new file mode 100644 index 0000000000000..6aec24f183d99 --- /dev/null +++ b/tests/cases/conformance/types/localTypes/localTypes5.ts @@ -0,0 +1,14 @@ +function foo() { + class X { + m() { + return (function () { + class Y { + } + return new Y(); + })(); + } + } + var x = new X(); + return x.m(); +} +var x = foo();