diff --git a/Gulpfile.ts b/Gulpfile.ts index 32fbf2c43e..03046789fe 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -935,7 +935,7 @@ gulp.task(loggedIOJsPath, /*help*/ false, [], (done) => { const temp = path.join(builtLocalDirectory, "temp"); mkdirP(temp, (err) => { if (err) { console.error(err); done(err); process.exit(1); } - exec(host, [LKGCompiler, "--types --outdir", temp, loggedIOpath], () => { + exec(host, [LKGCompiler, "--types", "--target es5", "--lib es5", "--outdir", temp, loggedIOpath], () => { fs.renameSync(path.join(temp, "/harness/loggedIO.js"), loggedIOJsPath); del(temp).then(() => done(), done); }, done); @@ -946,7 +946,13 @@ const instrumenterPath = path.join(harnessDirectory, "instrumenter.ts"); const instrumenterJsPath = path.join(builtLocalDirectory, "instrumenter.js"); gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => { const settings: tsc.Settings = getCompilerSettings({ - outFile: instrumenterJsPath + outFile: instrumenterJsPath, + target: "es5", + lib: [ + "es6", + "dom", + "scripthost" + ] }, /*useBuiltCompiler*/ true); return gulp.src(instrumenterPath) .pipe(newer(instrumenterJsPath)) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e426a7bdba..2d46488665 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -685,10 +685,6 @@ namespace ts { return type.flags & TypeFlags.Object ? (type).objectFlags : 0; } - function getCheckFlags(symbol: Symbol): CheckFlags { - return symbol.flags & SymbolFlags.Transient ? (symbol).checkFlags : 0; - } - function isGlobalSourceFile(node: Node) { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } @@ -1284,7 +1280,7 @@ namespace ts { else if (result.flags & SymbolFlags.Class) { error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); } - else if (result.flags & SymbolFlags.Enum) { + else if (result.flags & SymbolFlags.RegularEnum) { error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); } } @@ -1304,7 +1300,7 @@ namespace ts { return node; } - return findAncestor(node, n => n.kind === SyntaxKind.ImportDeclaration) as ImportDeclaration; + return findAncestor(node, isImportDeclaration); } } @@ -2814,7 +2810,7 @@ namespace ts { } function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration { - const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration.name.kind === SyntaxKind.Identifier ? @@ -4193,7 +4189,7 @@ namespace ts { const func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && !hasDynamicName(func)) { - const getter = getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); @@ -4482,8 +4478,8 @@ namespace ts { function getTypeOfAccessors(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); - const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); if (getter && getter.flags & NodeFlags.JavaScriptFile) { const jsDocType = getTypeForDeclarationFromJSDocComment(getter); @@ -4532,7 +4528,7 @@ namespace ts { if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } @@ -5009,7 +5005,7 @@ namespace ts { return unknownType; } - let declaration: JSDocTypedefTag | TypeAliasDeclaration = getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag); + let declaration: JSDocTypedefTag | TypeAliasDeclaration = getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag); let type: Type; if (declaration) { if (declaration.jsDocTypeLiteral) { @@ -5020,7 +5016,7 @@ namespace ts { } } else { - declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); + declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); type = getTypeFromTypeNode(declaration.type); } @@ -6313,7 +6309,7 @@ namespace ts { !hasDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(declaration.symbol, otherKind); + const other = getDeclarationOfKind(declaration.symbol, otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } @@ -6356,7 +6352,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. if (declaration.kind === SyntaxKind.GetAccessor && !hasDynamicName(declaration)) { - const setter = getDeclarationOfKind(declaration.symbol, SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(declaration.symbol, SyntaxKind.SetAccessor); return getAnnotatedAccessorType(setter); } @@ -6569,7 +6565,7 @@ namespace ts { } function getConstraintDeclaration(type: TypeParameter) { - return (getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint; + return getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter).constraint; } function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type { @@ -10190,22 +10186,11 @@ namespace ts { } function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) { - let sourceStack: Type[]; - let targetStack: Type[]; - let depth = 0; + let symbolStack: Symbol[]; + let visited: Map; let inferiority = 0; - const visited = createMap(); inferFromTypes(originalSource, originalTarget); - function isInProcess(source: Type, target: Type) { - for (let i = 0; i < depth; i++) { - if (source === sourceStack[i] && target === targetStack[i]) { - return true; - } - } - return false; - } - function inferFromTypes(source: Type, target: Type) { if (!couldContainTypeVariables(target)) { return; @@ -10333,26 +10318,29 @@ namespace ts { else { source = getApparentType(source); if (source.flags & TypeFlags.Object) { - if (isInProcess(source, target)) { - return; - } - if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType(target, targetStack, depth)) { - return; - } const key = source.id + "," + target.id; - if (visited.get(key)) { + if (visited && visited.get(key)) { return; } - visited.set(key, true); - if (depth === 0) { - sourceStack = []; - targetStack = []; + (visited || (visited = createMap())).set(key, true); + // If we are already processing another target type with the same associated symbol (such as + // an instantiation of the same generic type), we do not explore this target as it would yield + // no further inferences. We exclude the static side of classes from this check since it shares + // its symbol with the instance side which would lead to false positives. + const isNonConstructorObject = target.flags & TypeFlags.Object && + !(getObjectFlags(target) & ObjectFlags.Anonymous && target.symbol && target.symbol.flags & SymbolFlags.Class); + const symbol = isNonConstructorObject ? target.symbol : undefined; + if (symbol) { + if (contains(symbolStack, symbol)) { + return; + } + (symbolStack || (symbolStack = [])).push(symbol); + inferFromObjectTypes(source, target); + symbolStack.pop(); + } + else { + inferFromObjectTypes(source, target); } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromObjectTypes(source, target); - depth--; } } } @@ -12660,7 +12648,7 @@ namespace ts { // corresponding set accessor has a type annotation, return statements in the function are contextually typed if (functionDecl.type || functionDecl.kind === SyntaxKind.Constructor || - functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) { + functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) { return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl)); } @@ -13407,6 +13395,7 @@ namespace ts { let spread: Type = emptyObjectType; let attributesArray: Symbol[] = []; let hasSpreadAnyType = false; + let typeToIntersect: Type; let explicitlySpecifyChildrenAttribute = false; const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); @@ -13438,11 +13427,16 @@ namespace ts { attributesArray = []; attributesTable = createMap(); } - const exprType = getApparentType(checkExpression(attributeDecl.expression)); + const exprType = checkExpression(attributeDecl.expression); if (isTypeAny(exprType)) { hasSpreadAnyType = true; } - spread = getSpreadType(spread, exprType); + if (isValidSpreadType(exprType)) { + spread = getSpreadType(spread, exprType); + } + else { + typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; + } } } @@ -13497,7 +13491,13 @@ namespace ts { } } - return hasSpreadAnyType ? anyType : createJsxAttributesType(attributes.symbol, attributesTable); + if (hasSpreadAnyType) { + return anyType; + } + + const attributeType = createJsxAttributesType(attributes.symbol, attributesTable); + return typeToIntersect && attributesTable.size ? getIntersectionType([typeToIntersect, attributeType]) : + typeToIntersect ? typeToIntersect : attributeType; /** * Create anonymous type from given attributes symbol table. @@ -13663,6 +13663,20 @@ namespace ts { return _jsxElementChildrenPropertyName; } + function getApparentTypeOfJsxPropsType(propsType: Type): Type { + if (!propsType) { + return undefined; + } + if (propsType.flags & TypeFlags.Intersection) { + const propsApparentType: Type[] = []; + for (const t of (propsType).types) { + propsApparentType.push(getApparentType(t)); + } + return getIntersectionType(propsApparentType); + } + return getApparentType(propsType); + } + /** * Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component. * Return only attributes type of successfully resolved call signature. @@ -13683,6 +13697,7 @@ namespace ts { if (callSignature !== unknownSignature) { const callReturnType = callSignature && getReturnTypeOfSignature(callSignature); let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); + paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { // Intersect in JSX.IntrinsicAttributes if it exists const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes); @@ -13720,7 +13735,8 @@ namespace ts { let allMatchingAttributesType: Type; for (const candidate of candidatesOutArray) { const callReturnType = getReturnTypeOfSignature(candidate); - const paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); + let paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); + paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { let shouldBeCandidate = true; for (const attribute of openingLikeElement.attributes.properties) { @@ -14120,25 +14136,6 @@ namespace ts { return s.valueDeclaration ? s.valueDeclaration.kind : SyntaxKind.PropertyDeclaration; } - function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags { - if (s.valueDeclaration) { - const flags = getCombinedModifierFlags(s.valueDeclaration); - return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier; - } - if (getCheckFlags(s) & CheckFlags.Synthetic) { - const checkFlags = (s).checkFlags; - const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private : - checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public : - ModifierFlags.Protected; - const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0; - return accessModifier | staticModifier; - } - if (s.flags & SymbolFlags.Prototype) { - return ModifierFlags.Public | ModifierFlags.Static; - } - return 0; - } - function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags { return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0; } @@ -18194,7 +18191,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(node.symbol, otherKind); + const otherAccessor = getDeclarationOfKind(node.symbol, otherKind); if (otherAccessor) { if ((getModifierFlags(node) & ModifierFlags.AccessibilityModifier) !== (getModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier)) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); @@ -20326,7 +20323,7 @@ namespace ts { } function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) { - return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor))); + return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor))); } function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean { @@ -21014,7 +21011,7 @@ namespace ts { checkTypeParameterListsIdentical(symbol); // Only check this symbol once - const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); if (node === firstInterfaceDecl) { const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); @@ -22730,7 +22727,7 @@ namespace ts { const symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } - return findAncestor(node.parent, n => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol) as ModuleDeclaration | EnumDeclaration; + return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 321cc06f76..60553fdab0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -230,6 +230,8 @@ namespace ts { * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ + export function findAncestor(node: Node, callback: (element: Node) => element is T): T | undefined; + export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node | undefined; export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node { while (node) { const result = callback(node); @@ -490,6 +492,35 @@ namespace ts { return result; } + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * Avoids allocation if all elements map to themselves. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + export function sameFlatMap(array: T[], mapfn: (x: T, i: number) => T | T[]): T[] { + let result: T[]; + if (array) { + for (let i = 0; i < array.length; i++) { + const item = array[i]; + const mapped = mapfn(item, i); + if (result || item !== mapped || isArray(mapped)) { + if (!result) { + result = array.slice(0, i); + } + if (isArray(mapped)) { + addRange(result, mapped); + } + else { + result.push(mapped); + } + } + } + } + return result || array; + } + /** * Computes the first matching span of elements and returns a tuple of the first span * and the remaining elements. diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 7917480975..615f3b1b36 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -740,6 +740,9 @@ namespace ts { // Transformation nodes case SyntaxKind.PartiallyEmittedExpression: return emitPartiallyEmittedExpression(node); + + case SyntaxKind.CommaListExpression: + return emitCommaList(node); } } @@ -2124,6 +2127,10 @@ namespace ts { emitExpression(node.expression); } + function emitCommaList(node: CommaListExpression) { + emitExpressionList(node, node.elements, ListFormat.CommaListElements); + } + /** * Emits any prologue directives at the start of a Statement list, returning the * number of prologue directives written to the output. @@ -2979,6 +2986,7 @@ namespace ts { ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, + CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine, CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, TemplateExpressionSpans = SingleLine | NoInterveningComments, diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 1a5f1fbac5..fbb387f034 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2091,6 +2091,30 @@ namespace ts { return node; } + function flattenCommaElements(node: Expression): Expression | Expression[] { + if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { + if (node.kind === SyntaxKind.CommaListExpression) { + return (node).elements; + } + if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { + return [node.left, node.right]; + } + } + return node; + } + + export function createCommaList(elements: Expression[]) { + const node = createSynthesizedNode(SyntaxKind.CommaListExpression); + node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); + return node; + } + + export function updateCommaList(node: CommaListExpression, elements: Expression[]) { + return node.elements !== elements + ? updateNode(createCommaList(elements), node) + : node; + } + export function createBundle(sourceFiles: SourceFile[]) { const node = createNode(SyntaxKind.Bundle); node.sourceFiles = sourceFiles; @@ -2898,7 +2922,11 @@ namespace ts { } export function inlineExpressions(expressions: Expression[]) { - return reduceLeft(expressions, createComma); + // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call + // stack size exceeded" errors. + return expressions.length > 10 + ? createCommaList(expressions) + : reduceLeft(expressions, createComma); } export function createExpressionFromEntityName(node: EntityName | Expression): Expression { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index acf01bac90..12a42b6899 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -47,13 +47,11 @@ namespace ts { return resolved.path; } - /** Adds `isExernalLibraryImport` to a Resolved to get a ResolvedModule. */ - function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModuleFull { - return { resolvedFileName: path, extension, isExternalLibraryImport }; - } - function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations { - return { resolvedModule: resolved && resolvedModuleFromResolved(resolved, isExternalLibraryImport), failedLookupLocations }; + return { + resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, isExternalLibraryImport }, + failedLookupLocations + }; } export function moduleHasNonRelativeName(moduleName: string): boolean { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index cc3fb24bdb..2d9806bcbf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -23,19 +23,19 @@ namespace ts { } } - function visitNode(cbNode: (node: Node) => T, node: Node): T { + function visitNode(cbNode: (node: Node) => T, node: Node): T | undefined { if (node) { return cbNode(node); } } - function visitNodeArray(cbNodes: (nodes: Node[]) => T, nodes: Node[]) { + function visitNodeArray(cbNodes: (nodes: Node[]) => T, nodes: Node[]): T | undefined { if (nodes) { return cbNodes(nodes); } } - function visitEachNode(cbNode: (node: Node) => T, nodes: Node[]) { + function visitEachNode(cbNode: (node: Node) => T, nodes: Node[]): T | undefined { if (nodes) { for (const node of nodes) { const result = cbNode(node); @@ -50,7 +50,7 @@ namespace ts { // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { + export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T | undefined { if (!node) { return; } @@ -362,6 +362,8 @@ namespace ts { return visitNode(cbNode, (node).expression); case SyntaxKind.MissingDeclaration: return visitNodes(cbNodes, node.decorators); + case SyntaxKind.CommaListExpression: + return visitNodes(cbNodes, (node).elements); case SyntaxKind.JsxElement: return visitNode(cbNode, (node).openingElement) || diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7893fee651..8233ab4802 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -241,6 +241,101 @@ namespace ts { return output; } + const redForegroundEscapeSequence = "\u001b[91m"; + const yellowForegroundEscapeSequence = "\u001b[93m"; + const blueForegroundEscapeSequence = "\u001b[93m"; + const gutterStyleSequence = "\u001b[100;30m"; + const gutterSeparator = " "; + const resetEscapeSequence = "\u001b[0m"; + const ellipsis = "..."; + function getCategoryFormat(category: DiagnosticCategory): string { + switch (category) { + case DiagnosticCategory.Warning: return yellowForegroundEscapeSequence; + case DiagnosticCategory.Error: return redForegroundEscapeSequence; + case DiagnosticCategory.Message: return blueForegroundEscapeSequence; + } + } + + function formatAndReset(text: string, formatStyle: string) { + return formatStyle + text + resetEscapeSequence; + } + + function padLeft(s: string, length: number) { + while (s.length < length) { + s = " " + s; + } + return s; + } + + export function formatDiagnosticsWithColorAndContext(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string { + let output = ""; + for (const diagnostic of diagnostics) { + if (diagnostic.file) { + const { start, length, file } = diagnostic; + const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); + const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); + const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; + const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; + + const hasMoreThanFiveLines = (lastLine - firstLine) >= 4; + let gutterWidth = (lastLine + 1 + "").length; + if (hasMoreThanFiveLines) { + gutterWidth = Math.max(ellipsis.length, gutterWidth); + } + + output += sys.newLine; + for (let i = firstLine; i <= lastLine; i++) { + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. + if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { + output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + sys.newLine; + i = lastLine - 1; + } + + const lineStart = getPositionOfLineAndCharacter(file, i, 0); + const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; + let lineContent = file.text.slice(lineStart, lineEnd); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces + + // Output the gutter and the actual contents of the line. + output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += lineContent + sys.newLine; + + // Output the gutter and the error span for the line using tildes. + output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += redForegroundEscapeSequence; + if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. + const lastCharForLine = i === lastLine ? lastLineChar : undefined; + + output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); + output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); + } + else if (i === lastLine) { + output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); + } + else { + // Squiggle the entire line. + output += lineContent.replace(/./g, "~"); + } + output += resetEscapeSequence; + + output += sys.newLine; + } + + output += sys.newLine; + output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; + } + + const categoryColor = getCategoryFormat(diagnostic.category); + const category = DiagnosticCategory[diagnostic.category].toLowerCase(); + output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; + } + return output; + } + export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string { if (typeof messageText === "string") { return messageText; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 659c2f416a..d27bbf879f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -712,11 +712,11 @@ namespace ts { return accumulator; } - export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) { + export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); } - export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) { + export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); } @@ -746,10 +746,11 @@ namespace ts { } /** Optionally, get the shebang */ - export function getShebang(text: string): string { - return shebangTriviaRegex.test(text) - ? shebangTriviaRegex.exec(text)[0] - : undefined; + export function getShebang(text: string): string | undefined { + const match = shebangTriviaRegex.exec(text); + if (match) { + return match[0]; + } } export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean { diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index fef1b009ba..81ebd0b8f5 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -929,8 +929,8 @@ namespace ts { text: ` var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; ` }; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 8981da65ba..834c7326e2 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -60,93 +60,8 @@ namespace ts { sys.write(ts.formatDiagnostics([diagnostic], host)); } - const redForegroundEscapeSequence = "\u001b[91m"; - const yellowForegroundEscapeSequence = "\u001b[93m"; - const blueForegroundEscapeSequence = "\u001b[93m"; - const gutterStyleSequence = "\u001b[100;30m"; - const gutterSeparator = " "; - const resetEscapeSequence = "\u001b[0m"; - const ellipsis = "..."; - function getCategoryFormat(category: DiagnosticCategory): string { - switch (category) { - case DiagnosticCategory.Warning: return yellowForegroundEscapeSequence; - case DiagnosticCategory.Error: return redForegroundEscapeSequence; - case DiagnosticCategory.Message: return blueForegroundEscapeSequence; - } - } - - function formatAndReset(text: string, formatStyle: string) { - return formatStyle + text + resetEscapeSequence; - } - function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: FormatDiagnosticsHost): void { - let output = ""; - - if (diagnostic.file) { - const { start, length, file } = diagnostic; - const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); - const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); - const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; - const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; - - const hasMoreThanFiveLines = (lastLine - firstLine) >= 4; - let gutterWidth = (lastLine + 1 + "").length; - if (hasMoreThanFiveLines) { - gutterWidth = Math.max(ellipsis.length, gutterWidth); - } - - output += sys.newLine; - for (let i = firstLine; i <= lastLine; i++) { - // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, - // so we'll skip ahead to the second-to-last line. - if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + sys.newLine; - i = lastLine - 1; - } - - const lineStart = getPositionOfLineAndCharacter(file, i, 0); - const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; - let lineContent = file.text.slice(lineStart, lineEnd); - lineContent = lineContent.replace(/\s+$/g, ""); // trim from end - lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces - - // Output the gutter and the actual contents of the line. - output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += lineContent + sys.newLine; - - // Output the gutter and the error span for the line using tildes. - output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += redForegroundEscapeSequence; - if (i === firstLine) { - // If we're on the last line, then limit it to the last character of the last line. - // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. - const lastCharForLine = i === lastLine ? lastLineChar : undefined; - - output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); - output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); - } - else if (i === lastLine) { - output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); - } - else { - // Squiggle the entire line. - output += lineContent.replace(/./g, "~"); - } - output += resetEscapeSequence; - - output += sys.newLine; - } - - output += sys.newLine; - output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; - } - - const categoryColor = getCategoryFormat(diagnostic.category); - const category = DiagnosticCategory[diagnostic.category].toLowerCase(); - output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; - output += sys.newLine + sys.newLine; - - sys.write(output); + sys.write(ts.formatDiagnosticsWithColorAndContext([diagnostic], host) + sys.newLine + sys.newLine); } function reportWatchDiagnostic(diagnostic: Diagnostic) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3ac3caa121..0283c45f2e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -389,6 +389,7 @@ namespace ts { // Transformation nodes NotEmittedStatement, PartiallyEmittedExpression, + CommaListExpression, MergeDeclarationMarker, EndOfDeclarationMarker, @@ -1604,6 +1605,14 @@ namespace ts { kind: SyntaxKind.EndOfDeclarationMarker; } + /** + * A list of comma-seperated expressions. This node is only created by transformations. + */ + export interface CommaListExpression extends Expression { + kind: SyntaxKind.CommaListExpression; + elements: NodeArray; + } + /** * Marks the beginning of a merged transformed declaration. */ @@ -2519,11 +2528,11 @@ namespace ts { indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; - getSymbolAtLocation(node: Node): Symbol; + getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; - getShorthandAssignmentValueSymbol(location: Node): Symbol; - getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol; - getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol; + getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined; + getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined; + getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; @@ -2534,15 +2543,15 @@ namespace ts { getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; getContextualType(node: Expression): Type | undefined; - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature; - getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature; - isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; + getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature | undefined; + getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; isUnknownSymbol(symbol: Symbol): boolean; /* @internal */ getMergedSymbol(symbol: Symbol): Symbol; - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; + getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number | undefined; isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean; /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; @@ -2552,7 +2561,7 @@ namespace ts { /** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */ /* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[]; - getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type; + getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined; getJsxIntrinsicTagNames(): Symbol[]; isOptionalParameter(node: ParameterDeclaration): boolean; getAmbientModules(): Symbol[]; @@ -2560,10 +2569,10 @@ namespace ts { tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined; getApparentType(type: Type): Type; getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined; - getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string; - /* @internal */ getBaseConstraintOfType(type: Type): Type; + getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; + /* @internal */ getBaseConstraintOfType(type: Type): Type | undefined; - /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol; + /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; // Should not be called directly. Should only be accessed through the Program instance. /* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; @@ -2759,7 +2768,7 @@ namespace ts { getNodeCheckFlags(node: Node): NodeCheckFlags; isDeclarationVisible(node: Declaration): boolean; collectLinkedAliases(node: Identifier): Node[]; - isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -3141,7 +3150,7 @@ namespace ts { */ export interface TypeReference extends ObjectType { target: GenericType; // Type reference target - typeArguments: Type[]; // Type reference type arguments (undefined if none) + typeArguments?: Type[]; // Type reference type arguments (undefined if none) } // Generic class and interface types @@ -3271,7 +3280,7 @@ namespace ts { export interface Signature { declaration: SignatureDeclaration; // Originating declaration - typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) + typeParameters?: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters /* @internal */ thisParameter?: Symbol; // symbol of this-type parameter diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c8e481bc2e..8d570f7063 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -11,12 +11,12 @@ namespace ts { isTypeReferenceDirective?: boolean; } - export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { + export function getDeclarationOfKind(symbol: Symbol, kind: T["kind"]): T { const declarations = symbol.declarations; if (declarations) { for (const declaration of declarations) { if (declaration.kind === kind) { - return declaration; + return declaration as T; } } } @@ -2335,6 +2335,9 @@ namespace ts { case SyntaxKind.SpreadElement: return 1; + case SyntaxKind.CommaListExpression: + return 0; + default: return -1; } @@ -3924,6 +3927,7 @@ namespace ts { || kind === SyntaxKind.SpreadElement || kind === SyntaxKind.AsExpression || kind === SyntaxKind.OmittedExpression + || kind === SyntaxKind.CommaListExpression || isUnaryExpressionKind(kind); } @@ -4015,6 +4019,10 @@ namespace ts { return node.kind === SyntaxKind.ImportEqualsDeclaration; } + export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node.kind === SyntaxKind.ImportDeclaration; + } + export function isImportClause(node: Node): node is ImportClause { return node.kind === SyntaxKind.ImportClause; } @@ -4037,6 +4045,10 @@ namespace ts { return node.kind === SyntaxKind.ExportSpecifier; } + export function isExportAssignment(node: Node): node is ExportAssignment { + return node.kind === SyntaxKind.ExportAssignment; + } + export function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration { return node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration; } @@ -4244,6 +4256,29 @@ namespace ts { return options.watch && options.hasOwnProperty("watch"); } + export function getCheckFlags(symbol: Symbol): CheckFlags { + return symbol.flags & SymbolFlags.Transient ? (symbol).checkFlags : 0; + } + + export function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags { + if (s.valueDeclaration) { + const flags = getCombinedModifierFlags(s.valueDeclaration); + return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier; + } + if (getCheckFlags(s) & CheckFlags.Synthetic) { + const checkFlags = (s).checkFlags; + const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private : + checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public : + ModifierFlags.Protected; + const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0; + return accessModifier | staticModifier; + } + if (s.flags & SymbolFlags.Prototype) { + return ModifierFlags.Public | ModifierFlags.Static; + } + return 0; + } + export function levenshtein(s1: string, s2: string): number { let previous: number[] = new Array(s2.length + 1); let current: number[] = new Array(s2.length + 1); diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index f8fe92c184..eb28721a14 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -881,6 +881,10 @@ namespace ts { return updatePartiallyEmittedExpression(node, visitNode((node).expression, visitor, isExpression)); + case SyntaxKind.CommaListExpression: + return updateCommaList(node, + nodesVisitor((node).elements, visitor, isExpression)); + default: // No need to visit nodes with no children. return node; @@ -1403,6 +1407,10 @@ namespace ts { result = reduceNode((node).expression, cbNode, result); break; + case SyntaxKind.CommaListExpression: + result = reduceNodes((node).elements, cbNodes, result); + break; + default: break; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 83d27c951b..70b67f3326 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3417,6 +3417,18 @@ namespace FourSlashInterface { export class VerifyNegatable { public not: VerifyNegatable; + public allowedClassElementKeywords = [ + "public", + "private", + "protected", + "static", + "abstract", + "readonly", + "get", + "set", + "constructor", + "async" + ]; constructor(protected state: FourSlash.TestState, private negative = false) { if (!negative) { @@ -3453,6 +3465,12 @@ namespace FourSlashInterface { this.state.verifyCompletionListIsEmpty(this.negative); } + public completionListContainsClassElementKeywords() { + for (const keyword of this.allowedClassElementKeywords) { + this.completionListContains(keyword, keyword, /*documentation*/ undefined, "keyword"); + } + } + public completionListIsGlobal(expected: boolean) { this.state.verifyCompletionListIsGlobal(expected); } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 428b69027c..c4c9ecece2 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2267,6 +2267,7 @@ namespace ts.server.protocol { insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; + insertSpaceAfterTypeAssertion?: boolean; insertSpaceBeforeFunctionParenthesis?: boolean; placeOpenBraceOnNewLineForFunctions?: boolean; placeOpenBraceOnNewLineForControlBlocks?: boolean; diff --git a/src/services/completions.ts b/src/services/completions.ts index ce7e837e23..5bc2a26861 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -18,7 +18,7 @@ namespace ts.Completions { return undefined; } - const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag } = completionData; + const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords } = completionData; if (requestJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion @@ -52,7 +52,7 @@ namespace ts.Completions { sortText: "0", }); } - else { + else if (!hasFilteredClassMemberKeywords) { return undefined; } } @@ -60,8 +60,11 @@ namespace ts.Completions { getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log); } + if (hasFilteredClassMemberKeywords) { + addRange(entries, classMemberKeywordCompletions); + } // Add keywords if this is not a member completion list - if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) { + else if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) { addRange(entries, keywordCompletions); } @@ -411,7 +414,7 @@ namespace ts.Completions { } if (requestJsDocTagName || requestJsDocTag) { - return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag }; + return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords: false }; } if (!insideJsDocTagExpression) { @@ -510,6 +513,7 @@ namespace ts.Completions { let isGlobalCompletion = false; let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; + let hasFilteredClassMemberKeywords = false; let symbols: Symbol[] = []; if (isRightOfDot) { @@ -547,7 +551,7 @@ namespace ts.Completions { log("getCompletionData: Semantic work: " + (timestamp() - semanticStart)); - return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag }; + return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords }; function getTypeScriptMemberSymbols(): void { // Right of dot member completion list @@ -604,6 +608,7 @@ namespace ts.Completions { function tryGetGlobalSymbols(): boolean { let objectLikeContainer: ObjectLiteralExpression | BindingPattern; let namedImportsOrExports: NamedImportsOrExports; + let classLikeContainer: ClassLikeDeclaration; let jsxContainer: JsxOpeningLikeElement; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { @@ -616,6 +621,12 @@ namespace ts.Completions { return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); } + if (classLikeContainer = tryGetClassLikeCompletionContainer(contextToken)) { + // cursor inside class declaration + getGetClassLikeCompletionSymbols(classLikeContainer); + return true; + } + if (jsxContainer = tryGetContainingJsxElement(contextToken)) { let attrsType: Type; if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) { @@ -913,6 +924,62 @@ namespace ts.Completions { return true; } + /** + * Aggregates relevant symbols for completion in class declaration + * Relevant symbols are stored in the captured 'symbols' variable. + */ + function getGetClassLikeCompletionSymbols(classLikeDeclaration: ClassLikeDeclaration) { + // We're looking up possible property names from parent type. + isMemberCompletion = true; + // Declaring new property/method/accessor + isNewIdentifierLocation = true; + // Has keywords for class elements + hasFilteredClassMemberKeywords = true; + + const baseTypeNode = getClassExtendsHeritageClauseElement(classLikeDeclaration); + const implementsTypeNodes = getClassImplementsHeritageClauseElements(classLikeDeclaration); + if (baseTypeNode || implementsTypeNodes) { + const classElement = contextToken.parent; + let classElementModifierFlags = isClassElement(classElement) && getModifierFlags(classElement); + // If this is context token is not something we are editing now, consider if this would lead to be modifier + if (contextToken.kind === SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) { + switch (contextToken.getText()) { + case "private": + classElementModifierFlags = classElementModifierFlags | ModifierFlags.Private; + break; + case "static": + classElementModifierFlags = classElementModifierFlags | ModifierFlags.Static; + break; + } + } + + // No member list for private methods + if (!(classElementModifierFlags & ModifierFlags.Private)) { + let baseClassTypeToGetPropertiesFrom: Type; + if (baseTypeNode) { + baseClassTypeToGetPropertiesFrom = typeChecker.getTypeAtLocation(baseTypeNode); + if (classElementModifierFlags & ModifierFlags.Static) { + // Use static class to get property symbols from + baseClassTypeToGetPropertiesFrom = typeChecker.getTypeOfSymbolAtLocation( + baseClassTypeToGetPropertiesFrom.symbol, classLikeDeclaration); + } + } + const implementedInterfaceTypePropertySymbols = (classElementModifierFlags & ModifierFlags.Static) ? + undefined : + flatMap(implementsTypeNodes, typeNode => typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode))); + + // List of property symbols of base type that are not private and already implemented + symbols = filterClassMembersList( + baseClassTypeToGetPropertiesFrom ? + typeChecker.getPropertiesOfType(baseClassTypeToGetPropertiesFrom) : + undefined, + implementedInterfaceTypePropertySymbols, + classLikeDeclaration.members, + classElementModifierFlags); + } + } + } + /** * Returns the immediate owning object literal or binding pattern of a context token, * on the condition that one exists and that the context implies completion should be given. @@ -953,6 +1020,49 @@ namespace ts.Completions { return undefined; } + function isFromClassElementDeclaration(node: Node) { + return isClassElement(node.parent) && isClassLike(node.parent.parent); + } + + /** + * Returns the immediate owning class declaration of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetClassLikeCompletionContainer(contextToken: Node): ClassLikeDeclaration { + if (contextToken) { + switch (contextToken.kind) { + case SyntaxKind.OpenBraceToken: // class c { | + if (isClassLike(contextToken.parent)) { + return contextToken.parent; + } + break; + + // class c {getValue(): number; | } + case SyntaxKind.CommaToken: + case SyntaxKind.SemicolonToken: + // class c { method() { } | } + case SyntaxKind.CloseBraceToken: + if (isClassLike(location)) { + return location; + } + break; + + default: + if (isFromClassElementDeclaration(contextToken) && + (isClassMemberCompletionKeyword(contextToken.kind) || + isClassMemberCompletionKeywordText(contextToken.getText()))) { + return contextToken.parent.parent as ClassLikeDeclaration; + } + } + } + + // class c { method() { } | method2() { } } + if (location && location.kind === SyntaxKind.SyntaxList && isClassLike(location.parent)) { + return location.parent; + } + return undefined; + } + function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { const parent = contextToken.parent; @@ -1081,7 +1191,7 @@ namespace ts.Completions { isFunction(containingNodeKind); case SyntaxKind.StaticKeyword: - return containingNodeKind === SyntaxKind.PropertyDeclaration; + return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(contextToken.parent.parent); case SyntaxKind.DotDotDotToken: return containingNodeKind === SyntaxKind.Parameter || @@ -1098,13 +1208,17 @@ namespace ts.Completions { containingNodeKind === SyntaxKind.ExportSpecifier || containingNodeKind === SyntaxKind.NamespaceImport; + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: + if (isFromClassElementDeclaration(contextToken)) { + return false; + } + // falls through case SyntaxKind.ClassKeyword: case SyntaxKind.EnumKeyword: case SyntaxKind.InterfaceKeyword: case SyntaxKind.FunctionKeyword: case SyntaxKind.VarKeyword: - case SyntaxKind.GetKeyword: - case SyntaxKind.SetKeyword: case SyntaxKind.ImportKeyword: case SyntaxKind.LetKeyword: case SyntaxKind.ConstKeyword: @@ -1113,6 +1227,13 @@ namespace ts.Completions { return true; } + // If the previous token is keyword correspoding to class member completion keyword + // there will be completion available here + if (isClassMemberCompletionKeywordText(contextToken.getText()) && + isFromClassElementDeclaration(contextToken)) { + return false; + } + // Previous token may have been a keyword that was converted to an identifier. switch (contextToken.getText()) { case "abstract": @@ -1159,7 +1280,7 @@ namespace ts.Completions { for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out - if (element.getStart() <= position && position <= element.getEnd()) { + if (isCurrentlyEditingNode(element)) { continue; } @@ -1198,7 +1319,7 @@ namespace ts.Completions { } // If this is the current item we are editing right now, do not filter it out - if (m.getStart() <= position && position <= m.getEnd()) { + if (isCurrentlyEditingNode(m)) { continue; } @@ -1223,6 +1344,58 @@ namespace ts.Completions { return filter(contextualMemberSymbols, m => !existingMemberNames.get(m.name)); } + /** + * Filters out completion suggestions for class elements. + * + * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags + */ + function filterClassMembersList(baseSymbols: Symbol[], implementingTypeSymbols: Symbol[], existingMembers: ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { + const existingMemberNames = createMap(); + for (const m of existingMembers) { + // Ignore omitted expressions for missing members + if (m.kind !== SyntaxKind.PropertyDeclaration && + m.kind !== SyntaxKind.MethodDeclaration && + m.kind !== SyntaxKind.GetAccessor && + m.kind !== SyntaxKind.SetAccessor) { + continue; + } + + // If this is the current item we are editing right now, do not filter it out + if (isCurrentlyEditingNode(m)) { + continue; + } + + // Dont filter member even if the name matches if it is declared private in the list + if (hasModifier(m, ModifierFlags.Private)) { + continue; + } + + // do not filter it out if the static presence doesnt match + const mIsStatic = hasModifier(m, ModifierFlags.Static); + const currentElementIsStatic = !!(currentClassElementModifierFlags & ModifierFlags.Static); + if ((mIsStatic && !currentElementIsStatic) || + (!mIsStatic && currentElementIsStatic)) { + continue; + } + + const existingName = getPropertyNameForPropertyNameNode(m.name); + if (existingName) { + existingMemberNames.set(existingName, true); + } + } + + return concatenate( + filter(baseSymbols, baseProperty => isValidProperty(baseProperty, ModifierFlags.Private)), + filter(implementingTypeSymbols, implementingProperty => isValidProperty(implementingProperty, ModifierFlags.NonPublicAccessibilityModifier)) + ); + + function isValidProperty(propertySymbol: Symbol, inValidModifierFlags: ModifierFlags) { + return !existingMemberNames.get(propertySymbol.name) && + propertySymbol.getDeclarations() && + !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & inValidModifierFlags); + } + } + /** * Filters out completion suggestions from 'symbols' according to existing JSX attributes. * @@ -1233,7 +1406,7 @@ namespace ts.Completions { const seenNames = createMap(); for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out - if (attr.getStart() <= position && position <= attr.getEnd()) { + if (isCurrentlyEditingNode(attr)) { continue; } @@ -1244,6 +1417,10 @@ namespace ts.Completions { return filter(symbols, a => !seenNames.get(a.name)); } + + function isCurrentlyEditingNode(node: Node): boolean { + return node.getStart() <= position && position <= node.getEnd(); + } } /** @@ -1306,6 +1483,29 @@ namespace ts.Completions { }); } + function isClassMemberCompletionKeyword(kind: SyntaxKind) { + switch (kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ConstructorKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: + case SyntaxKind.AsyncKeyword: + return true; + } + } + + function isClassMemberCompletionKeywordText(text: string) { + return isClassMemberCompletionKeyword(stringToToken(text)); + } + + const classMemberKeywordCompletions = filter(keywordCompletions, entry => + isClassMemberCompletionKeywordText(entry.name)); + function isEqualityExpression(node: Node): node is BinaryExpression { return isBinaryExpression(node) && isEqualityOperatorKind(node.operatorToken.kind); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 395c282f6d..d9deaef9e5 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -550,7 +550,7 @@ namespace ts.FindAllReferences.Core { } function isObjectBindingPatternElementWithoutPropertyName(symbol: Symbol): boolean { - const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); + const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); return bindingElement && bindingElement.parent.kind === SyntaxKind.ObjectBindingPattern && !bindingElement.propertyName; @@ -558,7 +558,7 @@ namespace ts.FindAllReferences.Core { function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined { if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); + const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); return typeOfPattern && checker.getPropertyOfType(typeOfPattern, (bindingElement.name).text); } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index df50f3ec31..c540c44620 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -526,17 +526,18 @@ namespace ts.FindAllReferences { return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } - function symbolName(symbol: Symbol): string { + function symbolName(symbol: Symbol): string | undefined { if (symbol.name !== "default") { return symbol.name; } - const name = forEach(symbol.declarations, decl => { + return forEach(symbol.declarations, decl => { + if (isExportAssignment(decl)) { + return isIdentifier(decl.expression) ? decl.expression.text : undefined; + } const name = getNameOfDeclaration(decl); return name && name.kind === SyntaxKind.Identifier && name.text; }); - Debug.assert(!!name); - return name; } /** If at an export specifier, go to the symbol it refers to. */ diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 5bf3e37f28..71dc7b7813 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -200,27 +200,33 @@ namespace ts.SymbolDisplay { (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it const functionDeclaration = location.parent; - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); - if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); - } - else { - signature = allSignatures[0]; - } + // Use function declaration to write the signatures only if the symbol corresponding to this declaration + const locationIsSymbolDeclaration = findDeclaration(symbol, declaration => + declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); - if (functionDeclaration.kind === SyntaxKind.Constructor) { - // show (constructor) Type(...) signature - symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else { - // (function/method) symbol(..signature) - addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && - !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); - } + if (locationIsSymbolDeclaration) { + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); + } + else { + signature = allSignatures[0]; + } - addSignatureDisplayParts(signature, allSignatures); - hasAddedSymbolInfo = true; + if (functionDeclaration.kind === SyntaxKind.Constructor) { + // show (constructor) Type(...) signature + symbolKind = ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else { + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && + !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); + } + + addSignatureDisplayParts(signature, allSignatures); + hasAddedSymbolInfo = true; + } } } } @@ -269,7 +275,7 @@ namespace ts.SymbolDisplay { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); @@ -290,9 +296,9 @@ namespace ts.SymbolDisplay { } else { // Method/function type parameter - let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); - Debug.assert(declaration !== undefined); - declaration = declaration.parent; + const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); + Debug.assert(decl !== undefined); + const declaration = decl.parent; if (declaration) { if (isFunctionLikeKind(declaration.kind)) { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4ae9204f7e..ed28daf019 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -651,44 +651,26 @@ namespace ts { return current; } - if (includeJsDocComment) { - const jsDocChildren = ts.filter(current.getChildren(), isJSDocNode); - for (const jsDocChild of jsDocChildren) { - const start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - const end = jsDocChild.getEnd(); - if (position < end || (position === end && jsDocChild.kind === SyntaxKind.EndOfFileToken)) { - current = jsDocChild; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - const previousToken = findPrecedingToken(position, sourceFile, jsDocChild); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } - } - } - } - } - // find the child that contains 'position' for (const child of current.getChildren()) { - // all jsDocComment nodes were already visited - if (isJSDocNode(child)) { + if (isJSDocNode(child) && !includeJsDocComment) { continue; } + const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - const end = child.getEnd(); - if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) { - current = child; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - const previousToken = findPrecedingToken(position, sourceFile, child); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } + if (start > position) { + continue; + } + + const end = child.getEnd(); + if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) { + current = child; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + const previousToken = findPrecedingToken(position, sourceFile, child); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; } } } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 5f1b97b208..d91571f93a 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -128,8 +128,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -169,8 +169,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; class C5 { f() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index 1fa1b19e36..cfd7c9725e 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -264,8 +264,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -354,8 +354,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index 98e8291ac6..4ca8322da9 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -91,8 +91,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -130,8 +130,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; function f5() { return __asyncGenerator(this, arguments, function* f5_1() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index f842a2c813..410a25d2e1 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -218,8 +218,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -303,8 +303,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index d491c0465f..602fd47d38 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -91,8 +91,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -130,8 +130,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; const f5 = function () { return __asyncGenerator(this, arguments, function* () { diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index 779d9c5340..45d17737ce 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -218,8 +218,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -303,8 +303,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 22ffff01ee..760931a434 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -111,8 +111,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -152,8 +152,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; const o5 = { f() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 46f3a1efac..b5069bcea2 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -238,8 +238,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -325,8 +325,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt b/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt index aea5366389..64e1830b52 100644 --- a/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt +++ b/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt @@ -1,14 +1,11 @@ tests/cases/compiler/enumUsedBeforeDeclaration.ts(1,18): error TS2450: Enum 'Color' used before its declaration. -tests/cases/compiler/enumUsedBeforeDeclaration.ts(2,24): error TS2450: Enum 'ConstColor' used before its declaration. -==== tests/cases/compiler/enumUsedBeforeDeclaration.ts (2 errors) ==== +==== tests/cases/compiler/enumUsedBeforeDeclaration.ts (1 errors) ==== const v: Color = Color.Green; ~~~~~ !!! error TS2450: Enum 'Color' used before its declaration. const v2: ConstColor = ConstColor.Green; - ~~~~~~~~~~ -!!! error TS2450: Enum 'ConstColor' used before its declaration. enum Color { Red, Green, Blue } const enum ConstColor { Red, Green, Blue } diff --git a/tests/baselines/reference/tsxAttributeResolution5.errors.txt b/tests/baselines/reference/tsxAttributeResolution5.errors.txt index 0c6be5f35d..f5af99d6f0 100644 --- a/tests/baselines/reference/tsxAttributeResolution5.errors.txt +++ b/tests/baselines/reference/tsxAttributeResolution5.errors.txt @@ -1,8 +1,10 @@ -tests/cases/conformance/jsx/file.tsx(21,16): error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. - Types of property 'x' are incompatible. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/jsx/file.tsx(25,16): error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. - Property 'x' is missing in type '{ y: string; }'. +tests/cases/conformance/jsx/file.tsx(21,16): error TS2322: Type 'T' is not assignable to type 'Attribs1'. + Type '{ x: number; }' is not assignable to type 'Attribs1'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsx/file.tsx(25,16): error TS2322: Type 'T' is not assignable to type 'Attribs1'. + Type '{ y: string; }' is not assignable to type 'Attribs1'. + Property 'x' is missing in type '{ y: string; }'. tests/cases/conformance/jsx/file.tsx(29,8): error TS2322: Type '{}' is not assignable to type 'Attribs1'. Property 'x' is missing in type '{}'. @@ -30,16 +32,18 @@ tests/cases/conformance/jsx/file.tsx(29,8): error TS2322: Type '{}' is not assig function make2 (obj: T) { return ; // Error (x is number, not string) ~~~~~~~~ -!!! error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. -!!! error TS2322: Types of property 'x' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Type 'T' is not assignable to type 'Attribs1'. +!!! error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. } function make3 (obj: T) { return ; // Error, missing x ~~~~~~~~ -!!! error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. -!!! error TS2322: Property 'x' is missing in type '{ y: string; }'. +!!! error TS2322: Type 'T' is not assignable to type 'Attribs1'. +!!! error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. +!!! error TS2322: Property 'x' is missing in type '{ y: string; }'. } diff --git a/tests/baselines/reference/tsxGenericAttributesType1.js b/tests/baselines/reference/tsxGenericAttributesType1.js new file mode 100644 index 0000000000..5d3d388396 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType1.js @@ -0,0 +1,28 @@ +//// [file.tsx] +import React = require('react'); + +const decorator = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +const decorator2 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +const decorator3 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +//// [file.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +var decorator = function (Component) { + return function (props) { return ; }; +}; +var decorator2 = function (Component) { + return function (props) { return ; }; +}; +var decorator3 = function (Component) { + return function (props) { return ; }; +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType1.symbols b/tests/baselines/reference/tsxGenericAttributesType1.symbols new file mode 100644 index 0000000000..473de9b5c7 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType1.symbols @@ -0,0 +1,66 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +const decorator = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator : Symbol(decorator, Decl(file.tsx, 2, 5)) +>T : Symbol(T, Decl(file.tsx, 2, 28)) +>Component : Symbol(Component, Decl(file.tsx, 2, 31)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 2, 28)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 2, 28)) + + return (props) => +>props : Symbol(props, Decl(file.tsx, 3, 12)) +>Component : Symbol(Component, Decl(file.tsx, 2, 31)) +>props : Symbol(props, Decl(file.tsx, 3, 12)) +>Component : Symbol(Component, Decl(file.tsx, 2, 31)) + +}; + +const decorator2 = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator2 : Symbol(decorator2, Decl(file.tsx, 6, 5)) +>T : Symbol(T, Decl(file.tsx, 6, 29)) +>x : Symbol(x, Decl(file.tsx, 6, 40)) +>Component : Symbol(Component, Decl(file.tsx, 6, 54)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 6, 29)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 6, 29)) + + return (props) => +>props : Symbol(props, Decl(file.tsx, 7, 12)) +>Component : Symbol(Component, Decl(file.tsx, 6, 54)) +>props : Symbol(props, Decl(file.tsx, 7, 12)) +>x : Symbol(x, Decl(file.tsx, 7, 43)) +>Component : Symbol(Component, Decl(file.tsx, 6, 54)) + +}; + +const decorator3 = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator3 : Symbol(decorator3, Decl(file.tsx, 10, 5)) +>T : Symbol(T, Decl(file.tsx, 10, 29)) +>x : Symbol(x, Decl(file.tsx, 10, 40)) +>U : Symbol(U, Decl(file.tsx, 10, 53)) +>x : Symbol(x, Decl(file.tsx, 10, 65)) +>Component : Symbol(Component, Decl(file.tsx, 10, 80)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 10, 29)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) +>T : Symbol(T, Decl(file.tsx, 10, 29)) + + return (props) => +>props : Symbol(props, Decl(file.tsx, 11, 12)) +>Component : Symbol(Component, Decl(file.tsx, 10, 80)) +>x : Symbol(x, Decl(file.tsx, 11, 32)) +>props : Symbol(props, Decl(file.tsx, 11, 12)) +>Component : Symbol(Component, Decl(file.tsx, 10, 80)) + +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType1.types b/tests/baselines/reference/tsxGenericAttributesType1.types new file mode 100644 index 0000000000..50be358302 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType1.types @@ -0,0 +1,77 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +const decorator = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator : (Component: React.StatelessComponent) => React.StatelessComponent +>function (Component: React.StatelessComponent): React.StatelessComponent { return (props) => } : (Component: React.StatelessComponent) => React.StatelessComponent +>T : T +>Component : React.StatelessComponent +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T + + return (props) => +>(props) => : (props: T & { children?: React.ReactNode; }) => JSX.Element +>props : T & { children?: React.ReactNode; } +> : JSX.Element +>Component : React.StatelessComponent +>props : T & { children?: React.ReactNode; } +>Component : React.StatelessComponent + +}; + +const decorator2 = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator2 : (Component: React.StatelessComponent) => React.StatelessComponent +>function (Component: React.StatelessComponent): React.StatelessComponent { return (props) => } : (Component: React.StatelessComponent) => React.StatelessComponent +>T : T +>x : number +>Component : React.StatelessComponent +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T + + return (props) => +>(props) => : (props: T & { children?: React.ReactNode; }) => JSX.Element +>props : T & { children?: React.ReactNode; } +> : JSX.Element +>Component : React.StatelessComponent +>props : T & { children?: React.ReactNode; } +>x : number +>2 : 2 +>Component : React.StatelessComponent + +}; + +const decorator3 = function (Component: React.StatelessComponent): React.StatelessComponent { +>decorator3 : (Component: React.StatelessComponent) => React.StatelessComponent +>function (Component: React.StatelessComponent): React.StatelessComponent { return (props) => } : (Component: React.StatelessComponent) => React.StatelessComponent +>T : T +>x : number +>U : U +>x : number +>Component : React.StatelessComponent +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T +>React : any +>StatelessComponent : React.StatelessComponent

+>T : T + + return (props) => +>(props) => : (props: T & { children?: React.ReactNode; }) => JSX.Element +>props : T & { children?: React.ReactNode; } +> : JSX.Element +>Component : React.StatelessComponent +>x : number +>2 : 2 +>props : T & { children?: React.ReactNode; } +>Component : React.StatelessComponent + +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType2.errors.txt b/tests/baselines/reference/tsxGenericAttributesType2.errors.txt new file mode 100644 index 0000000000..cbd926c9b6 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType2.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/jsx/file.tsx(4,45): error TS2339: Property 'y' does not exist on type 'IntrinsicAttributes & { x: number; } & { children?: ReactNode; }'. + + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + import React = require('react'); + + const decorator4 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => + ~~~~~~~~~~ +!!! error TS2339: Property 'y' does not exist on type 'IntrinsicAttributes & { x: number; } & { children?: ReactNode; }'. + }; \ No newline at end of file diff --git a/tests/baselines/reference/tsxGenericAttributesType2.js b/tests/baselines/reference/tsxGenericAttributesType2.js new file mode 100644 index 0000000000..7b46d08c2c --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType2.js @@ -0,0 +1,14 @@ +//// [file.tsx] +import React = require('react'); + +const decorator4 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +//// [file.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +var decorator4 = function (Component) { + return function (props) { return ; }; +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType3.js b/tests/baselines/reference/tsxGenericAttributesType3.js new file mode 100644 index 0000000000..51491d99aa --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType3.js @@ -0,0 +1,48 @@ +//// [file.tsx] +import React = require('react'); + +class B1 extends React.Component { + render() { + return

hi
; + } +} +class B extends React.Component { + render() { + return ; + } +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +var B1 = (function (_super) { + __extends(B1, _super); + function B1() { + return _super !== null && _super.apply(this, arguments) || this; + } + B1.prototype.render = function () { + return
hi
; + }; + return B1; +}(React.Component)); +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + B.prototype.render = function () { + return ; + }; + return B; +}(React.Component)); diff --git a/tests/baselines/reference/tsxGenericAttributesType3.symbols b/tests/baselines/reference/tsxGenericAttributesType3.symbols new file mode 100644 index 0000000000..8c235257e8 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType3.symbols @@ -0,0 +1,41 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +class B1 extends React.Component { +>B1 : Symbol(B1, Decl(file.tsx, 0, 32)) +>T : Symbol(T, Decl(file.tsx, 2, 9)) +>x : Symbol(x, Decl(file.tsx, 2, 20)) +>x : Symbol(x, Decl(file.tsx, 2, 36)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>T : Symbol(T, Decl(file.tsx, 2, 9)) + + render() { +>render : Symbol(B1.render, Decl(file.tsx, 2, 82)) + + return
hi
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + } +} +class B extends React.Component { +>B : Symbol(B, Decl(file.tsx, 6, 1)) +>U : Symbol(U, Decl(file.tsx, 7, 8)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>U : Symbol(U, Decl(file.tsx, 7, 8)) + + render() { +>render : Symbol(B.render, Decl(file.tsx, 7, 43)) + + return ; +>B1 : Symbol(B1, Decl(file.tsx, 0, 32)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this : Symbol(B, Decl(file.tsx, 6, 1)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>x : Symbol(x, Decl(file.tsx, 9, 34)) + } +} diff --git a/tests/baselines/reference/tsxGenericAttributesType3.types b/tests/baselines/reference/tsxGenericAttributesType3.types new file mode 100644 index 0000000000..72674ac5bf --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType3.types @@ -0,0 +1,43 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +class B1 extends React.Component { +>B1 : B1 +>T : T +>x : string +>x : string +>React.Component : React.Component +>React : typeof React +>Component : typeof React.Component +>T : T + + render() { +>render : () => JSX.Element + + return
hi
; +>
hi
: JSX.Element +>div : any +>div : any + } +} +class B extends React.Component { +>B : B +>U : U +>React.Component : React.Component +>React : typeof React +>Component : typeof React.Component +>U : U + + render() { +>render : () => JSX.Element + + return ; +> : JSX.Element +>B1 : typeof B1 +>this.props : U & { children?: React.ReactNode; } +>this : this +>props : U & { children?: React.ReactNode; } +>x : string + } +} diff --git a/tests/baselines/reference/tsxGenericAttributesType4.errors.txt b/tests/baselines/reference/tsxGenericAttributesType4.errors.txt new file mode 100644 index 0000000000..ee91f938b9 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType4.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/jsx/file.tsx(11,36): error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes> & { children?: ReactNode; }'. + + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + import React = require('react'); + + class B1 extends React.Component { + render() { + return
hi
; + } + } + class B extends React.Component { + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + ~~~~~~ +!!! error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes> & { children?: ReactNode; }'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/tsxGenericAttributesType4.js b/tests/baselines/reference/tsxGenericAttributesType4.js new file mode 100644 index 0000000000..a00d03cd61 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType4.js @@ -0,0 +1,50 @@ +//// [file.tsx] +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + } +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +var B1 = (function (_super) { + __extends(B1, _super); + function B1() { + return _super !== null && _super.apply(this, arguments) || this; + } + B1.prototype.render = function () { + return
hi
; + }; + return B1; +}(React.Component)); +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + B.prototype.render = function () { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + }; + return B; +}(React.Component)); diff --git a/tests/baselines/reference/tsxGenericAttributesType5.errors.txt b/tests/baselines/reference/tsxGenericAttributesType5.errors.txt new file mode 100644 index 0000000000..83f07326f9 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType5.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/jsx/file.tsx(12,36): error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes> & { children?: ReactNode; }'. + + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + import React = require('react'); + + class B1 extends React.Component { + render() { + return
hi
; + } + } + class B extends React.Component { + props: U; + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + ~~~~~~ +!!! error TS2339: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes> & { children?: ReactNode; }'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/tsxGenericAttributesType5.js b/tests/baselines/reference/tsxGenericAttributesType5.js new file mode 100644 index 0000000000..cb535417dd --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType5.js @@ -0,0 +1,51 @@ +//// [file.tsx] +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + props: U; + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + } +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +var B1 = (function (_super) { + __extends(B1, _super); + function B1() { + return _super !== null && _super.apply(this, arguments) || this; + } + B1.prototype.render = function () { + return
hi
; + }; + return B1; +}(React.Component)); +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + B.prototype.render = function () { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + }; + return B; +}(React.Component)); diff --git a/tests/baselines/reference/tsxGenericAttributesType6.js b/tests/baselines/reference/tsxGenericAttributesType6.js new file mode 100644 index 0000000000..84cab3e1f9 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType6.js @@ -0,0 +1,49 @@ +//// [file.tsx] +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + props: U; + render() { + return ; + } +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +var B1 = (function (_super) { + __extends(B1, _super); + function B1() { + return _super !== null && _super.apply(this, arguments) || this; + } + B1.prototype.render = function () { + return
hi
; + }; + return B1; +}(React.Component)); +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + B.prototype.render = function () { + return ; + }; + return B; +}(React.Component)); diff --git a/tests/baselines/reference/tsxGenericAttributesType6.symbols b/tests/baselines/reference/tsxGenericAttributesType6.symbols new file mode 100644 index 0000000000..27c8ed2d6d --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType6.symbols @@ -0,0 +1,45 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +class B1 extends React.Component { +>B1 : Symbol(B1, Decl(file.tsx, 0, 32)) +>T : Symbol(T, Decl(file.tsx, 2, 9)) +>x : Symbol(x, Decl(file.tsx, 2, 20)) +>x : Symbol(x, Decl(file.tsx, 2, 36)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>T : Symbol(T, Decl(file.tsx, 2, 9)) + + render() { +>render : Symbol(B1.render, Decl(file.tsx, 2, 82)) + + return
hi
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + } +} +class B extends React.Component { +>B : Symbol(B, Decl(file.tsx, 6, 1)) +>U : Symbol(U, Decl(file.tsx, 7, 8)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>U : Symbol(U, Decl(file.tsx, 7, 8)) + + props: U; +>props : Symbol(B.props, Decl(file.tsx, 7, 43)) +>U : Symbol(U, Decl(file.tsx, 7, 8)) + + render() { +>render : Symbol(B.render, Decl(file.tsx, 8, 13)) + + return ; +>B1 : Symbol(B1, Decl(file.tsx, 0, 32)) +>this.props : Symbol(B.props, Decl(file.tsx, 7, 43)) +>this : Symbol(B, Decl(file.tsx, 6, 1)) +>props : Symbol(B.props, Decl(file.tsx, 7, 43)) +>x : Symbol(x, Decl(file.tsx, 10, 34)) + } +} diff --git a/tests/baselines/reference/tsxGenericAttributesType6.types b/tests/baselines/reference/tsxGenericAttributesType6.types new file mode 100644 index 0000000000..662b6299da --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType6.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +class B1 extends React.Component { +>B1 : B1 +>T : T +>x : string +>x : string +>React.Component : React.Component +>React : typeof React +>Component : typeof React.Component +>T : T + + render() { +>render : () => JSX.Element + + return
hi
; +>
hi
: JSX.Element +>div : any +>div : any + } +} +class B extends React.Component { +>B : B +>U : U +>React.Component : React.Component +>React : typeof React +>Component : typeof React.Component +>U : U + + props: U; +>props : U +>U : U + + render() { +>render : () => JSX.Element + + return ; +> : JSX.Element +>B1 : typeof B1 +>this.props : U +>this : this +>props : U +>x : string + } +} diff --git a/tests/baselines/reference/tsxGenericAttributesType7.js b/tests/baselines/reference/tsxGenericAttributesType7.js new file mode 100644 index 0000000000..4e254f25e5 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType7.js @@ -0,0 +1,22 @@ +//// [file.tsx] +import React = require('react'); + +declare function Component(props: T) : JSX.Element; +const decorator = function (props: U) { + return ; +} + +const decorator1 = function (props: U) { + return ; +} + +//// [file.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +var decorator = function (props) { + return ; +}; +var decorator1 = function (props) { + return ; +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType7.symbols b/tests/baselines/reference/tsxGenericAttributesType7.symbols new file mode 100644 index 0000000000..e31042bd84 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType7.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +declare function Component(props: T) : JSX.Element; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>T : Symbol(T, Decl(file.tsx, 2, 27)) +>props : Symbol(props, Decl(file.tsx, 2, 30)) +>T : Symbol(T, Decl(file.tsx, 2, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) + +const decorator = function (props: U) { +>decorator : Symbol(decorator, Decl(file.tsx, 3, 5)) +>U : Symbol(U, Decl(file.tsx, 3, 28)) +>props : Symbol(props, Decl(file.tsx, 3, 31)) +>U : Symbol(U, Decl(file.tsx, 3, 28)) + + return ; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>props : Symbol(props, Decl(file.tsx, 3, 31)) +} + +const decorator1 = function (props: U) { +>decorator1 : Symbol(decorator1, Decl(file.tsx, 7, 5)) +>U : Symbol(U, Decl(file.tsx, 7, 29)) +>x : Symbol(x, Decl(file.tsx, 7, 40)) +>props : Symbol(props, Decl(file.tsx, 7, 52)) +>U : Symbol(U, Decl(file.tsx, 7, 29)) + + return ; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>props : Symbol(props, Decl(file.tsx, 7, 52)) +>x : Symbol(x, Decl(file.tsx, 8, 32)) +} diff --git a/tests/baselines/reference/tsxGenericAttributesType7.types b/tests/baselines/reference/tsxGenericAttributesType7.types new file mode 100644 index 0000000000..58d853e488 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType7.types @@ -0,0 +1,39 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +declare function Component(props: T) : JSX.Element; +>Component : (props: T) => JSX.Element +>T : T +>props : T +>T : T +>JSX : any +>Element : JSX.Element + +const decorator = function (props: U) { +>decorator : (props: U) => JSX.Element +>function (props: U) { return ;} : (props: U) => JSX.Element +>U : U +>props : U +>U : U + + return ; +> : JSX.Element +>Component : (props: T) => JSX.Element +>props : U +} + +const decorator1 = function (props: U) { +>decorator1 : (props: U) => JSX.Element +>function (props: U) { return ;} : (props: U) => JSX.Element +>U : U +>x : string +>props : U +>U : U + + return ; +> : JSX.Element +>Component : (props: T) => JSX.Element +>props : U +>x : string +} diff --git a/tests/baselines/reference/tsxGenericAttributesType8.js b/tests/baselines/reference/tsxGenericAttributesType8.js new file mode 100644 index 0000000000..435bf425c6 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType8.js @@ -0,0 +1,22 @@ +//// [file.tsx] +import React = require('react'); + +declare function Component(props: T) : JSX.Element; +const decorator = function (props: U) { + return ; +} + +const decorator1 = function (props: U) { + return ; +} + +//// [file.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +var decorator = function (props) { + return ; +}; +var decorator1 = function (props) { + return ; +}; diff --git a/tests/baselines/reference/tsxGenericAttributesType8.symbols b/tests/baselines/reference/tsxGenericAttributesType8.symbols new file mode 100644 index 0000000000..516dbe9c32 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType8.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +declare function Component(props: T) : JSX.Element; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>T : Symbol(T, Decl(file.tsx, 2, 27)) +>props : Symbol(props, Decl(file.tsx, 2, 30)) +>T : Symbol(T, Decl(file.tsx, 2, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) + +const decorator = function (props: U) { +>decorator : Symbol(decorator, Decl(file.tsx, 3, 5)) +>U : Symbol(U, Decl(file.tsx, 3, 28)) +>props : Symbol(props, Decl(file.tsx, 3, 31)) +>U : Symbol(U, Decl(file.tsx, 3, 28)) + + return ; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>props : Symbol(props, Decl(file.tsx, 3, 31)) +} + +const decorator1 = function (props: U) { +>decorator1 : Symbol(decorator1, Decl(file.tsx, 7, 5)) +>U : Symbol(U, Decl(file.tsx, 7, 29)) +>x : Symbol(x, Decl(file.tsx, 7, 40)) +>props : Symbol(props, Decl(file.tsx, 7, 52)) +>U : Symbol(U, Decl(file.tsx, 7, 29)) + + return ; +>Component : Symbol(Component, Decl(file.tsx, 0, 32)) +>props : Symbol(props, Decl(file.tsx, 7, 52)) +} diff --git a/tests/baselines/reference/tsxGenericAttributesType8.types b/tests/baselines/reference/tsxGenericAttributesType8.types new file mode 100644 index 0000000000..b2a62a575f --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType8.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +declare function Component(props: T) : JSX.Element; +>Component : (props: T) => JSX.Element +>T : T +>props : T +>T : T +>JSX : any +>Element : JSX.Element + +const decorator = function (props: U) { +>decorator : (props: U) => JSX.Element +>function (props: U) { return ;} : (props: U) => JSX.Element +>U : U +>props : U +>U : U + + return ; +> : JSX.Element +>Component : (props: T) => JSX.Element +>props : U +} + +const decorator1 = function (props: U) { +>decorator1 : (props: U) => JSX.Element +>function (props: U) { return ;} : (props: U) => JSX.Element +>U : U +>x : string +>props : U +>U : U + + return ; +> : JSX.Element +>Component : (props: T) => JSX.Element +>props : U +} diff --git a/tests/baselines/reference/tsxGenericAttributesType9.js b/tests/baselines/reference/tsxGenericAttributesType9.js new file mode 100644 index 0000000000..b7b90736ad --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.js @@ -0,0 +1,40 @@ +//// [file.tsx] +import React = require('react'); + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ + return class extends React.PureComponent { + public render(): JSX.Element { + return ( + + ); + } + }; +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +function makeP(Ctor) { + return (function (_super) { + __extends(class_1, _super); + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + class_1.prototype.render = function () { + return (); + }; + return class_1; + }(React.PureComponent)); +} +exports.makeP = makeP; diff --git a/tests/baselines/reference/tsxGenericAttributesType9.symbols b/tests/baselines/reference/tsxGenericAttributesType9.symbols new file mode 100644 index 0000000000..f4df2e7940 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ +>makeP : Symbol(makeP, Decl(file.tsx, 0, 32)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) +>Ctor : Symbol(Ctor, Decl(file.tsx, 2, 25)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>ComponentClass : Symbol(React.ComponentClass, Decl(react.d.ts, 204, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>ComponentClass : Symbol(React.ComponentClass, Decl(react.d.ts, 204, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) + + return class extends React.PureComponent { +>React.PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 179, 5)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 179, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) + + public render(): JSX.Element { +>render : Symbol((Anonymous class).render, Decl(file.tsx, 3, 52)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) + + return ( + +>Ctor : Symbol(Ctor, Decl(file.tsx, 2, 25)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this : Symbol((Anonymous class), Decl(file.tsx, 3, 7)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) + + ); + } + }; +} diff --git a/tests/baselines/reference/tsxGenericAttributesType9.types b/tests/baselines/reference/tsxGenericAttributesType9.types new file mode 100644 index 0000000000..a1d7efc49b --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ +>makeP :

(Ctor: React.ComponentClass

) => React.ComponentClass

+>P : P +>Ctor : React.ComponentClass

+>React : any +>ComponentClass : React.ComponentClass

+>P : P +>React : any +>ComponentClass : React.ComponentClass

+>P : P + + return class extends React.PureComponent { +>class extends React.PureComponent { public render(): JSX.Element { return ( ); } } : typeof (Anonymous class) +>React.PureComponent : React.PureComponent +>React : typeof React +>PureComponent : typeof React.PureComponent +>P : P + + public render(): JSX.Element { +>render : () => JSX.Element +>JSX : any +>Element : JSX.Element + + return ( +>( ) : JSX.Element + + +> : JSX.Element +>Ctor : React.ComponentClass

+>this.props : P & { children?: React.ReactNode; } +>this : this +>props : P & { children?: React.ReactNode; } + + ); + } + }; +} diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.types b/tests/baselines/reference/tsxStatelessFunctionComponents3.types index 714781058e..879f8c75cd 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponents3.types +++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.types @@ -21,8 +21,8 @@ var MainMenu: React.StatelessComponent<{}> = (props) => (

>MainMenu : React.StatelessComponent<{}> >React : any >StatelessComponent : React.StatelessComponent

->(props) => (

Main Menu

) : (props: {}) => JSX.Element ->props : {} +>(props) => (

Main Menu

) : (props: { children?: React.ReactNode; }) => JSX.Element +>props : { children?: React.ReactNode; } >(

Main Menu

) : JSX.Element >

Main Menu

: JSX.Element >div : any @@ -40,7 +40,7 @@ var App: React.StatelessComponent<{ children }> = ({children}) => ( >React : any >StatelessComponent : React.StatelessComponent

>children : any ->({children}) => (

) : ({children}: { children: any; }) => JSX.Element +>({children}) => (
) : ({children}: { children: any; } & { children?: React.ReactNode; }) => JSX.Element >children : any >(
) : JSX.Element diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt index c8ff457711..7e94011688 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt @@ -1,10 +1,9 @@ -tests/cases/conformance/jsx/file.tsx(8,34): error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. - Type '{ ignore-prop: 10; prop: number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. +tests/cases/conformance/jsx/file.tsx(8,34): error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. + Type 'T & { ignore-prop: 10; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. Types of property '"ignore-prop"' are incompatible. Type '10' is not assignable to type 'string'. -tests/cases/conformance/jsx/file.tsx(13,34): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. - Type '{}' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. - Property 'prop' is missing in type '{}'. +tests/cases/conformance/jsx/file.tsx(13,34): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. + Type 'T' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. tests/cases/conformance/jsx/file.tsx(20,19): error TS2322: Type '{ func: (a: number, b: string) => void; }' is not assignable to type 'IntrinsicAttributes & { func: (arg: number) => void; }'. Type '{ func: (a: number, b: string) => void; }' is not assignable to type '{ func: (arg: number) => void; }'. Types of property 'func' are incompatible. @@ -25,8 +24,8 @@ tests/cases/conformance/jsx/file.tsx(31,10): error TS2453: The type argument for function Bar(arg: T) { let a1 = ; ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. -!!! error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. +!!! error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. +!!! error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. !!! error TS2322: Types of property '"ignore-prop"' are incompatible. !!! error TS2322: Type '10' is not assignable to type 'string'. } @@ -35,9 +34,8 @@ tests/cases/conformance/jsx/file.tsx(31,10): error TS2453: The type argument for function Baz(arg: T) { let a0 = ~~~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. -!!! error TS2322: Type '{}' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. -!!! error TS2322: Property 'prop' is missing in type '{}'. +!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. +!!! error TS2322: Type 'T' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. } declare function Link(l: {func: (arg: U)=>void}): JSX.Element; diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt index d9b50ef31c..311cfaed86 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt @@ -1,9 +1,12 @@ tests/cases/conformance/jsx/file.tsx(9,33): error TS2322: Type '{ a: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: number; }'. Type '{ a: number; }' is not assignable to type '{ b: {}; a: number; }'. Property 'b' is missing in type '{ a: number; }'. -tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. - Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. - Property 'a' is missing in type '{ b: number; }'. +tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. + Type 'T' is not assignable to type '{ b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. + Property 'a' is missing in type '{ b: number; }'. ==== tests/cases/conformance/jsx/file.tsx (2 errors) ==== @@ -22,7 +25,10 @@ tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type '{ b: number; }' !!! error TS2322: Property 'b' is missing in type '{ a: number; }'. let a2 = // missing a ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. -!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. -!!! error TS2322: Property 'a' is missing in type '{ b: number; }'. +!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Type 'T' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Property 'a' is missing in type '{ b: number; }'. } \ No newline at end of file diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt index b92375797e..57a2ae556f 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt @@ -1,7 +1,11 @@ +tests/cases/conformance/jsx/file.tsx(15,14): error TS2605: JSX element type 'Element' is not a constructor function for JSX elements. + Property 'render' is missing in type 'Element'. +tests/cases/conformance/jsx/file.tsx(15,15): error TS2453: The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly. + Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate '"hello"'. tests/cases/conformance/jsx/file.tsx(16,42): error TS2339: Property 'prop1' does not exist on type 'IntrinsicAttributes & { prop: number; }'. -==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/file.tsx (3 errors) ==== import React = require('react') declare function Component(l: U): JSX.Element; @@ -17,6 +21,12 @@ tests/cases/conformance/jsx/file.tsx(16,42): error TS2339: Property 'prop1' does let a1 = ; // U is number let a2 = ; // U is number let a3 = ; // U is "hello" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2605: JSX element type 'Element' is not a constructor function for JSX elements. +!!! error TS2605: Property 'render' is missing in type 'Element'. + ~~~~~~~~~~~~~~~~~ +!!! error TS2453: The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly. +!!! error TS2453: Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate '"hello"'. let a4 = ; // U is "hello" ~~~~~~~~~~~~~ !!! error TS2339: Property 'prop1' does not exist on type 'IntrinsicAttributes & { prop: number; }'. diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType1.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType1.tsx new file mode 100644 index 0000000000..e6b7fc18ef --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType1.tsx @@ -0,0 +1,18 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +const decorator = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +const decorator2 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; + +const decorator3 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType2.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType2.tsx new file mode 100644 index 0000000000..48acd55546 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType2.tsx @@ -0,0 +1,10 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +const decorator4 = function (Component: React.StatelessComponent): React.StatelessComponent { + return (props) => +}; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType3.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType3.tsx new file mode 100644 index 0000000000..b683c5e797 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType3.tsx @@ -0,0 +1,17 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + render() { + return ; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType4.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType4.tsx new file mode 100644 index 0000000000..b207f2b439 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType4.tsx @@ -0,0 +1,18 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType5.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType5.tsx new file mode 100644 index 0000000000..d0215da739 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType5.tsx @@ -0,0 +1,19 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + props: U; + render() { + // Should be an ok but as of 2.3.3 this will be an error as we will instantiate B1.props to be empty object + return ; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType6.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType6.tsx new file mode 100644 index 0000000000..d70df8a0cf --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType6.tsx @@ -0,0 +1,18 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +class B1 extends React.Component { + render() { + return
hi
; + } +} +class B extends React.Component { + props: U; + render() { + return ; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType7.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType7.tsx new file mode 100644 index 0000000000..3044fda23d --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType7.tsx @@ -0,0 +1,15 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +declare function Component(props: T) : JSX.Element; +const decorator = function (props: U) { + return ; +} + +const decorator1 = function (props: U) { + return ; +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType8.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType8.tsx new file mode 100644 index 0000000000..b1d3a7445c --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType8.tsx @@ -0,0 +1,15 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +declare function Component(props: T) : JSX.Element; +const decorator = function (props: U) { + return ; +} + +const decorator1 = function (props: U) { + return ; +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx new file mode 100644 index 0000000000..a9466a4398 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx @@ -0,0 +1,16 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ + return class extends React.PureComponent { + public render(): JSX.Element { + return ( + + ); + } + }; +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionEntryForClassMembers.ts b/tests/cases/fourslash/completionEntryForClassMembers.ts new file mode 100644 index 0000000000..527611b85b --- /dev/null +++ b/tests/cases/fourslash/completionEntryForClassMembers.ts @@ -0,0 +1,256 @@ +/// + +////abstract class B { +//// private privateMethod() { } +//// protected protectedMethod() { }; +//// static staticMethod() { } +//// abstract getValue(): number; +//// /*abstractClass*/ +////} +////class C extends B { +//// /*classThatIsEmptyAndExtendingAnotherClass*/ +////} +////class D extends B { +//// /*classThatHasAlreadyImplementedAnotherClassMethod*/ +//// getValue() { +//// return 10; +//// } +//// /*classThatHasAlreadyImplementedAnotherClassMethodAfterMethod*/ +////} +////class D1 extends B { +//// /*classThatHasDifferentMethodThanBase*/ +//// getValue1() { +//// return 10; +//// } +//// /*classThatHasDifferentMethodThanBaseAfterMethod*/ +////} +////class D2 extends B { +//// /*classThatHasAlreadyImplementedAnotherClassProtectedMethod*/ +//// protectedMethod() { +//// } +//// /*classThatHasDifferentMethodThanBaseAfterProtectedMethod*/ +////} +////class D3 extends D1 { +//// /*classThatExtendsClassExtendingAnotherClass*/ +////} +////class D4 extends D1 { +//// static /*classThatExtendsClassExtendingAnotherClassAndTypesStatic*/ +////} +////class D5 extends D2 { +//// /*classThatExtendsClassExtendingAnotherClassWithOverridingMember*/ +////} +////class D6 extends D2 { +//// static /*classThatExtendsClassExtendingAnotherClassWithOverridingMemberAndTypesStatic*/ +////} +////class E { +//// /*classThatDoesNotExtendAnotherClass*/ +////} +////class F extends B { +//// public /*classThatHasWrittenPublicKeyword*/ +////} +////class F2 extends B { +//// private /*classThatHasWrittenPrivateKeyword*/ +////} +////class G extends B { +//// static /*classElementContainingStatic*/ +////} +////class G2 extends B { +//// private static /*classElementContainingPrivateStatic*/ +////} +////class H extends B { +//// prop/*classThatStartedWritingIdentifier*/ +////} +//////Class for location verification +////class I extends B { +//// prop0: number +//// /*propDeclarationWithoutSemicolon*/ +//// prop: number; +//// /*propDeclarationWithSemicolon*/ +//// prop1 = 10; +//// /*propAssignmentWithSemicolon*/ +//// prop2 = 10 +//// /*propAssignmentWithoutSemicolon*/ +//// method(): number +//// /*methodSignatureWithoutSemicolon*/ +//// method2(): number; +//// /*methodSignatureWithSemicolon*/ +//// method3() { +//// /*InsideMethod*/ +//// } +//// /*methodImplementation*/ +//// get c() +//// /*accessorSignatureWithoutSemicolon*/ +//// set c() +//// { +//// } +//// /*accessorSignatureImplementation*/ +////} +////class J extends B { +//// get /*classThatHasWrittenGetKeyword*/ +////} +////class K extends B { +//// set /*classThatHasWrittenSetKeyword*/ +////} +////class J extends B { +//// get identi/*classThatStartedWritingIdentifierOfGetAccessor*/ +////} +////class K extends B { +//// set identi/*classThatStartedWritingIdentifierOfSetAccessor*/ +////} +////class L extends B { +//// public identi/*classThatStartedWritingIdentifierAfterModifier*/ +////} +////class L2 extends B { +//// private identi/*classThatStartedWritingIdentifierAfterPrivateModifier*/ +////} +////class M extends B { +//// static identi/*classThatStartedWritingIdentifierAfterStaticModifier*/ +////} +////class M extends B { +//// private static identi/*classThatStartedWritingIdentifierAfterPrivateStaticModifier*/ +////} +////class N extends B { +//// async /*classThatHasWrittenAsyncKeyword*/ +////} + +const allowedKeywordCount = verify.allowedClassElementKeywords.length; +type CompletionInfo = [string, string]; +type CompletionInfoVerifier = { validMembers: CompletionInfo[], invalidMembers: CompletionInfo[] }; + +function verifyClassElementLocations({ validMembers, invalidMembers }: CompletionInfoVerifier, classElementCompletionLocations: string[]) { + for (const marker of classElementCompletionLocations) { + goTo.marker(marker); + verifyCompletionInfo(validMembers, verify); + verifyCompletionInfo(invalidMembers, verify.not); + verify.completionListContainsClassElementKeywords(); + verify.completionListCount(allowedKeywordCount + validMembers.length); + } +} + +function verifyCompletionInfo(memberInfo: CompletionInfo[], verify: FourSlashInterface.verifyNegatable) { + for (const [symbol, text] of memberInfo) { + verify.completionListContains(symbol, text, /*documentation*/ undefined, "method"); + } +} + +const allMembersOfBase: CompletionInfo[] = [ + ["getValue", "(method) B.getValue(): number"], + ["protectedMethod", "(method) B.protectedMethod(): void"], + ["privateMethod", "(method) B.privateMethod(): void"], + ["staticMethod", "(method) B.staticMethod(): void"] +]; +const publicCompletionInfoOfD1: CompletionInfo[] = [ + ["getValue1", "(method) D1.getValue1(): number"] +]; +const publicCompletionInfoOfD2: CompletionInfo[] = [ + ["protectedMethod", "(method) D2.protectedMethod(): void"] +]; +function filterCompletionInfo(fn: (a: CompletionInfo) => boolean): CompletionInfoVerifier { + const validMembers: CompletionInfo[] = []; + const invalidMembers: CompletionInfo[] = []; + for (const member of allMembersOfBase) { + if (fn(member)) { + validMembers.push(member); + } + else { + invalidMembers.push(member); + } + } + return { validMembers, invalidMembers }; +} + + +const instanceMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "getValue" || a === "protectedMethod"); +const staticMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "staticMethod"); +const instanceWithoutProtectedMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "getValue"); +const instanceWithoutPublicMemberInfo = filterCompletionInfo(([a]: CompletionInfo) => a === "protectedMethod"); + +const instanceMemberInfoD1: CompletionInfoVerifier = { + validMembers: instanceMemberInfo.validMembers.concat(publicCompletionInfoOfD1), + invalidMembers: instanceMemberInfo.invalidMembers +}; +const instanceMemberInfoD2: CompletionInfoVerifier = { + validMembers: instanceWithoutProtectedMemberInfo.validMembers.concat(publicCompletionInfoOfD2), + invalidMembers: instanceWithoutProtectedMemberInfo.invalidMembers +}; +const staticMemberInfoDn: CompletionInfoVerifier = { + validMembers: staticMemberInfo.validMembers, + invalidMembers: staticMemberInfo.invalidMembers.concat(publicCompletionInfoOfD1, publicCompletionInfoOfD2) +}; + +// Not a class element declaration location +const nonClassElementMarkers = [ + "InsideMethod" +]; +for (const marker of nonClassElementMarkers) { + goTo.marker(marker); + verifyCompletionInfo(allMembersOfBase, verify.not); + verify.not.completionListIsEmpty(); +} + +// Only keywords allowed at this position since they dont extend the class or are private +const onlyClassElementKeywordLocations = [ + "abstractClass", + "classThatDoesNotExtendAnotherClass", + "classThatHasWrittenPrivateKeyword", + "classElementContainingPrivateStatic", + "classThatStartedWritingIdentifierAfterPrivateModifier", + "classThatStartedWritingIdentifierAfterPrivateStaticModifier" +]; +verifyClassElementLocations({ validMembers: [], invalidMembers: allMembersOfBase }, onlyClassElementKeywordLocations); + +// Instance base members and class member keywords allowed +const classInstanceElementLocations = [ + "classThatIsEmptyAndExtendingAnotherClass", + "classThatHasDifferentMethodThanBase", + "classThatHasDifferentMethodThanBaseAfterMethod", + "classThatHasWrittenPublicKeyword", + "classThatStartedWritingIdentifier", + "propDeclarationWithoutSemicolon", + "propDeclarationWithSemicolon", + "propAssignmentWithSemicolon", + "propAssignmentWithoutSemicolon", + "methodSignatureWithoutSemicolon", + "methodSignatureWithSemicolon", + "methodImplementation", + "accessorSignatureWithoutSemicolon", + "accessorSignatureImplementation", + "classThatHasWrittenGetKeyword", + "classThatHasWrittenSetKeyword", + "classThatStartedWritingIdentifierOfGetAccessor", + "classThatStartedWritingIdentifierOfSetAccessor", + "classThatStartedWritingIdentifierAfterModifier", + "classThatHasWrittenAsyncKeyword" +]; +verifyClassElementLocations(instanceMemberInfo, classInstanceElementLocations); + +// Static Base members and class member keywords allowed +const staticClassLocations = [ + "classElementContainingStatic", + "classThatStartedWritingIdentifierAfterStaticModifier" +]; +verifyClassElementLocations(staticMemberInfo, staticClassLocations); + +const classInstanceElementWithoutPublicMethodLocations = [ + "classThatHasAlreadyImplementedAnotherClassMethod", + "classThatHasAlreadyImplementedAnotherClassMethodAfterMethod", +]; +verifyClassElementLocations(instanceWithoutPublicMemberInfo, classInstanceElementWithoutPublicMethodLocations); + +const classInstanceElementWithoutProtectedMethodLocations = [ + "classThatHasAlreadyImplementedAnotherClassProtectedMethod", + "classThatHasDifferentMethodThanBaseAfterProtectedMethod", +]; +verifyClassElementLocations(instanceWithoutProtectedMemberInfo, classInstanceElementWithoutProtectedMethodLocations); + +// instance memebers in D1 and base class are shown +verifyClassElementLocations(instanceMemberInfoD1, ["classThatExtendsClassExtendingAnotherClass"]); + +// instance memebers in D2 and base class are shown +verifyClassElementLocations(instanceMemberInfoD2, ["classThatExtendsClassExtendingAnotherClassWithOverridingMember"]); + +// static base members and class member keywords allowed +verifyClassElementLocations(staticMemberInfoDn, [ + "classThatExtendsClassExtendingAnotherClassAndTypesStatic", + "classThatExtendsClassExtendingAnotherClassWithOverridingMemberAndTypesStatic" +]); \ No newline at end of file diff --git a/tests/cases/fourslash/completionEntryForClassMembers2.ts b/tests/cases/fourslash/completionEntryForClassMembers2.ts new file mode 100644 index 0000000000..539702196a --- /dev/null +++ b/tests/cases/fourslash/completionEntryForClassMembers2.ts @@ -0,0 +1,456 @@ +/// + +////interface I { +//// methodOfInterface(): number; +////} +////interface I2 { +//// methodOfInterface2(): number; +////} +////interface I3 { +//// getValue(): string; +//// method(): string; +////} +////interface I4 { +//// staticMethod(): void; +//// method(): string; +////} +////class B0 { +//// private privateMethod() { } +//// protected protectedMethod() { } +//// static staticMethod() { } +//// getValue(): string | boolean { return "hello"; } +//// private privateMethod1() { } +//// protected protectedMethod1() { } +//// static staticMethod1() { } +//// getValue1(): string | boolean { return "hello"; } +////} +////interface I5 extends B0 { +//// methodOfInterface5(): number; +////} +////interface I6 extends B0 { +//// methodOfInterface6(): number; +//// staticMethod(): void; +////} +////interface I7 extends I { +//// methodOfInterface7(): number; +////} +////class B { +//// private privateMethod() { } +//// protected protectedMethod() { } +//// static staticMethod() { } +//// getValue(): string | boolean { return "hello"; } +////} +////class C0 implements I, I2 { +//// /*implementsIAndI2*/ +////} +////class C00 implements I, I2 { +//// static /*implementsIAndI2AndWritingStatic*/ +////} +////class C001 implements I, I2 { +//// methodOfInterface/*implementsIAndI2AndWritingMethodNameOfI*/ +////} +////class C extends B implements I, I2 { +//// /*extendsBAndImplementsIAndI2*/ +////} +////class C1 extends B implements I, I2 { +//// static /*extendsBAndImplementsIAndI2AndWritingStatic*/ +////} +////class D extends B implements I, I2 { +//// /*extendsBAndImplementsIAndI2WithMethodFromB*/ +//// protected protectedMethod() { +//// return "protected"; +//// } +////} +////class E extends B implements I, I2 { +//// /*extendsBAndImplementsIAndI2WithMethodFromI*/ +//// methodOfInterface() { +//// return 1; +//// } +////} +////class F extends B implements I, I2 { +//// /*extendsBAndImplementsIAndI2WithMethodFromBAndI*/ +//// protected protectedMethod() { +//// return "protected" +//// } +//// methodOfInterface() { +//// return 1; +//// } +////} +////class F2 extends B implements I, I2 { +//// protected protectedMethod() { +//// return "protected" +//// } +//// methodOfInterface() { +//// return 1; +//// } +//// static /*extendsBAndImplementsIAndI2WithMethodFromBAndIAndTypesStatic*/ +////} +////class G extends B implements I3 { +//// /*extendsBAndImplementsI3WithSameNameMembers*/ +////} +////class H extends B implements I3 { +//// /*extendsBAndImplementsI3WithSameNameMembersAndHasImplementedTheMember*/ +//// getValue() { +//// return "hello"; +//// } +////} +////class J extends B0 implements I4 { +//// /*extendsB0ThatExtendsAndImplementsI4WithStaticMethod*/ +////} +////class L extends B0 implements I4 { +//// /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedAnotherMethod*/ +//// staticMethod2() { +//// return "hello"; +//// } +////} +////class K extends B0 implements I4 { +//// /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethod*/ +//// staticMethod() { +//// return "hello"; +//// } +////} +////class M extends B0 implements I4 { +//// /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsStatic*/ +//// static staticMethod() { +//// return "hello"; +//// } +////} +////class N extends B0 implements I4 { +//// /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsBoth*/ +//// staticMethod() { +//// return "hello"; +//// } +//// static staticMethod() { +//// return "hello"; +//// } +////} +////class J1 extends B0 implements I4 { +//// static /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodWritingStatic*/ +////} +////class L1 extends B0 implements I4 { +//// staticMethod2() { +//// return "hello"; +//// } +//// static /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedAnotherMethodWritingStatic*/ +////} +////class K1 extends B0 implements I4 { +//// staticMethod() { +//// return "hello"; +//// } +//// static /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodWritingStatic*/ +////} +////class M1 extends B0 implements I4 { +//// static staticMethod() { +//// return "hello"; +//// } +//// static /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsStaticWritingStatic*/ +////} +////class N1 extends B0 implements I4 { +//// staticMethod() { +//// return "hello"; +//// } +//// static staticMethod() { +//// return "hello"; +//// } +//// static /*extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsBothWritingStatic*/ +////} +////class O implements I7 { +//// /*implementsI7whichExtendsI*/ +////} +////class P implements I7, I { +//// /*implementsI7whichExtendsIAndAlsoImplementsI*/ +////} +////class Q implements I, I7 { +//// /*implementsIAndAlsoImplementsI7whichExtendsI*/ +////} +////class R implements I5 { +//// /*implementsI5ThatExtendsB0*/ +////} +////class S implements I6 { +//// /*implementsI6ThatExtendsB0AndHasStaticMethodOfB0*/ +////} +////class T extends B0 implements I5 { +//// /*extendsB0AndImplementsI5ThatExtendsB0*/ +////} +////class U extends B0 implements I6 { +//// /*extendsB0AndImplementsI6ThatExtendsB0AndHasStaticMethodOfB0*/ +////} +////class R1 implements I5 { +//// static /*implementsI5ThatExtendsB0TypesStatic*/ +////} +////class S1 implements I6 { +//// static /*implementsI6ThatExtendsB0AndHasStaticMethodOfB0TypesStatic*/ +////} +////class T1 extends B0 implements I5 { +//// static /*extendsB0AndImplementsI5ThatExtendsB0TypesStatic*/ +////} +////class U1 extends B0 implements I6 { +//// static /*extendsB0AndImplementsI6ThatExtendsB0AndHasStaticMethodOfB0TypesStatic*/ +////} + +const allowedKeywordCount = verify.allowedClassElementKeywords.length; +type CompletionInfo = [string, string]; +type CompletionInfoVerifier = { validMembers: CompletionInfo[], invalidMembers: CompletionInfo[] }; + +function verifyClassElementLocations({ validMembers, invalidMembers }: CompletionInfoVerifier, classElementCompletionLocations: string[]) { + for (const marker of classElementCompletionLocations) { + goTo.marker(marker); + verifyCompletionInfo(validMembers, verify); + verifyCompletionInfo(invalidMembers, verify.not); + verify.completionListContainsClassElementKeywords(); + verify.completionListCount(allowedKeywordCount + validMembers.length); + } +} + +function verifyCompletionInfo(memberInfo: CompletionInfo[], verify: FourSlashInterface.verifyNegatable) { + for (const [symbol, text] of memberInfo) { + verify.completionListContains(symbol, text, /*documentation*/ undefined, "method"); + } +} + +const validInstanceMembersOfBaseClassB: CompletionInfo[] = [ + ["getValue", "(method) B.getValue(): string | boolean"], + ["protectedMethod", "(method) B.protectedMethod(): void"], +]; +const validStaticMembersOfBaseClassB: CompletionInfo[] = [ + ["staticMethod", "(method) B.staticMethod(): void"] +]; +const privateMembersOfBaseClassB: CompletionInfo[] = [ + ["privateMethod", "(method) B.privateMethod(): void"], +]; +const protectedPropertiesOfBaseClassB0: CompletionInfo[] = [ + ["protectedMethod", "(method) B0.protectedMethod(): void"], + ["protectedMethod1", "(method) B0.protectedMethod1(): void"], +]; +const publicPropertiesOfBaseClassB0: CompletionInfo[] = [ + ["getValue", "(method) B0.getValue(): string | boolean"], + ["getValue1", "(method) B0.getValue1(): string | boolean"], +]; +const validInstanceMembersOfBaseClassB0: CompletionInfo[] = protectedPropertiesOfBaseClassB0.concat(publicPropertiesOfBaseClassB0); +const validStaticMembersOfBaseClassB0: CompletionInfo[] = [ + ["staticMethod", "(method) B0.staticMethod(): void"], + ["staticMethod1", "(method) B0.staticMethod1(): void"] +]; +const privateMembersOfBaseClassB0: CompletionInfo[] = [ + ["privateMethod", "(method) B0.privateMethod(): void"], + ["privateMethod1", "(method) B0.privateMethod1(): void"], +]; +const membersOfI: CompletionInfo[] = [ + ["methodOfInterface", "(method) I.methodOfInterface(): number"], +]; +const membersOfI2: CompletionInfo[] = [ + ["methodOfInterface2", "(method) I2.methodOfInterface2(): number"], +]; +const membersOfI3: CompletionInfo[] = [ + ["getValue", "(method) I3.getValue(): string"], + ["method", "(method) I3.method(): string"], +]; +const membersOfI4: CompletionInfo[] = [ + ["staticMethod", "(method) I4.staticMethod(): void"], + ["method", "(method) I4.method(): string"], +]; +const membersOfI5: CompletionInfo[] = publicPropertiesOfBaseClassB0.concat([ + ["methodOfInterface5", "(method) I5.methodOfInterface5(): number"] +]); +const membersOfI6: CompletionInfo[] = publicPropertiesOfBaseClassB0.concat([ + ["staticMethod", "(method) I6.staticMethod(): void"], + ["methodOfInterface6", "(method) I6.methodOfInterface6(): number"] +]); +const membersOfI7: CompletionInfo[] = membersOfI.concat([ + ["methodOfInterface7", "(method) I7.methodOfInterface7(): number"] +]); + +function getCompletionInfoVerifier( + validMembers: CompletionInfo[], + invalidMembers: CompletionInfo[], + arrayToDistribute: CompletionInfo[], + isValidDistributionCriteria: (v: CompletionInfo) => boolean): CompletionInfoVerifier { + if (arrayToDistribute) { + validMembers = validMembers.concat(arrayToDistribute.filter(isValidDistributionCriteria)); + invalidMembers = invalidMembers.concat(arrayToDistribute.filter(v => !isValidDistributionCriteria(v))); + } + return { + validMembers, + invalidMembers + } +} + +const noMembers: CompletionInfo[] = []; +const membersOfIAndI2 = membersOfI.concat(membersOfI2); +const invalidMembersOfBAtInstanceLocation = privateMembersOfBaseClassB.concat(validStaticMembersOfBaseClassB); + +// members of I and I2 +verifyClassElementLocations({ validMembers: membersOfIAndI2, invalidMembers: noMembers }, [ + "implementsIAndI2", + "implementsIAndI2AndWritingMethodNameOfI" +]); + +// Static location so no members of I and I2 +verifyClassElementLocations({ validMembers: noMembers, invalidMembers: membersOfIAndI2 }, + ["implementsIAndI2AndWritingStatic"]); + +const allInstanceBAndIAndI2 = membersOfIAndI2.concat(validInstanceMembersOfBaseClassB); +// members of instance B, I and I2 +verifyClassElementLocations({ + validMembers: allInstanceBAndIAndI2, + invalidMembers: invalidMembersOfBAtInstanceLocation +}, ["extendsBAndImplementsIAndI2"]); + +// static location so only static members of B and no members of instance B, I and I2 +verifyClassElementLocations({ + validMembers: validStaticMembersOfBaseClassB, + invalidMembers: privateMembersOfBaseClassB.concat(allInstanceBAndIAndI2) +}, [ + "extendsBAndImplementsIAndI2AndWritingStatic", + "extendsBAndImplementsIAndI2WithMethodFromBAndIAndTypesStatic" + ]); + +// instance members of B without protectedMethod, I and I2 +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ membersOfIAndI2, + /*invalidMembers*/ invalidMembersOfBAtInstanceLocation, + /*arrayToDistribute*/ validInstanceMembersOfBaseClassB, + value => value[0] !== "protectedMethod"), + ["extendsBAndImplementsIAndI2WithMethodFromB"]); + +// instance members of B, members of T without methodOfInterface and I2 +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ membersOfI2.concat(validInstanceMembersOfBaseClassB), + /*invalidMembers*/ invalidMembersOfBAtInstanceLocation, + /*arrayToDistribute*/ membersOfI, + value => value[0] !== "methodOfInterface"), + ["extendsBAndImplementsIAndI2WithMethodFromI"]); + +// instance members of B without protectedMethod, members of T without methodOfInterface and I2 +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ membersOfI2, + /*invalidMembers*/ invalidMembersOfBAtInstanceLocation, + /*arrayToDistribute*/ membersOfI.concat(validInstanceMembersOfBaseClassB), + value => value[0] !== "methodOfInterface" && value[0] !== "protectedMethod"), + ["extendsBAndImplementsIAndI2WithMethodFromBAndI"]); + +// members of B and members of I3 that are not same as name of method in B +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ validInstanceMembersOfBaseClassB, + /*invalidMembers*/ invalidMembersOfBAtInstanceLocation, + /*arrayToDistribute*/ membersOfI3, + value => value[0] !== "getValue"), + ["extendsBAndImplementsI3WithSameNameMembers"]); + +// members of B (without getValue since its implemented) and members of I3 that are not same as name of method in B +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ noMembers, + /*invalidMembers*/ invalidMembersOfBAtInstanceLocation, + /*arrayToDistribute*/ membersOfI3.concat(validInstanceMembersOfBaseClassB), + value => value[0] !== "getValue"), + ["extendsBAndImplementsI3WithSameNameMembersAndHasImplementedTheMember"]); + +const invalidMembersOfB0AtInstanceSide = privateMembersOfBaseClassB0.concat(validStaticMembersOfBaseClassB0); +const invalidMembersOfB0AtStaticSide = privateMembersOfBaseClassB0.concat(validInstanceMembersOfBaseClassB0); +// members of B0 and members of I4 +verifyClassElementLocations({ + validMembers: validInstanceMembersOfBaseClassB0.concat(membersOfI4), + invalidMembers: invalidMembersOfB0AtInstanceSide +}, [ + "extendsB0ThatExtendsAndImplementsI4WithStaticMethod", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedAnotherMethod", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsStatic" + ]); + +// members of B0 and members of I4 that are not staticMethod +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ validInstanceMembersOfBaseClassB0, + /*invalidMembers*/ invalidMembersOfB0AtInstanceSide, + /*arrayToDistribute*/ membersOfI4, + value => value[0] !== "staticMethod" + ), [ + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethod", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsBoth" + ]); + +// static members of B0 +verifyClassElementLocations({ + validMembers: validStaticMembersOfBaseClassB0, + invalidMembers: invalidMembersOfB0AtStaticSide.concat(membersOfI4) +}, [ + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodWritingStatic", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedAnotherMethodWritingStatic", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodWritingStatic" + ]); + +// static members of B0 without staticMethod +verifyClassElementLocations( + getCompletionInfoVerifier( + /*validMembers*/ noMembers, + /*invalidMembers*/ invalidMembersOfB0AtStaticSide.concat(membersOfI4), + /*arrayToDistribute*/ validStaticMembersOfBaseClassB0, + value => value[0] !== "staticMethod" + ), [ + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsStaticWritingStatic", + "extendsB0ThatExtendsAndImplementsI4WithStaticMethodAndImplementedThatMethodAsBothWritingStatic" + ]); + +// members of I7 extends I +verifyClassElementLocations({ validMembers: membersOfI7, invalidMembers: noMembers }, [ + "implementsI7whichExtendsI", + "implementsI7whichExtendsIAndAlsoImplementsI", + "implementsIAndAlsoImplementsI7whichExtendsI" +]); + +const invalidMembersOfB0AtInstanceSideFromInterfaceExtendingB0 = invalidMembersOfB0AtInstanceSide + .concat(protectedPropertiesOfBaseClassB0); +// members of I5 extends B0 +verifyClassElementLocations({ + validMembers: membersOfI5, + invalidMembers: invalidMembersOfB0AtInstanceSideFromInterfaceExtendingB0 +}, [ + "implementsI5ThatExtendsB0", + ]); + +// members of I6 extends B0 +verifyClassElementLocations({ + validMembers: membersOfI6, + invalidMembers: invalidMembersOfB0AtInstanceSideFromInterfaceExtendingB0 +}, [ + "implementsI6ThatExtendsB0AndHasStaticMethodOfB0", + ]); + +// members of B0 and I5 that extends B0 +verifyClassElementLocations({ + validMembers: membersOfI5.concat(protectedPropertiesOfBaseClassB0), + invalidMembers: invalidMembersOfB0AtInstanceSide +}, [ + "extendsB0AndImplementsI5ThatExtendsB0" + ]); + +// members of B0 and I6 that extends B0 +verifyClassElementLocations({ + validMembers: membersOfI6.concat(protectedPropertiesOfBaseClassB0), + invalidMembers: invalidMembersOfB0AtInstanceSide +}, [ + "extendsB0AndImplementsI6ThatExtendsB0AndHasStaticMethodOfB0" + ]); + +// nothing on static side as these do not extend any other class +verifyClassElementLocations({ + validMembers: [], + invalidMembers: membersOfI5.concat(membersOfI6, invalidMembersOfB0AtStaticSide) +}, [ + "implementsI5ThatExtendsB0TypesStatic", + "implementsI6ThatExtendsB0AndHasStaticMethodOfB0TypesStatic" + ]); + +// statics of base B but nothing from instance side +verifyClassElementLocations({ + validMembers: validStaticMembersOfBaseClassB0, + invalidMembers: membersOfI5.concat(membersOfI6, invalidMembersOfB0AtStaticSide) +}, [ + "extendsB0AndImplementsI5ThatExtendsB0TypesStatic", + "extendsB0AndImplementsI6ThatExtendsB0AndHasStaticMethodOfB0TypesStatic" + ]); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListBuilderLocations_properties.ts b/tests/cases/fourslash/completionListBuilderLocations_properties.ts index 806d8c1de4..2cdc3b7e7b 100644 --- a/tests/cases/fourslash/completionListBuilderLocations_properties.ts +++ b/tests/cases/fourslash/completionListBuilderLocations_properties.ts @@ -10,4 +10,4 @@ //// public static a/*property2*/ ////} -goTo.eachMarker(() => verify.completionListIsEmpty()); +goTo.eachMarker(() => verify.completionListContainsClassElementKeywords()); diff --git a/tests/cases/fourslash/completionListInNamedClassExpression.ts b/tests/cases/fourslash/completionListInNamedClassExpression.ts index cf0d170f6a..8ca6806ce7 100644 --- a/tests/cases/fourslash/completionListInNamedClassExpression.ts +++ b/tests/cases/fourslash/completionListInNamedClassExpression.ts @@ -1,4 +1,4 @@ -/// +/// //// var x = class myClass { //// getClassName (){ @@ -11,4 +11,4 @@ goTo.marker("0"); verify.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); goTo.marker("1"); -verify.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); \ No newline at end of file +verify.not.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInNamedClassExpressionWithShadowing.ts b/tests/cases/fourslash/completionListInNamedClassExpressionWithShadowing.ts index e1274e6f59..fd347d5803 100644 --- a/tests/cases/fourslash/completionListInNamedClassExpressionWithShadowing.ts +++ b/tests/cases/fourslash/completionListInNamedClassExpressionWithShadowing.ts @@ -1,4 +1,4 @@ -/// +/// //// class myClass { /*0*/ } //// /*1*/ @@ -16,7 +16,7 @@ //// } goTo.marker("0"); -verify.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); +verify.not.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); verify.not.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); goTo.marker("1"); @@ -28,7 +28,7 @@ verify.completionListContains("myClass", "(local class) myClass", /*documentatio verify.not.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); goTo.marker("3"); -verify.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); +verify.not.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); verify.not.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); goTo.marker("4"); @@ -36,5 +36,5 @@ verify.completionListContains("myClass", "class myClass", /*documentation*/ unde verify.not.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); goTo.marker("5"); -verify.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); +verify.not.completionListContains("myClass", "class myClass", /*documentation*/ undefined, "class"); verify.not.completionListContains("myClass", "(local class) myClass", /*documentation*/ undefined, "local class"); diff --git a/tests/cases/fourslash/completionListIsGlobalCompletion.ts b/tests/cases/fourslash/completionListIsGlobalCompletion.ts index a1fadc6bb1..121ab940d6 100644 --- a/tests/cases/fourslash/completionListIsGlobalCompletion.ts +++ b/tests/cases/fourslash/completionListIsGlobalCompletion.ts @@ -53,7 +53,7 @@ verify.completionListIsGlobal(false); goTo.marker("9"); verify.completionListIsGlobal(false); goTo.marker("10"); -verify.completionListIsGlobal(true); +verify.completionListIsGlobal(false); goTo.marker("11"); verify.completionListIsGlobal(true); goTo.marker("12"); diff --git a/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts b/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts index 51e4013e53..916ad10fe9 100644 --- a/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts +++ b/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts @@ -225,27 +225,28 @@ //// ////var shwvar = 1; -function goToMarkAndGeneralVerify(marker: string) +function goToMarkAndGeneralVerify(marker: string, isClassScope?: boolean) { goTo.marker(marker); - verify.completionListContains('mod1var', 'var mod1var: number'); - verify.completionListContains('mod1fn', 'function mod1fn(): void'); - verify.completionListContains('mod1cls', 'class mod1cls'); - verify.completionListContains('mod1int', 'interface mod1int'); - verify.completionListContains('mod1mod', 'namespace mod1mod'); - verify.completionListContains('mod1evar', 'var mod1.mod1evar: number'); - verify.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); - verify.completionListContains('mod1ecls', 'class mod1.mod1ecls'); - verify.completionListContains('mod1eint', 'interface mod1.mod1eint'); - verify.completionListContains('mod1emod', 'namespace mod1.mod1emod'); - verify.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); - verify.completionListContains('mod2', 'namespace mod2'); - verify.completionListContains('mod3', 'namespace mod3'); - verify.completionListContains('shwvar', 'var shwvar: number'); - verify.completionListContains('shwfn', 'function shwfn(): void'); - verify.completionListContains('shwcls', 'class shwcls'); - verify.completionListContains('shwint', 'interface shwint'); + const verifyModule = isClassScope ? verify.not : verify; + verifyModule.completionListContains('mod1var', 'var mod1var: number'); + verifyModule.completionListContains('mod1fn', 'function mod1fn(): void'); + verifyModule.completionListContains('mod1cls', 'class mod1cls'); + verifyModule.completionListContains('mod1int', 'interface mod1int'); + verifyModule.completionListContains('mod1mod', 'namespace mod1mod'); + verifyModule.completionListContains('mod1evar', 'var mod1.mod1evar: number'); + verifyModule.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); + verifyModule.completionListContains('mod1ecls', 'class mod1.mod1ecls'); + verifyModule.completionListContains('mod1eint', 'interface mod1.mod1eint'); + verifyModule.completionListContains('mod1emod', 'namespace mod1.mod1emod'); + verifyModule.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); + verifyModule.completionListContains('mod2', 'namespace mod2'); + verifyModule.completionListContains('mod3', 'namespace mod3'); + verifyModule.completionListContains('shwvar', 'var shwvar: number'); + verifyModule.completionListContains('shwfn', 'function shwfn(): void'); + verifyModule.completionListContains('shwcls', 'class shwcls'); + verifyModule.completionListContains('shwint', 'interface shwint'); verify.not.completionListContains('mod2var'); verify.not.completionListContains('mod2fn'); @@ -280,7 +281,7 @@ verify.completionListContains('bar', '(local var) bar: number'); verify.completionListContains('foob', '(local function) foob(): void'); // from class in mod1 -goToMarkAndGeneralVerify('class'); +goToMarkAndGeneralVerify('class', /*isClassScope*/ true); //verify.not.completionListContains('ceFunc'); //verify.not.completionListContains('ceVar'); @@ -306,7 +307,7 @@ verify.completionListContains('bar', '(local var) bar: number'); verify.completionListContains('foob', '(local function) foob(): void'); // from exported class in mod1 -goToMarkAndGeneralVerify('exportedClass'); +goToMarkAndGeneralVerify('exportedClass', /*isClassScope*/ true); //verify.not.completionListContains('ceFunc'); //verify.not.completionListContains('ceVar'); diff --git a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts index 865887661e..340d0bd319 100644 --- a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts +++ b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts @@ -231,6 +231,39 @@ //// x: /*objectLiteral*/ ////} +goTo.marker('extendedClass'); + +verify.not.completionListContains('mod1'); +verify.not.completionListContains('mod2'); +verify.not.completionListContains('mod3'); +verify.not.completionListContains('shwvar', 'var shwvar: number'); +verify.not.completionListContains('shwfn', 'function shwfn(): void'); +verify.not.completionListContains('shwcls', 'class shwcls'); +verify.not.completionListContains('shwint', 'interface shwint'); + +verify.not.completionListContains('mod2var'); +verify.not.completionListContains('mod2fn'); +verify.not.completionListContains('mod2cls'); +verify.not.completionListContains('mod2int'); +verify.not.completionListContains('mod2mod'); +verify.not.completionListContains('mod2evar'); +verify.not.completionListContains('mod2efn'); +verify.not.completionListContains('mod2ecls'); +verify.not.completionListContains('mod2eint'); +verify.not.completionListContains('mod2emod'); +verify.not.completionListContains('sfvar'); +verify.not.completionListContains('sffn'); +verify.not.completionListContains('scvar'); +verify.not.completionListContains('scfn'); +verify.completionListContains('scpfn'); +verify.completionListContains('scpvar'); +verify.not.completionListContains('scsvar'); +verify.not.completionListContains('scsfn'); +verify.not.completionListContains('sivar'); +verify.not.completionListContains('sifn'); +verify.not.completionListContains('mod1exvar'); +verify.not.completionListContains('mod2eexvar'); + function goToMarkerAndVerify(marker: string) { goTo.marker(marker); @@ -267,8 +300,6 @@ function goToMarkerAndVerify(marker: string) verify.not.completionListContains('mod2eexvar'); } -goToMarkerAndVerify('extendedClass'); - goToMarkerAndVerify('objectLiteral'); goTo.marker('localVar'); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts new file mode 100644 index 0000000000..c8fdb0a614 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /a.ts +////const [|{| "isWriteAccess": true, "isDefinition": true |}a|] = 0; +////export default [|a|]; + +// @Filename: /b.ts +////import [|{| "isWriteAccess": true, "isDefinition": true |}a|] from "./a"; +////[|a|]; + +const [r0, r1, r2, r3] = test.ranges(); +verify.referenceGroups([r0, r1], [ + { definition: "const a: 0", ranges: [r0, r1] }, + { definition: "import a", ranges: [r2, r3] } +]); +verify.singleReferenceGroup("import a", [r2, r3]); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 374dfd33c7..31d8b8b4ef 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -133,11 +133,13 @@ declare namespace FourSlashInterface { class verifyNegatable { private negative; not: verifyNegatable; + allowedClassElementKeywords: string[]; constructor(negative?: boolean); completionListCount(expectedCount: number): void; completionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number): void; completionListItemsCountIsGreaterThan(count: number): void; completionListIsEmpty(): void; + completionListContainsClassElementKeywords(): void; completionListAllowsNewIdentifier(): void; signatureHelpPresent(): void; errorExistsBetweenMarkers(startMarker: string, endMarker: string): void; diff --git a/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts b/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts index 3e453663f6..448c262753 100644 --- a/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts +++ b/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts @@ -26,7 +26,7 @@ const methods = ranges.get("method"); const [m0, m1, m2] = methods; verify.referenceGroups(m0, [{ definition: "(method) Base.method(a?: T, b?: U): this", ranges: methods }]); verify.referenceGroups(m1, [ - { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) Base.method(a?: T, b?: U): this", ranges: [m0] }, { definition: "(method) MyClass.method(): void", ranges: [m1, m2] } ]); verify.referenceGroups(m2, [ diff --git a/tests/cases/fourslash/tsxQuickInfo6.ts b/tests/cases/fourslash/tsxQuickInfo6.ts index 88d9435e80..2b65dc7667 100644 --- a/tests/cases/fourslash/tsxQuickInfo6.ts +++ b/tests/cases/fourslash/tsxQuickInfo6.ts @@ -15,5 +15,5 @@ verify.quickInfos({ 1: "function ComponentSpecific(l: {\n prop: number;\n}): any", - 2: "function ComponentSpecific<\"hello\">(l: {\n prop: \"hello\";\n}): any" + 2: "function ComponentSpecific(l: {\n prop: U;\n}): any" }); diff --git a/tests/cases/fourslash/tsxQuickInfo7.ts b/tests/cases/fourslash/tsxQuickInfo7.ts index 3e66fb655f..cf08aa53e9 100644 --- a/tests/cases/fourslash/tsxQuickInfo7.ts +++ b/tests/cases/fourslash/tsxQuickInfo7.ts @@ -24,6 +24,6 @@ verify.quickInfos({ 3: "function OverloadComponent(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)", 4: "function OverloadComponent(attr: {\n b: number;\n a?: string;\n \"ignore-prop\": boolean;\n}): any (+2 overloads)", 5: "function OverloadComponent(): any (+2 overloads)", - 6: "function OverloadComponent(attr: {\n b: number;\n a: boolean;\n}): any (+2 overloads)", - 7: "function OverloadComponent(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)" + 6: "function OverloadComponent(): any (+2 overloads)", + 7: "function OverloadComponent(): any (+2 overloads)", }); diff --git a/tests/lib/react.d.ts b/tests/lib/react.d.ts index 1d7b787b99..7f03899eb6 100644 --- a/tests/lib/react.d.ts +++ b/tests/lib/react.d.ts @@ -197,7 +197,7 @@ declare namespace __React { type SFC

= StatelessComponent

; interface StatelessComponent

{ - (props: P, context?: any): ReactElement; + (props: P & { children?: ReactNode }, context?: any): ReactElement; propTypes?: ValidationMap

; contextTypes?: ValidationMap; defaultProps?: P;