From 8b24189aeed41bd51344b71f9796b4c8f42397c2 Mon Sep 17 00:00:00 2001 From: Yuichi Nukiyama Date: Thu, 6 Apr 2017 23:29:36 +0900 Subject: [PATCH 01/32] Fix Headers interface --- src/lib/dom.iterable.d.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index b5e0404c17bdd..94a710f648898 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -21,6 +21,21 @@ interface FormData { [Symbol.iterator](): IterableIterator; } +interface Headers { + /** + * Returns an iterator allowing to go through all key/value pairs contained in this object. + */ + entries(): IterableIterator<[string, string]>; + /** + * Returns an iterator allowing to go through all keys f the key/value pairs contained in this object. + */ + keys(): IterableIterator; + /** + * Returns an iterator allowing to go through all values of the key/value pairs contained in this object. + */ + values(): IterableIterator; +} + interface NodeList { /** * Returns an array of key, value pairs for every entry in the list From b3846bfe65ed6ee16fb9cd118c1630d0d701d907 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 7 Apr 2017 16:41:29 -0700 Subject: [PATCH 02/32] Wip - type checking JSX children --- src/compiler/checker.ts | 61 +++++++++++++++++----------- src/compiler/diagnosticMessages.json | 4 ++ src/compiler/types.ts | 6 ++- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d7acedd663d94..ff10bea4f973a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,4 +1,4 @@ -/// +/// /// /* @internal */ @@ -424,6 +424,8 @@ namespace ts { IntrinsicClassAttributes: "IntrinsicClassAttributes" }; + const jsxChildrenPropertyName = "children"; + const subtypeRelation = createMap(); const assignableRelation = createMap(); const comparableRelation = createMap(); @@ -8648,7 +8650,7 @@ namespace ts { // is considered known if the object type is empty and the check is for assignability, if the object type has // index signatures, or if the property is actually declared in the object type. In a union or intersection // type, a property is considered known if it is known in any constituent type. - function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean { + function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean, containsSynthesizedJsxChildren: boolean): boolean { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); if ((relation === assignableRelation || relation === comparableRelation) && @@ -8658,14 +8660,16 @@ namespace ts { else if (resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name))) { return true; } - else if (getPropertyOfType(type, name) || (isComparingJsxAttributes && !isUnhyphenatedJsxName(name))) { - // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. + else if (getPropertyOfType(type, name) || containsSynthesizedJsxChildren || (isComparingJsxAttributes && !isUnhyphenatedJsxName(name))) { + // For JSXAttributes, consider that the attribute to be known if + // 1. the attribute has a hyphenated name + // 2. "children" attribute that is synthesized from children property of Jsx element return true; } } else if (type.flags & TypeFlags.UnionOrIntersection) { for (const t of (type).types) { - if (isKnownProperty(t, name, isComparingJsxAttributes)) { + if (isKnownProperty(t, name, isComparingJsxAttributes, containsSynthesizedJsxChildren)) { return true; } } @@ -8676,8 +8680,9 @@ namespace ts { function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { const isComparingJsxAttributes = !!(source.flags & TypeFlags.JsxAttributes); + const containsSynthesizedJsxChildren = !!(source.flags & TypeFlags.ContainsSynthesizedJsxChildren); for (const prop of getPropertiesOfObjectType(source)) { - if (!isKnownProperty(target, prop.name, isComparingJsxAttributes)) { + if (!isKnownProperty(target, prop.name, isComparingJsxAttributes, containsSynthesizedJsxChildren)) { if (reportErrors) { // We know *exactly* where things went wrong when comparing the types. // Use this property as the error node as this will be more helpful in @@ -13173,21 +13178,6 @@ namespace ts { checkExpression(node.closingElement.tagName); } - // Check children - for (const child of node.children) { - switch (child.kind) { - case SyntaxKind.JsxExpression: - checkJsxExpression(child); - break; - case SyntaxKind.JsxElement: - checkJsxElement(child); - break; - case SyntaxKind.JsxSelfClosingElement: - checkJsxSelfClosingElement(child); - break; - } - } - return getJsxGlobalElementType() || anyType; } @@ -13280,6 +13270,30 @@ namespace ts { } }); } + + // Handle children attribute + const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? + openingLikeElement.parent as JsxElement : undefined; + let containsSynthesizedJsxChildren = false; + // Comment + if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { + // Error if there is a attribute named "children" and children element. + // This is because children element will overwrite the value from attributes + if (attributesTable.has(jsxChildrenPropertyName)) { + error(attributes, Diagnostics.props_children_are_specified_twice_The_attribute_named_children_will_be_overwritten); + } + + // If there are children in the body of JSX element, create dummy attribute "children" with anyType so that it will pass the attribute checking process + const childrenPropSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, jsxChildrenPropertyName); + const childrenTypes: Type[] = []; + for (const child of (parent as JsxElement).children) { + childrenTypes.push(child.kind === SyntaxKind.JsxText ? stringType : checkExpression(child)); + } + childrenPropSymbol.type = getUnionType(childrenTypes, /*subtypeReduction*/ false); + attributesTable.set(jsxChildrenPropertyName, childrenPropSymbol); + containsSynthesizedJsxChildren = true; + } + return createJsxAttributesType(attributes.symbol, attributesTable); /** @@ -13290,7 +13304,8 @@ namespace ts { function createJsxAttributesType(symbol: Symbol, attributesTable: Map) { const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; - result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag; + const containsSynthesizedJsxChildrenFlag = containsSynthesizedJsxChildren ? TypeFlags.ContainsSynthesizedJsxChildren : 0; + result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | containsSynthesizedJsxChildrenFlag; result.objectFlags |= ObjectFlags.ObjectLiteral; return result; } @@ -14533,7 +14548,7 @@ namespace ts { // We can figure that out by resolving attributes property and check number of properties in the resolved type // If the call has correct arity, we will then check if the argument type and parameter type is assignable - const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incomplete + const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incoplete if (callIsIncomplete) { return true; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 075d4247460e9..72554a9f0bacf 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2099,6 +2099,10 @@ "category": "Error", "code": 2707 }, + "props.children are specified twice. The attribute named 'children' will be overwritten.": { + "category": "Error", + "code": 2708 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 354ef9d8b1043..fd246fed82102 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1,4 +1,4 @@ -namespace ts { +namespace ts { /** * Type of objects whose values are all of the same type. * The `in` and `for-in` operators can *not* be safely used, @@ -10,7 +10,7 @@ namespace ts { /** ES6 Map interface. */ export interface Map { - get(key: string): T; + get(key: string): T | undefined; has(key: string): boolean; set(key: string, value: T): this; delete(key: string): boolean; @@ -2975,6 +2975,8 @@ namespace ts { NonPrimitive = 1 << 24, // intrinsic object type /* @internal */ JsxAttributes = 1 << 25, // Jsx attributes type + /* @internal */ + ContainsSynthesizedJsxChildren = 1 << 26, // Jsx attributes type contains synthesized children property from Jsx element's children /* @internal */ Nullable = Undefined | Null, From f86a730371c506d5ca9864b8d3a4b1835e1d4d47 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 11 Apr 2017 10:52:18 -0700 Subject: [PATCH 03/32] Consider whitespace that won't be emitted to be different kind so that we won't include in typ-checking --- src/compiler/checker.ts | 15 ++++++--------- src/compiler/parser.ts | 8 ++++++-- src/compiler/scanner.ts | 21 ++++++++++++++++++++- src/compiler/types.ts | 1 + 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff10bea4f973a..2c9d4f95d5f88 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13275,7 +13275,7 @@ namespace ts { const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined; let containsSynthesizedJsxChildren = false; - // Comment + // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { // Error if there is a attribute named "children" and children element. // This is because children element will overwrite the value from attributes @@ -13287,7 +13287,11 @@ namespace ts { const childrenPropSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, jsxChildrenPropertyName); const childrenTypes: Type[] = []; for (const child of (parent as JsxElement).children) { - childrenTypes.push(child.kind === SyntaxKind.JsxText ? stringType : checkExpression(child)); + // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that + // because then type of children property will have constituent of string type. + if (child.kind !== SyntaxKind.JsxTextAllWhiteSpaces) { + childrenTypes.push(child.kind === SyntaxKind.JsxText ? stringType : checkExpression(child as Expression, checkMode)); + } } childrenPropSymbol.type = getUnionType(childrenTypes, /*subtypeReduction*/ false); attributesTable.set(jsxChildrenPropertyName, childrenPropSymbol); @@ -17099,13 +17103,6 @@ namespace ts { return cache ? checkExpressionCached(node) : checkExpression(node); } - // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When - // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the - // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in - // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function - // object, it serves as an indicator that all contained function and arrow expressions should be considered to - // have the wildcard function type; this form of type check is used during overload resolution to exclude - // contextually typed function and arrow expressions in the initial phase. function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type { let type: Type; if (node.kind === SyntaxKind.QualifiedName) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a82d5b02b4402..770601bd56cd8 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3825,7 +3825,7 @@ namespace ts { } function parseJsxText(): JsxText { - const node = createNode(SyntaxKind.JsxText, scanner.getStartPos()); + const node = createNode(currentToken, scanner.getStartPos()); currentToken = scanner.scanJsxToken(); return finishNode(node); } @@ -3833,6 +3833,7 @@ namespace ts { function parseJsxChild(): JsxChild { switch (token()) { case SyntaxKind.JsxText: + case SyntaxKind.JsxTextAllWhiteSpaces: return parseJsxText(); case SyntaxKind.OpenBraceToken: return parseJsxExpression(/*inExpressionContext*/ false); @@ -3862,7 +3863,10 @@ namespace ts { else if (token() === SyntaxKind.ConflictMarkerTrivia) { break; } - result.push(parseJsxChild()); + const child = parseJsxChild(); + if (child) { + result.push(child); + } } result.end = scanner.getTokenPos(); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 7b6e0c09db48b..59453f4fa4b28 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1723,6 +1723,11 @@ namespace ts { return token = SyntaxKind.OpenBraceToken; } + // First non-whitespace character on this line. + let firstNonWhitespace = 0; + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitspace, + while (pos < end) { pos++; char = text.charCodeAt(pos); @@ -1736,8 +1741,22 @@ namespace ts { } break; } + + // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces. + // i.e (- : whitespace) + //
---- + //
becomes
+ // + //
----
becomes
----
+ if (isLineBreak(char) && firstNonWhitespace === 0) { + firstNonWhitespace = -1; + } + else if (!isWhiteSpaceSingleLine(char)) { + firstNonWhitespace = pos; + } } - return token = SyntaxKind.JsxText; + + return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText; } // Scans a JSX identifier; these differ from normal identifiers in that diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fd246fed82102..0e0deeedfaa3b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -65,6 +65,7 @@ NumericLiteral, StringLiteral, JsxText, + JsxTextAllWhiteSpaces, RegularExpressionLiteral, NoSubstitutionTemplateLiteral, // Pseudo-literals From 8e2dd382679be99b680b14df9c34334675844d83 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 11 Apr 2017 10:52:50 -0700 Subject: [PATCH 04/32] Use JSX Attributes to contextually type children property --- src/compiler/checker.ts | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2c9d4f95d5f88..62fabf8b85a75 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12635,6 +12635,35 @@ namespace ts { return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } + function getContextualTypeForJsxExpression(node: JsxExpression): Type { + // JSX expression can appear in two position : JSX Element's children or JSX attribute + const jsxAttributes = isJsxAttributeLike(node.parent) ? + node.parent.parent : + node.parent.openingElement.attributes; // node.parent is JsxElement + + // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type + // which is a type of the parameter of the signature we are trying out. + // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName + const attributesType = getContextualType(jsxAttributes); + + if (!attributesType || isTypeAny(attributesType)) { + return undefined; + } + + if (isJsxAttribute(node.parent)) { + // JSX expression is in JSX attribute + return getTypeOfPropertyOfType(attributesType, (node.parent as JsxAttribute).name.text); + } + else if (node.parent.kind === SyntaxKind.JsxElement) { + // JSX expression is in children of JSX Element, we will look for an atttribute named "chidlren" + return getTypeOfPropertyOfType(attributesType, jsxChildrenPropertyName); + } + else { + // JSX expression is in JSX spread attribute + return attributesType; + } + } + function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) { // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type // which is a type of the parameter of the signature we are trying out. @@ -12718,7 +12747,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return getContextualType(parent); case SyntaxKind.JsxExpression: - return getContextualType(parent); + return getContextualTypeForJsxExpression(parent); case SyntaxKind.JsxAttribute: case SyntaxKind.JsxSpreadAttribute: return getContextualTypeForJsxAttribute(parent); From 17417e9a88f2fdb738d7a72f8a012ca43657d03c Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 11 Apr 2017 10:53:14 -0700 Subject: [PATCH 05/32] Format checker --- src/compiler/checker.ts | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62fabf8b85a75..7bbab7005fd13 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -349,7 +349,7 @@ namespace ts { // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, + BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, StringStrictFacts = BaseStringStrictFacts | Truthy | Falsy, StringFacts = BaseStringFacts | Truthy, EmptyStringStrictFacts = BaseStringStrictFacts | Falsy, @@ -1618,7 +1618,7 @@ namespace ts { } } - // May be an untyped module. If so, ignore resolutionDiagnostic. + // May be an untyped module. If so, ignore resolutionDiagnostic. if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) { if (isForAugmentation) { const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; @@ -3973,7 +3973,7 @@ namespace ts { type; } - function getTypeForDeclarationFromJSDocComment(declaration: Node ) { + function getTypeForDeclarationFromJSDocComment(declaration: Node) { const jsdocType = getJSDocType(declaration); if (jsdocType) { return getTypeFromTypeNode(jsdocType); @@ -5640,7 +5640,7 @@ namespace ts { function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type { return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type) : type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type) : - getBaseConstraintOfType(type); + getBaseConstraintOfType(type); } function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { @@ -5713,7 +5713,7 @@ namespace ts { } return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) : t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) : - undefined; + undefined; } if (t.flags & TypeFlags.Index) { return stringType; @@ -5764,11 +5764,11 @@ namespace ts { const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type; return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t) : t.flags & TypeFlags.StringLike ? globalStringType : - t.flags & TypeFlags.NumberLike ? globalNumberType : - t.flags & TypeFlags.BooleanLike ? globalBooleanType : - t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) : - t.flags & TypeFlags.NonPrimitive ? emptyObjectType : - t; + t.flags & TypeFlags.NumberLike ? globalNumberType : + t.flags & TypeFlags.BooleanLike ? globalBooleanType : + t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) : + t.flags & TypeFlags.NonPrimitive ? emptyObjectType : + t; } function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { @@ -7212,8 +7212,8 @@ namespace ts { function getIndexType(type: Type): Type { return maybeTypeOfKind(type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType(type) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : - type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : - getLiteralTypeFromPropertyNames(type); + type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : + getLiteralTypeFromPropertyNames(type); } function getIndexTypeOrString(type: Type): Type { @@ -7409,7 +7409,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type): Type { + function getSpreadType(left: Type, right: Type): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -7698,7 +7698,7 @@ namespace ts { function createTypeMapper(sources: Type[], targets: Type[]): TypeMapper { const mapper: TypeMapper = sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : sources.length === 2 ? makeBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) : - makeArrayTypeMapper(sources, targets); + makeArrayTypeMapper(sources, targets); mapper.mappedTypes = sources; return mapper; } @@ -8502,7 +8502,7 @@ namespace ts { (globalNumberType === source && numberType === target) || (globalBooleanType === source && booleanType === target) || (getGlobalESSymbolType(/*reportErrors*/ false) === source && esSymbolType === target)) { - reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); + reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); } } @@ -9631,25 +9631,25 @@ namespace ts { function isLiteralType(type: Type): boolean { return type.flags & TypeFlags.Boolean ? true : type.flags & TypeFlags.Union ? type.flags & TypeFlags.Enum ? true : !forEach((type).types, t => !isUnitType(t)) : - isUnitType(type); + isUnitType(type); } function getBaseTypeOfLiteralType(type: Type): Type { return type.flags & TypeFlags.StringLiteral ? stringType : type.flags & TypeFlags.NumberLiteral ? numberType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.EnumLiteral ? (type).baseType : - type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getBaseTypeOfLiteralType)) : - type; + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.EnumLiteral ? (type).baseType : + type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getBaseTypeOfLiteralType)) : + type; } function getWidenedLiteralType(type: Type): Type { return type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.EnumLiteral ? (type).baseType : - type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getWidenedLiteralType)) : - type; + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.EnumLiteral ? (type).baseType : + type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getWidenedLiteralType)) : + type; } /** @@ -9674,9 +9674,9 @@ namespace ts { function getFalsyFlags(type: Type): TypeFlags { return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type).types) : type.flags & TypeFlags.StringLiteral ? (type).text === "" ? TypeFlags.StringLiteral : 0 : - type.flags & TypeFlags.NumberLiteral ? (type).text === "0" ? TypeFlags.NumberLiteral : 0 : - type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : - type.flags & TypeFlags.PossiblyFalsy; + type.flags & TypeFlags.NumberLiteral ? (type).text === "0" ? TypeFlags.NumberLiteral : 0 : + type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : + type.flags & TypeFlags.PossiblyFalsy; } function includeFalsyTypes(type: Type, flags: TypeFlags) { @@ -10862,8 +10862,8 @@ namespace ts { isTypeSubsetOf(numberType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, TypeFlags.NumberLiteral)) { return mapType(typeWithPrimitives, t => t.flags & TypeFlags.String ? extractTypesOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.StringLiteral) : - t.flags & TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) : - t); + t.flags & TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) : + t); } return typeWithPrimitives; } @@ -11439,7 +11439,7 @@ namespace ts { const discriminantType = getUnionType(clauseTypes); const caseType = discriminantType.flags & TypeFlags.Never ? neverType : - replacePrimitivesWithLiterals(filterType(type, t => isTypeComparableTo(discriminantType, t)), discriminantType); + replacePrimitivesWithLiterals(filterType(type, t => isTypeComparableTo(discriminantType, t)), discriminantType); if (!hasDefaultClause) { return caseType; } @@ -11519,8 +11519,8 @@ namespace ts { // two types. return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : - isTypeAssignableTo(candidate, type) ? candidate : - getIntersectionType([type, candidate]); + isTypeAssignableTo(candidate, type) ? candidate : + getIntersectionType([type, candidate]); } function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { @@ -11797,7 +11797,7 @@ namespace ts { isInAmbientContext(declaration); const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : - includeFalsyTypes(type, TypeFlags.Undefined); + includeFalsyTypes(type, TypeFlags.Undefined); const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the @@ -12304,7 +12304,7 @@ namespace ts { func.kind === SyntaxKind.GetAccessor || func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent : - undefined; + undefined; } function getThisTypeArgument(type: Type): Type { From 4562fd089cd19f0f49fe57be9a8a6af800983f98 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 11 Apr 2017 14:55:26 -0700 Subject: [PATCH 06/32] Store scanning information whether JSXText is just an all whitespaces --- src/compiler/checker.ts | 9 +++++++-- src/compiler/parser.ts | 3 ++- src/compiler/scanner.ts | 2 +- src/compiler/types.ts | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7bbab7005fd13..18ad0c0437c2f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13318,8 +13318,13 @@ namespace ts { for (const child of (parent as JsxElement).children) { // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that // because then type of children property will have constituent of string type. - if (child.kind !== SyntaxKind.JsxTextAllWhiteSpaces) { - childrenTypes.push(child.kind === SyntaxKind.JsxText ? stringType : checkExpression(child as Expression, checkMode)); + if (child.kind === SyntaxKind.JsxText) { + if (!child.containsOnlyWhiteSpaces) { + childrenTypes.push(stringType); + } + } + else { + childrenTypes.push(checkExpression(child, checkMode)); } } childrenPropSymbol.type = getUnionType(childrenTypes, /*subtypeReduction*/ false); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 770601bd56cd8..cc18fb3260c99 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3825,7 +3825,8 @@ namespace ts { } function parseJsxText(): JsxText { - const node = createNode(currentToken, scanner.getStartPos()); + const node = createNode(SyntaxKind.JsxText, scanner.getStartPos()); + node.containsOnlyWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces; currentToken = scanner.scanJsxToken(); return finishNode(node); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 59453f4fa4b28..2d7ca500893db 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1729,7 +1729,6 @@ namespace ts { // firstNonWhitespace = 0 to indicate that we want leading whitspace, while (pos < end) { - pos++; char = text.charCodeAt(pos); if (char === CharacterCodes.openBrace) { break; @@ -1754,6 +1753,7 @@ namespace ts { else if (!isWhiteSpaceSingleLine(char)) { firstNonWhitespace = pos; } + pos++; } return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0e0deeedfaa3b..d52f277c9ef2d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1572,7 +1572,8 @@ } export interface JsxText extends Node { - kind: SyntaxKind.JsxText; + kind: SyntaxKind.JsxText, + containsOnlyWhiteSpaces: boolean, parent?: JsxElement; } From c1ea3034d5d02b22ef192939704cc77b97657ce0 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 11 Apr 2017 15:35:06 -0700 Subject: [PATCH 07/32] wip-fixing consuming whitespace in children --- src/compiler/emitter.ts | 2 +- src/compiler/scanner.ts | 8 ++++---- src/services/formatting/smartIndenter.ts | 2 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 69b5188878f86..669c9f5dd36ee 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2457,7 +2457,7 @@ namespace ts { let indentation: number; for (const line of lines) { for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { - if (!isWhiteSpace(line.charCodeAt(i))) { + if (!isWhiteSpaceLike(line.charCodeAt(i))) { if (indentation === undefined || i < indentation) { indentation = i; break; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2d7ca500893db..86699702c3b36 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -366,7 +366,7 @@ namespace ts { return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position); } - export function isWhiteSpace(ch: number): boolean { + export function isWhiteSpaceLike(ch: number): boolean { return isWhiteSpaceSingleLine(ch) || isLineBreak(ch); } @@ -510,7 +510,7 @@ namespace ts { break; default: - if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { pos++; continue; } @@ -691,7 +691,7 @@ namespace ts { } break scan; default: - if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { if (hasPendingCommentRange && isLineBreak(ch)) { pendingHasTrailingNewLine = true; } @@ -1750,7 +1750,7 @@ namespace ts { if (isLineBreak(char) && firstNonWhitespace === 0) { firstNonWhitespace = -1; } - else if (!isWhiteSpaceSingleLine(char)) { + else if (!isWhiteSpaceLike(char) && (char !== CharacterCodes.openBrace || char !== CharacterCodes.lessThan)) { firstNonWhitespace = pos; } pos++; diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index b5c901482a7bc..01feaf390818e 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -54,7 +54,7 @@ namespace ts.formatting { let current = position; while (current > 0) { const char = sourceFile.text.charCodeAt(current); - if (!isWhiteSpace(char)) { + if (!isWhiteSpaceLike(char)) { break; } current--; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index d7056cfdca241..e63c46ea8cedd 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -608,7 +608,7 @@ namespace ts.textChanges { if (force || !isTrivia(s)) { this.lastNonTriviaPosition = this.writer.getTextPos(); let i = 0; - while (isWhiteSpace(s.charCodeAt(s.length - i - 1))) { + while (isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { i++; } // trim trailing whitespaces diff --git a/src/services/utilities.ts b/src/services/utilities.ts index fe9a310ad4bf7..5a1acdf1cec09 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1381,7 +1381,7 @@ namespace ts { } export function getFirstNonSpaceCharacterPosition(text: string, position: number) { - while (isWhiteSpace(text.charCodeAt(position))) { + while (isWhiteSpaceLike(text.charCodeAt(position))) { position += 1; } return position; From 4fa23127fcd9281c39e87120d5f690ec293a7fd8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 12 Apr 2017 12:08:12 -0700 Subject: [PATCH 08/32] Fixing consuming whitespace in children --- src/compiler/checker.ts | 4 +++- src/compiler/emitter.ts | 2 +- src/compiler/scanner.ts | 8 ++++---- src/compiler/types.ts | 4 ++-- src/services/formatting/smartIndenter.ts | 2 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 18ad0c0437c2f..745d38bd04341 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13327,7 +13327,9 @@ namespace ts { childrenTypes.push(checkExpression(child, checkMode)); } } - childrenPropSymbol.type = getUnionType(childrenTypes, /*subtypeReduction*/ false); + childrenPropSymbol.type = childrenTypes.length === 1 ? + childrenTypes[0] : + createArrayType(getUnionType(childrenTypes, /*subtypeReduction*/ false)); attributesTable.set(jsxChildrenPropertyName, childrenPropSymbol); containsSynthesizedJsxChildren = true; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 69b5188878f86..669c9f5dd36ee 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2457,7 +2457,7 @@ namespace ts { let indentation: number; for (const line of lines) { for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { - if (!isWhiteSpace(line.charCodeAt(i))) { + if (!isWhiteSpaceLike(line.charCodeAt(i))) { if (indentation === undefined || i < indentation) { indentation = i; break; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2d7ca500893db..8f2cacd3e385a 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -366,7 +366,7 @@ namespace ts { return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position); } - export function isWhiteSpace(ch: number): boolean { + export function isWhiteSpaceLike(ch: number): boolean { return isWhiteSpaceSingleLine(ch) || isLineBreak(ch); } @@ -510,7 +510,7 @@ namespace ts { break; default: - if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { pos++; continue; } @@ -691,7 +691,7 @@ namespace ts { } break scan; default: - if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { if (hasPendingCommentRange && isLineBreak(ch)) { pendingHasTrailingNewLine = true; } @@ -1750,7 +1750,7 @@ namespace ts { if (isLineBreak(char) && firstNonWhitespace === 0) { firstNonWhitespace = -1; } - else if (!isWhiteSpaceSingleLine(char)) { + else if (!isWhiteSpaceLike(char)) { firstNonWhitespace = pos; } pos++; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d52f277c9ef2d..fe415431c77eb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1572,8 +1572,8 @@ } export interface JsxText extends Node { - kind: SyntaxKind.JsxText, - containsOnlyWhiteSpaces: boolean, + kind: SyntaxKind.JsxText; + containsOnlyWhiteSpaces: boolean; parent?: JsxElement; } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index b5c901482a7bc..01feaf390818e 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -54,7 +54,7 @@ namespace ts.formatting { let current = position; while (current > 0) { const char = sourceFile.text.charCodeAt(current); - if (!isWhiteSpace(char)) { + if (!isWhiteSpaceLike(char)) { break; } current--; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index d7056cfdca241..e63c46ea8cedd 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -608,7 +608,7 @@ namespace ts.textChanges { if (force || !isTrivia(s)) { this.lastNonTriviaPosition = this.writer.getTextPos(); let i = 0; - while (isWhiteSpace(s.charCodeAt(s.length - i - 1))) { + while (isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { i++; } // trim trailing whitespaces diff --git a/src/services/utilities.ts b/src/services/utilities.ts index fe9a310ad4bf7..5a1acdf1cec09 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1381,7 +1381,7 @@ namespace ts { } export function getFirstNonSpaceCharacterPosition(text: string, position: number) { - while (isWhiteSpace(text.charCodeAt(position))) { + while (isWhiteSpaceLike(text.charCodeAt(position))) { position += 1; } return position; From f0990460a62bda901a0548f3d7e6a579cd06ccce Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 12 Apr 2017 12:17:27 -0700 Subject: [PATCH 09/32] Add tests --- .../jsx/checkJsxChildrenProperty1.tsx | 27 ++++++++++ .../jsx/checkJsxChildrenProperty2.tsx | 49 +++++++++++++++++++ .../jsx/checkJsxChildrenProperty3.tsx | 44 +++++++++++++++++ .../jsx/checkJsxChildrenProperty4.tsx | 49 +++++++++++++++++++ .../jsx/checkJsxChildrenProperty5.tsx | 35 +++++++++++++ .../jsx/checkJsxChildrenProperty6.tsx | 48 ++++++++++++++++++ .../jsx/checkJsxChildrenProperty7.tsx | 33 +++++++++++++ .../jsx/checkJsxChildrenProperty8.tsx | 34 +++++++++++++ ...tsxStatelessFunctionComponentOverload6.tsx | 2 +- ...nInFunctionExpressionOfChildrenCallback.ts | 31 ++++++++++++ 10 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty1.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty3.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty4.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty5.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty6.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty7.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty8.tsx create mode 100644 tests/cases/fourslash/tscCompletionInFunctionExpressionOfChildrenCallback.ts diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty1.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty1.tsx new file mode 100644 index 0000000000000..70b58c03f6ac1 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty1.tsx @@ -0,0 +1,27 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface Prop { + a: number, + b: string, + children: string | JSX.Element +} + +function Comp(p: Prop) { + return
{p.b}
; +} + +// OK +let k = ; +let k1 = + + hi hi hi! + ; +let k2 = + +
hi hi hi!
+
; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx new file mode 100644 index 0000000000000..0c78f8f41255b --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx @@ -0,0 +1,49 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface Prop { + a: number, + b: string, + children: string | JSX.Element +} + +function Comp(p: Prop) { + return
{p.b}
; +} + +// Error: missing children +let k = ; + +let k1 = + + hi hi hi! + ; + +// Error: incorrect type +let k2 = + +
My Div
+ {(name: string) =>
My name {name}
} +
; + +let k3 = + +
My Div
+ {1000000} +
; + +let k4 = + +
My Div
+ hi hi hi! +
; + +let k5 = + +
My Div
+
My Div
+
; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty3.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty3.tsx new file mode 100644 index 0000000000000..c67c6d5440dce --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty3.tsx @@ -0,0 +1,44 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface IUser { + Name: string; +} + +interface IFetchUserProps { + children: (user: IUser) => JSX.Element; +} + +class FetchUser extends React.Component { + render() { + return this.state + ? this.props.children(this.state.result) + : null; + } +} + +// Ok +function UserName0() { + return ( + + { user => ( +

{ user.Name }

+ ) } +
+ ); +} + +function UserName1() { + return ( + + + { user => ( +

{ user.Name }

+ ) } +
+ ); +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty4.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty4.tsx new file mode 100644 index 0000000000000..34877f2000cd3 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty4.tsx @@ -0,0 +1,49 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface IUser { + Name: string; +} + +interface IFetchUserProps { + children: (user: IUser) => JSX.Element; +} + +class FetchUser extends React.Component { + render() { + return this.state + ? this.props.children(this.state.result) + : null; + } +} + +// Error +function UserName() { + return ( + + { user => ( +

{ user.NAme }

+ ) } +
+ ); +} + +function UserName1() { + return ( + + + + + { user => ( +

{ user.Name }

+ ) } + { user => ( +

{ user.Name }

+ ) } +
+ ); +} \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty5.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty5.tsx new file mode 100644 index 0000000000000..6143e4b0fafa9 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty5.tsx @@ -0,0 +1,35 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface Prop { + a: number, + b: string, + children: Button; +} + +class Button extends React.Component { + render() { + return (
My Button
) + } +} + +function Comp(p: Prop) { + return
{p.b}
; +} + +// Error: no children specified +let k = ; + +// Error: JSX.element is not the same as JSX.ElementClass +let k1 = + + ; + +//// [file.jsx] +var Button = (function () { + function Button() { + } + Button.prototype.render = function () { + return (
My Button
); + }; + return Button; +}()); +// OK +var k1 =

Hello

world

; +var k2 =

Hello

{function (user) { return

{user.name}

; }}
; +var k3 =
{1} {"That is a number"}
; +var k4 = ; diff --git a/tests/baselines/reference/checkJsxChildrenProperty10.symbols b/tests/baselines/reference/checkJsxChildrenProperty10.symbols new file mode 100644 index 0000000000000..bf054377fb16a --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty10.symbols @@ -0,0 +1,73 @@ +=== tests/cases/conformance/jsx/file.tsx === +declare module JSX { +>JSX : Symbol(JSX, Decl(file.tsx, 0, 0)) + + interface Element { } +>Element : Symbol(Element, Decl(file.tsx, 0, 20)) + + interface ElementAttributesProperty { props: {} } +>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(file.tsx, 1, 22)) +>props : Symbol(ElementAttributesProperty.props, Decl(file.tsx, 2, 38)) + + interface IntrinsicElements { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(file.tsx, 2, 50)) + + div: any; +>div : Symbol(IntrinsicElements.div, Decl(file.tsx, 3, 30)) + + h2: any; +>h2 : Symbol(IntrinsicElements.h2, Decl(file.tsx, 4, 11)) + + h1: any; +>h1 : Symbol(IntrinsicElements.h1, Decl(file.tsx, 5, 10)) + } +} + +class Button { +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) + + props: {} +>props : Symbol(Button.props, Decl(file.tsx, 10, 14)) + + render() { +>render : Symbol(Button.render, Decl(file.tsx, 11, 10)) + + return (
My Button
) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + } +} + +// OK +let k1 =

Hello

world

; +>k1 : Symbol(k1, Decl(file.tsx, 18, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(file.tsx, 5, 10)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(file.tsx, 5, 10)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +>k2 : Symbol(k2, Decl(file.tsx, 19, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>user : Symbol(user, Decl(file.tsx, 19, 34)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>user : Symbol(user, Decl(file.tsx, 19, 34)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k3 =
{1} {"That is a number"}
; +>k3 : Symbol(k3, Decl(file.tsx, 20, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k4 = ; +>k4 : Symbol(k4, Decl(file.tsx, 21, 3)) +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) + diff --git a/tests/baselines/reference/checkJsxChildrenProperty10.types b/tests/baselines/reference/checkJsxChildrenProperty10.types new file mode 100644 index 0000000000000..cee5995b8515e --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty10.types @@ -0,0 +1,89 @@ +=== tests/cases/conformance/jsx/file.tsx === +declare module JSX { +>JSX : any + + interface Element { } +>Element : Element + + interface ElementAttributesProperty { props: {} } +>ElementAttributesProperty : ElementAttributesProperty +>props : {} + + interface IntrinsicElements { +>IntrinsicElements : IntrinsicElements + + div: any; +>div : any + + h2: any; +>h2 : any + + h1: any; +>h1 : any + } +} + +class Button { +>Button : Button + + props: {} +>props : {} + + render() { +>render : () => JSX.Element + + return (
My Button
) +>(
My Button
) : JSX.Element +>
My Button
: JSX.Element +>div : any +>div : any + } +} + +// OK +let k1 =

Hello

world

; +>k1 : JSX.Element +>

Hello

world

: JSX.Element +>div : any +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>

world

: JSX.Element +>h1 : any +>h1 : any +>div : any + +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +>k2 : JSX.Element +>

Hello

{(user: any) =>

{user.name}

}
: JSX.Element +>div : any +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>(user: any) =>

{user.name}

: (user: any) => JSX.Element +>user : any +>

{user.name}

: JSX.Element +>h2 : any +>user.name : any +>user : any +>name : any +>h2 : any +>div : any + +let k3 =
{1} {"That is a number"}
; +>k3 : JSX.Element +>
{1} {"That is a number"}
: JSX.Element +>div : any +>1 : 1 +>"That is a number" : "That is a number" +>div : any + +let k4 = ; +>k4 : JSX.Element +> : JSX.Element +>Button : typeof Button +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>Button : typeof Button + diff --git a/tests/baselines/reference/checkJsxChildrenProperty11.js b/tests/baselines/reference/checkJsxChildrenProperty11.js new file mode 100644 index 0000000000000..f022b28f20c28 --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty11.js @@ -0,0 +1,38 @@ +//// [file.tsx] +declare module JSX { + interface Element { } + interface ElementAttributesProperty { props: {} } + interface IntrinsicElements { + div: any; + h2: any; + h1: any; + } +} + +class Button { + props: {} + render() { + return (
My Button
) + } +} + +// OK +let k1 =

Hello

world

; +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +let k3 =
{1} {"That is a number"}
; +let k4 = ; + +//// [file.jsx] +var Button = (function () { + function Button() { + } + Button.prototype.render = function () { + return (
My Button
); + }; + return Button; +}()); +// OK +var k1 =

Hello

world

; +var k2 =

Hello

{function (user) { return

{user.name}

; }}
; +var k3 =
{1} {"That is a number"}
; +var k4 = ; diff --git a/tests/baselines/reference/checkJsxChildrenProperty11.symbols b/tests/baselines/reference/checkJsxChildrenProperty11.symbols new file mode 100644 index 0000000000000..bf054377fb16a --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty11.symbols @@ -0,0 +1,73 @@ +=== tests/cases/conformance/jsx/file.tsx === +declare module JSX { +>JSX : Symbol(JSX, Decl(file.tsx, 0, 0)) + + interface Element { } +>Element : Symbol(Element, Decl(file.tsx, 0, 20)) + + interface ElementAttributesProperty { props: {} } +>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(file.tsx, 1, 22)) +>props : Symbol(ElementAttributesProperty.props, Decl(file.tsx, 2, 38)) + + interface IntrinsicElements { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(file.tsx, 2, 50)) + + div: any; +>div : Symbol(IntrinsicElements.div, Decl(file.tsx, 3, 30)) + + h2: any; +>h2 : Symbol(IntrinsicElements.h2, Decl(file.tsx, 4, 11)) + + h1: any; +>h1 : Symbol(IntrinsicElements.h1, Decl(file.tsx, 5, 10)) + } +} + +class Button { +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) + + props: {} +>props : Symbol(Button.props, Decl(file.tsx, 10, 14)) + + render() { +>render : Symbol(Button.render, Decl(file.tsx, 11, 10)) + + return (
My Button
) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + } +} + +// OK +let k1 =

Hello

world

; +>k1 : Symbol(k1, Decl(file.tsx, 18, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(file.tsx, 5, 10)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(file.tsx, 5, 10)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +>k2 : Symbol(k2, Decl(file.tsx, 19, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>user : Symbol(user, Decl(file.tsx, 19, 34)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>user : Symbol(user, Decl(file.tsx, 19, 34)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k3 =
{1} {"That is a number"}
; +>k3 : Symbol(k3, Decl(file.tsx, 20, 3)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(file.tsx, 3, 30)) + +let k4 = ; +>k4 : Symbol(k4, Decl(file.tsx, 21, 3)) +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(file.tsx, 4, 11)) +>Button : Symbol(Button, Decl(file.tsx, 8, 1)) + diff --git a/tests/baselines/reference/checkJsxChildrenProperty11.types b/tests/baselines/reference/checkJsxChildrenProperty11.types new file mode 100644 index 0000000000000..cee5995b8515e --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty11.types @@ -0,0 +1,89 @@ +=== tests/cases/conformance/jsx/file.tsx === +declare module JSX { +>JSX : any + + interface Element { } +>Element : Element + + interface ElementAttributesProperty { props: {} } +>ElementAttributesProperty : ElementAttributesProperty +>props : {} + + interface IntrinsicElements { +>IntrinsicElements : IntrinsicElements + + div: any; +>div : any + + h2: any; +>h2 : any + + h1: any; +>h1 : any + } +} + +class Button { +>Button : Button + + props: {} +>props : {} + + render() { +>render : () => JSX.Element + + return (
My Button
) +>(
My Button
) : JSX.Element +>
My Button
: JSX.Element +>div : any +>div : any + } +} + +// OK +let k1 =

Hello

world

; +>k1 : JSX.Element +>

Hello

world

: JSX.Element +>div : any +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>

world

: JSX.Element +>h1 : any +>h1 : any +>div : any + +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +>k2 : JSX.Element +>

Hello

{(user: any) =>

{user.name}

}
: JSX.Element +>div : any +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>(user: any) =>

{user.name}

: (user: any) => JSX.Element +>user : any +>

{user.name}

: JSX.Element +>h2 : any +>user.name : any +>user : any +>name : any +>h2 : any +>div : any + +let k3 =
{1} {"That is a number"}
; +>k3 : JSX.Element +>
{1} {"That is a number"}
: JSX.Element +>div : any +>1 : 1 +>"That is a number" : "That is a number" +>div : any + +let k4 = ; +>k4 : JSX.Element +> : JSX.Element +>Button : typeof Button +>

Hello

: JSX.Element +>h2 : any +>h2 : any +>Button : typeof Button + diff --git a/tests/baselines/reference/checkJsxChildrenProperty3.symbols b/tests/baselines/reference/checkJsxChildrenProperty3.symbols index 2a1aca621e951..e2e8492156fb1 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty3.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty3.symbols @@ -61,11 +61,11 @@ function UserName0() { >user : Symbol(user, Decl(file.tsx, 22, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 22, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ) } @@ -85,11 +85,11 @@ function UserName1() { >user : Symbol(user, Decl(file.tsx, 33, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 33, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ) } diff --git a/tests/baselines/reference/checkJsxChildrenProperty6.symbols b/tests/baselines/reference/checkJsxChildrenProperty6.symbols index df48a53e37d05..7935b8cb2fe76 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty6.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty6.symbols @@ -29,8 +29,8 @@ class Button extends React.Component { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } // Ok diff --git a/tests/baselines/reference/checkJsxChildrenProperty8.symbols b/tests/baselines/reference/checkJsxChildrenProperty8.symbols index 92c2e685e71c4..211009642bb53 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty8.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty8.symbols @@ -29,8 +29,8 @@ class Button extends React.Component { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } // OK diff --git a/tests/baselines/reference/checkJsxChildrenProperty9.symbols b/tests/baselines/reference/checkJsxChildrenProperty9.symbols index 38f680a7aeba8..d37d8a1bfe656 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty9.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty9.symbols @@ -5,26 +5,26 @@ import React = require('react'); // OK let k1 =

Hello

world

; >k1 : Symbol(k1, Decl(file.tsx, 3, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) let k2 =

Hello

{(user: any) =>

{user.name}

}
; >k2 : Symbol(k2, Decl(file.tsx, 4, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2408, 48)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) let k3 =
{1} {"That is a number"}
; >k3 : Symbol(k3, Decl(file.tsx, 5, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) diff --git a/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols b/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols index 900aa7cf84225..fbe4d1bf5dc10 100644 --- a/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols +++ b/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols @@ -19,8 +19,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 5, 50)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols b/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols index 766505b551812..15d4a04901f32 100644 --- a/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols +++ b/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols @@ -19,8 +19,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 5, 50)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols index cc669b485e427..cb18cd27d624b 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols @@ -12,8 +12,8 @@ class Poisoned extends React.Component<{}, {}> { >render : Symbol(Poisoned.render, Decl(file.tsx, 2, 48)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols index f8c0bc4cf1f91..230e7b25dc5ae 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols @@ -48,8 +48,8 @@ class OverWriteAttr extends React.Component { >render : Symbol(OverWriteAttr.render, Decl(file.tsx, 17, 55)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols index ade152b687de4..c136d72444d0e 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols @@ -23,8 +23,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 7, 58)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols index c6b44bcd42859..6cb0486be61a1 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols @@ -23,8 +23,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 7, 58)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } @@ -56,8 +56,8 @@ class EmptyProp extends React.Component<{}, {}> { >render : Symbol(EmptyProp.render, Decl(file.tsx, 21, 49)) return
Default hi
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols index d3f967ca2e7d5..fd95004c914a1 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols @@ -22,8 +22,8 @@ class TextComponent extends React.Component { >render : Symbol(TextComponent.render, Decl(file.tsx, 5, 60)) return Some Text..; ->span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2458, 51)) ->span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2458, 51)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2462, 51)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2462, 51)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols index 6bfe0932173e6..1d0429a1cd154 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols @@ -45,8 +45,8 @@ class OverWriteAttr extends React.Component { >render : Symbol(OverWriteAttr.render, Decl(file.tsx, 17, 55)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols index ba9a28bfc1e41..26bda335e4fcf 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols @@ -23,8 +23,8 @@ class Opt extends React.Component { >render : Symbol(Opt.render, Decl(file.tsx, 7, 51)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } } diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols index a75b5f30c81e8..842c8b7b5d93a 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols +++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols @@ -5,7 +5,7 @@ import React = require('react'); const Foo = (props: any) =>
; >Foo : Symbol(Foo, Decl(file.tsx, 2, 5)) >props : Symbol(props, Decl(file.tsx, 2, 13)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) // Should be OK const foo = ; @@ -19,14 +19,14 @@ var MainMenu: React.StatelessComponent<{}> = (props) => (
>React : Symbol(React, Decl(file.tsx, 0, 0)) >StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) >props : Symbol(props, Decl(file.tsx, 8, 46)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45))

Main Menu

->h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2409, 48)) ->h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2409, 48)) +>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2413, 48)) +>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2413, 48))
); ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) var App: React.StatelessComponent<{ children }> = ({children}) => ( >App : Symbol(App, Decl(file.tsx, 12, 3)) @@ -36,12 +36,12 @@ var App: React.StatelessComponent<{ children }> = ({children}) => ( >children : Symbol(children, Decl(file.tsx, 12, 52))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) >MainMenu : Symbol(MainMenu, Decl(file.tsx, 8, 3))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ); diff --git a/tests/baselines/reference/tsxUnionElementType1.symbols b/tests/baselines/reference/tsxUnionElementType1.symbols index da0639ac5f15f..72b9d96dbe6aa 100644 --- a/tests/baselines/reference/tsxUnionElementType1.symbols +++ b/tests/baselines/reference/tsxUnionElementType1.symbols @@ -8,8 +8,8 @@ function SFC1(prop: { x: number }) { >x : Symbol(x, Decl(file.tsx, 2, 21)) return
hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) }; @@ -19,8 +19,8 @@ function SFC2(prop: { x: boolean }) { >x : Symbol(x, Decl(file.tsx, 6, 21)) return

World

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) } var SFCComp = SFC1 || SFC2; diff --git a/tests/baselines/reference/tsxUnionElementType5.symbols b/tests/baselines/reference/tsxUnionElementType5.symbols index e05f3deb9cca6..394e530231d6a 100644 --- a/tests/baselines/reference/tsxUnionElementType5.symbols +++ b/tests/baselines/reference/tsxUnionElementType5.symbols @@ -6,16 +6,16 @@ function EmptySFC1() { >EmptySFC1 : Symbol(EmptySFC1, Decl(file.tsx, 0, 32)) return
hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } function EmptySFC2() { >EmptySFC2 : Symbol(EmptySFC2, Decl(file.tsx, 4, 1)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) } function SFC2(prop: { x: boolean }) { @@ -24,8 +24,8 @@ function SFC2(prop: { x: boolean }) { >x : Symbol(x, Decl(file.tsx, 10, 21)) return

World

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2407, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) } var EmptySFCComp = EmptySFC1 || EmptySFC2; diff --git a/tests/baselines/reference/tsxUnionTypeComponent1.symbols b/tests/baselines/reference/tsxUnionTypeComponent1.symbols index ec57cfaa2de55..81ebe5ec01529 100644 --- a/tests/baselines/reference/tsxUnionTypeComponent1.symbols +++ b/tests/baselines/reference/tsxUnionTypeComponent1.symbols @@ -38,8 +38,8 @@ class MyComponent extends React.Component { }/> >MyComponent : Symbol(MyComponent, Decl(file.tsx, 4, 1)) >AnyComponent : Symbol(AnyComponent, Decl(file.tsx, 14, 12)) ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2383, 43)) ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2383, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2387, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2387, 43)) // Component Class as Props class MyButtonComponent extends React.Component<{},{}> { diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty10.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty10.tsx new file mode 100644 index 0000000000000..f13f44567ffb4 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty10.tsx @@ -0,0 +1,24 @@ +//@filename: file.tsx +//@jsx: preserve +declare module JSX { + interface Element { } + interface ElementAttributesProperty { props: {} } + interface IntrinsicElements { + div: any; + h2: any; + h1: any; + } +} + +class Button { + props: {} + render() { + return (
My Button
) + } +} + +// OK +let k1 =

Hello

world

; +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +let k3 =
{1} {"That is a number"}
; +let k4 = ; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty11.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty11.tsx new file mode 100644 index 0000000000000..a6fab6f506e66 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty11.tsx @@ -0,0 +1,25 @@ +//@filename: file.tsx +//@jsx: preserve +//@noImplicitAny: true +declare module JSX { + interface Element { } + interface ElementAttributesProperty { props: {} } + interface IntrinsicElements { + div: any; + h2: any; + h1: any; + } +} + +class Button { + props: {} + render() { + return (
My Button
) + } +} + +// OK +let k1 =

Hello

world

; +let k2 =

Hello

{(user: any) =>

{user.name}

}
; +let k3 =
{1} {"That is a number"}
; +let k4 = ; \ No newline at end of file diff --git a/tests/cases/fourslash/tscCompletionInFunctionExpressionOfChildrenCallback.ts b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback.ts similarity index 89% rename from tests/cases/fourslash/tscCompletionInFunctionExpressionOfChildrenCallback.ts rename to tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback.ts index 0a926e64ac0ed..911fa41470dc8 100644 --- a/tests/cases/fourslash/tscCompletionInFunctionExpressionOfChildrenCallback.ts +++ b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback.ts @@ -27,5 +27,4 @@ //// } goTo.marker(); -debugger; -verify.completionListContains('Name'); \ No newline at end of file +verify.completionListIsEmpty(); \ No newline at end of file diff --git a/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts new file mode 100644 index 0000000000000..491188115ebbb --- /dev/null +++ b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts @@ -0,0 +1,32 @@ +/// +//@module: commonjs +//@jsx: preserve + +// @Filename: 1.tsx +//// declare module JSX { +//// interface Element { } +//// interface IntrinsicElements { +//// } +//// interface ElementAttributesProperty { +//// props: { children; } +//// } +//// } +//// interface IUser { +//// Name: string; +//// } +//// interface IFetchUserProps { +//// children: (user: IUser) => any; +//// } +//// function FetchUser(props: IFetchUserProps) { return undefined; } +//// function UserName() { +//// return ( +//// +//// { user => ( +////

{ user./**/ }

+//// )} +////
+//// ); +//// } + +goTo.marker(); +verify.completionListContains('Name'); \ No newline at end of file From 7829cbae26ea1ccf6531c9958746f04b75595399 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 17 Apr 2017 13:00:45 -0700 Subject: [PATCH 17/32] Fix linting error --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 712b77ab3355b..c5b531337c93a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -411,7 +411,7 @@ namespace ts { let _jsxNamespace: string; let _jsxFactoryEntity: EntityName; - let _jsxElementAttribPropInterfaceSymbol: Symbol; // JSX.ElementAttributesProperty [symbol] + let _jsxElementAttribPropInterfaceSymbol: Symbol; // JSX.ElementAttributesProperty [symbol] let _jsxElementPropertiesName: string; let _jsxElementChildrenPropertyName: string; @@ -13506,7 +13506,7 @@ namespace ts { const propsType = getTypeOfSymbol(propertiesOfJsxElementAttribPropInterface[0]); const propertiesOfProps = propsType && getPropertiesOfType(propsType); if (propertiesOfProps && propertiesOfProps.length === 1) { - _jsxElementChildrenPropertyName = propertiesOfProps[0].name; + _jsxElementChildrenPropertyName = propertiesOfProps[0].name; } } } From d290cf7633d2d05300ff7332decff7de095b4eab Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 17 Apr 2017 13:11:16 -0700 Subject: [PATCH 18/32] Update error message to use variable name for "children" --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- .../reference/checkJsxChildrenProperty2.errors.txt | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c5b531337c93a..95b3de8df40d8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13322,7 +13322,7 @@ namespace ts { const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); if (jsxChildrenPropertyName) { if (attributesTable.has(jsxChildrenPropertyName)) { - error(attributes, Diagnostics.props_children_are_specified_twice_The_attribute_named_children_will_be_overwritten); + error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName); } // If there are children in the body of JSX element, create dummy attribute "children" with anyType so that it will pass the attribute checking process diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 72554a9f0bacf..b7f30e2b209c8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2099,7 +2099,7 @@ "category": "Error", "code": 2707 }, - "props.children are specified twice. The attribute named 'children' will be overwritten.": { + "'{0}' are specified twice. The attribute named '{0}' will be overwritten.": { "category": "Error", "code": 2708 }, diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt index ecde87c6fbf6e..d288d92e93bc9 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt +++ b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt @@ -1,8 +1,8 @@ tests/cases/conformance/jsx/file.tsx(14,15): error TS2322: Type '{ a: 10; b: "hi"; }' is not assignable to type 'IntrinsicAttributes & Prop'. Type '{ a: 10; b: "hi"; }' is not assignable to type 'Prop'. Property 'children' is missing in type '{ a: 10; b: "hi"; }'. -tests/cases/conformance/jsx/file.tsx(17,11): error TS2708: props.children are specified twice. The attribute named 'children' will be overwritten. -tests/cases/conformance/jsx/file.tsx(25,11): error TS2708: props.children are specified twice. The attribute named 'children' will be overwritten. +tests/cases/conformance/jsx/file.tsx(17,11): error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. +tests/cases/conformance/jsx/file.tsx(25,11): error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. tests/cases/conformance/jsx/file.tsx(31,11): error TS2322: Type '{ a: 10; b: "hi"; children: (Element | ((name: string) => Element))[]; }' is not assignable to type 'IntrinsicAttributes & Prop'. Type '{ a: 10; b: "hi"; children: (Element | ((name: string) => Element))[]; }' is not assignable to type 'Prop'. Types of property 'children' are incompatible. @@ -52,7 +52,7 @@ tests/cases/conformance/jsx/file.tsx(49,11): error TS2322: Type '{ a: 10; b: "hi let k0 = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2708: props.children are specified twice. The attribute named 'children' will be overwritten. +!!! error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; @@ -62,7 +62,7 @@ tests/cases/conformance/jsx/file.tsx(49,11): error TS2322: Type '{ a: 10; b: "hi let k1 = ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2708: props.children are specified twice. The attribute named 'children' will be overwritten. +!!! error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; From c13383a3a36e0b485dda8a3b5949f18317aa7beb Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 17 Apr 2017 13:32:57 -0700 Subject: [PATCH 19/32] Fix baselines and linting error from merging with master --- src/compiler/checker.ts | 6 +++--- .../reference/checkJsxChildrenProperty2.errors.txt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb62dff01c13f..9f623abec5fd9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8696,10 +8696,10 @@ namespace ts { // type, a property is considered known if it is known in any constituent type. function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean { if (type.flags & TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type); + const resolved = resolveStructuredTypeMembers(type); if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) || getPropertyOfType(type, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { - // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. + // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; } } @@ -13477,7 +13477,7 @@ namespace ts { function getPropertiesFromJsxElementAttributesProperty() { if (!_jsxElementAttribPropInterfaceSymbol) { // JSX - const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/undefined); + const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); // JSX.ElementAttributesProperty [symbol] _jsxElementAttribPropInterfaceSymbol = jsxNamespace && getSymbol(jsxNamespace.exports, JsxNames.ElementAttributesPropertyNameContainer, SymbolFlags.Type); } diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt index d288d92e93bc9..6bb91bd638501 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt +++ b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt @@ -1,8 +1,8 @@ tests/cases/conformance/jsx/file.tsx(14,15): error TS2322: Type '{ a: 10; b: "hi"; }' is not assignable to type 'IntrinsicAttributes & Prop'. Type '{ a: 10; b: "hi"; }' is not assignable to type 'Prop'. Property 'children' is missing in type '{ a: 10; b: "hi"; }'. -tests/cases/conformance/jsx/file.tsx(17,11): error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. -tests/cases/conformance/jsx/file.tsx(25,11): error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. +tests/cases/conformance/jsx/file.tsx(17,11): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. +tests/cases/conformance/jsx/file.tsx(25,11): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. tests/cases/conformance/jsx/file.tsx(31,11): error TS2322: Type '{ a: 10; b: "hi"; children: (Element | ((name: string) => Element))[]; }' is not assignable to type 'IntrinsicAttributes & Prop'. Type '{ a: 10; b: "hi"; children: (Element | ((name: string) => Element))[]; }' is not assignable to type 'Prop'. Types of property 'children' are incompatible. @@ -52,7 +52,7 @@ tests/cases/conformance/jsx/file.tsx(49,11): error TS2322: Type '{ a: 10; b: "hi let k0 = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. +!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; @@ -62,7 +62,7 @@ tests/cases/conformance/jsx/file.tsx(49,11): error TS2322: Type '{ a: 10; b: "hi let k1 = ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2708: 'children' are specified twice. The attribute named 'children' will be overwritten. +!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; From 13afdb81e8bd836e2b2171facf0c62e7ddbfce0a Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Thu, 20 Apr 2017 10:19:56 +0800 Subject: [PATCH 20/32] fix #15243: add URLSearchParams to iterable --- src/lib/dom.iterable.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index b5e0404c17bdd..1f047e33ba7fe 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -70,3 +70,10 @@ interface NodeListOf { [Symbol.iterator](): IterableIterator; } + +interface URLSearchParams { + /** + * iterate over key/value pairs + */ + [Symbol.iterator](): IterableIterator<[string, string]>; +} From e9cd3ade8600527b7ed9f1b13a514e5b61048580 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 19 Apr 2017 22:33:33 -0700 Subject: [PATCH 21/32] Change how we look up children attribute from react.d.ts --- src/compiler/checker.ts | 103 +++++++++++++++------------------------- tests/lib/react.d.ts | 8 ++-- 2 files changed, 42 insertions(+), 69 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f623abec5fd9..0524c24a70047 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -423,17 +423,20 @@ namespace ts { let _jsxNamespace: string; let _jsxFactoryEntity: EntityName; - let _jsxElementAttribPropInterfaceSymbol: Symbol; // JSX.ElementAttributesProperty [symbol] let _jsxElementPropertiesName: string; + let _hasComputedJsxElementPropertiesName = false; let _jsxElementChildrenPropertyName: string; + let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ const jsxTypes = createMap(); + const JsxNames = { JSX: "JSX", IntrinsicElements: "IntrinsicElements", ElementClass: "ElementClass", ElementAttributesPropertyNameContainer: "ElementAttributesProperty", + ElementChildrenAttributeNameContainer: "ElementChildrenAttribute", Element: "Element", IntrinsicAttributes: "IntrinsicAttributes", IntrinsicClassAttributes: "IntrinsicClassAttributes" @@ -12696,7 +12699,7 @@ namespace ts { else if (node.parent.kind === SyntaxKind.JsxElement) { // JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty) const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); - return jsxChildrenPropertyName ? getTypeOfPropertyOfType(attributesType, jsxChildrenPropertyName) : anyType; + return jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfType(attributesType, jsxChildrenPropertyName) : anyType; } else { // JSX expression is in JSX spread attribute @@ -13361,7 +13364,7 @@ namespace ts { // Error if there is a attribute named "children" and children element. // This is because children element will overwrite the value from attributes const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); - if (jsxChildrenPropertyName) { + if (jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { if (attributesTable.has(jsxChildrenPropertyName)) { error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName); } @@ -13474,14 +13477,34 @@ namespace ts { return getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true); } - function getPropertiesFromJsxElementAttributesProperty() { - if (!_jsxElementAttribPropInterfaceSymbol) { - // JSX - const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); - // JSX.ElementAttributesProperty [symbol] - _jsxElementAttribPropInterfaceSymbol = jsxNamespace && getSymbol(jsxNamespace.exports, JsxNames.ElementAttributesPropertyNameContainer, SymbolFlags.Type); + /** + * + */ + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: string): string { + // JSX + const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] + const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, SymbolFlags.Type); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] + const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); + // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute + const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); + if (propertiesOfJsxElementAttribPropInterface) { + // Element Attributes has zero properties, so the element attributes type will be the class instance type + if (propertiesOfJsxElementAttribPropInterface.length === 0) { + return ""; + } + // Element Attributes has one property, so the element attributes type will be the type of the corresponding + // property of the class instance type + else if (propertiesOfJsxElementAttribPropInterface.length === 1) { + return propertiesOfJsxElementAttribPropInterface[0].name; + } + else if (propertiesOfJsxElementAttribPropInterface.length > 1) { + // More than one property on ElementAttributesProperty is an error + error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer); + } } - return _jsxElementAttribPropInterfaceSymbol; + return undefined; } /// e.g. "props" for React.d.ts, @@ -13490,66 +13513,18 @@ namespace ts { /// or '' if it has 0 properties (which means every /// non-intrinsic elements' attributes type is the element instance type) function getJsxElementPropertiesName() { - if (!_jsxElementPropertiesName) { - const jsxElementAttribPropInterfaceSym = getPropertiesFromJsxElementAttributesProperty(); - // JSX.ElementAttributesProperty [type] - const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); - // The properties of JSX.ElementAttributesProperty - const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); - - // if there is a property in JSX.ElementAttributesProperty - // i.e. - // interface ElementAttributesProperty { - // props: { - // children?: any; - // }; - // } - if (propertiesOfJsxElementAttribPropInterface) { - // Element Attributes has zero properties, so the element attributes type will be the class instance type - if (propertiesOfJsxElementAttribPropInterface.length === 0) { - _jsxElementPropertiesName = ""; - } - // Element Attributes has one property, so the element attributes type will be the type of the corresponding - // property of the class instance type - else if (propertiesOfJsxElementAttribPropInterface.length === 1) { - _jsxElementPropertiesName = propertiesOfJsxElementAttribPropInterface[0].name; - } - // More than one property on ElementAttributesProperty is an error - else { - error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, JsxNames.ElementAttributesPropertyNameContainer); - _jsxElementPropertiesName = undefined; - } - } - else { - // No interface exists, so the element attributes type will be an implicit any - _jsxElementPropertiesName = undefined; - } + if (!_hasComputedJsxElementPropertiesName) { + _hasComputedJsxElementPropertiesName = true; + _jsxElementPropertiesName = getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer); } return _jsxElementPropertiesName; } function getJsxElementChildrenPropertyname(): string { - if (!_jsxElementChildrenPropertyName) { - const jsxElementAttribPropInterfaceSym = getPropertiesFromJsxElementAttributesProperty(); - // JSX.ElementAttributesProperty [type] - const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); - // The properties of JSX.ElementAttributesProperty - const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); - // if there is a property in JSX.ElementAttributesProperty - // i.e. - // interface ElementAttributesProperty { - // props: { - // children?: any; - // }; - // } - if (propertiesOfJsxElementAttribPropInterface && propertiesOfJsxElementAttribPropInterface.length === 1) { - const propsType = getTypeOfSymbol(propertiesOfJsxElementAttribPropInterface[0]); - const propertiesOfProps = propsType && getPropertiesOfType(propsType); - if (propertiesOfProps && propertiesOfProps.length === 1) { - _jsxElementChildrenPropertyName = propertiesOfProps[0].name; - } - } + if (!_hasComputedJsxElementChildrenPropertyName) { + _hasComputedJsxElementChildrenPropertyName = true; + _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); } return _jsxElementChildrenPropertyName; diff --git a/tests/lib/react.d.ts b/tests/lib/react.d.ts index cb34c8ab38f9b..0629cb956fc9b 100644 --- a/tests/lib/react.d.ts +++ b/tests/lib/react.d.ts @@ -2359,11 +2359,9 @@ declare namespace JSX { interface ElementClass extends React.Component { render(): JSX.Element | null; } - interface ElementAttributesProperty { - props: { - children: any; - }; - } + interface ElementAttributesProperty { props; } + + interface ElementChildrenAttribute { children; } interface IntrinsicAttributes extends React.Attributes { } From b7a30c11bd321a1c59c6d902caf4f5c145984be5 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 19 Apr 2017 22:33:54 -0700 Subject: [PATCH 22/32] Update tests and baselines --- .../checkJsxChildrenProperty1.symbols | 8 +++--- .../checkJsxChildrenProperty3.symbols | 8 +++--- .../checkJsxChildrenProperty6.symbols | 12 ++++---- .../checkJsxChildrenProperty8.symbols | 12 ++++---- .../checkJsxChildrenProperty9.symbols | 28 +++++++++---------- .../tsxDefaultAttributesResolution1.symbols | 4 +-- .../tsxDefaultAttributesResolution2.symbols | 4 +-- .../tsxSpreadAttributesResolution1.symbols | 4 +-- .../tsxSpreadAttributesResolution11.symbols | 4 +-- .../tsxSpreadAttributesResolution3.symbols | 4 +-- .../tsxSpreadAttributesResolution4.symbols | 8 +++--- .../tsxSpreadAttributesResolution7.symbols | 4 +-- .../tsxSpreadAttributesResolution8.symbols | 4 +-- .../tsxSpreadAttributesResolution9.symbols | 4 +-- .../tsxStatelessFunctionComponents3.symbols | 14 +++++----- .../reference/tsxUnionElementType1.symbols | 8 +++--- .../reference/tsxUnionElementType5.symbols | 12 ++++---- .../reference/tsxUnionTypeComponent1.symbols | 4 +-- ...InFunctionExpressionOfChildrenCallback1.ts | 5 ++-- 19 files changed, 75 insertions(+), 76 deletions(-) diff --git a/tests/baselines/reference/checkJsxChildrenProperty1.symbols b/tests/baselines/reference/checkJsxChildrenProperty1.symbols index d80a3b1e82b5f..8793d0edd496d 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty1.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty1.symbols @@ -23,11 +23,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 8, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } // OK @@ -59,8 +59,8 @@ let k2 = >b : Symbol(b, Decl(file.tsx, 19, 16))
hi hi hi!
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ; >Comp : Symbol(Comp, Decl(file.tsx, 6, 1)) diff --git a/tests/baselines/reference/checkJsxChildrenProperty3.symbols b/tests/baselines/reference/checkJsxChildrenProperty3.symbols index e2e8492156fb1..49d146f07dac4 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty3.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty3.symbols @@ -61,11 +61,11 @@ function UserName0() { >user : Symbol(user, Decl(file.tsx, 22, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 22, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ) } @@ -85,11 +85,11 @@ function UserName1() { >user : Symbol(user, Decl(file.tsx, 33, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 33, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ) } diff --git a/tests/baselines/reference/checkJsxChildrenProperty6.symbols b/tests/baselines/reference/checkJsxChildrenProperty6.symbols index 7935b8cb2fe76..e69b24a89ab22 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty6.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty6.symbols @@ -29,8 +29,8 @@ class Button extends React.Component { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } // Ok diff --git a/tests/baselines/reference/checkJsxChildrenProperty8.symbols b/tests/baselines/reference/checkJsxChildrenProperty8.symbols index 211009642bb53..b6f5f97adac23 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty8.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty8.symbols @@ -29,8 +29,8 @@ class Button extends React.Component { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } // OK diff --git a/tests/baselines/reference/checkJsxChildrenProperty9.symbols b/tests/baselines/reference/checkJsxChildrenProperty9.symbols index d37d8a1bfe656..25a32aae695f8 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty9.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty9.symbols @@ -5,26 +5,26 @@ import React = require('react'); // OK let k1 =

Hello

world

; >k1 : Symbol(k1, Decl(file.tsx, 3, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) let k2 =

Hello

{(user: any) =>

{user.name}

}
; >k2 : Symbol(k2, Decl(file.tsx, 4, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2412, 48)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) let k3 =
{1} {"That is a number"}
; >k3 : Symbol(k3, Decl(file.tsx, 5, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) diff --git a/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols b/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols index fbe4d1bf5dc10..ff8926b0ab0c8 100644 --- a/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols +++ b/tests/baselines/reference/tsxDefaultAttributesResolution1.symbols @@ -19,8 +19,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 5, 50)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols b/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols index 15d4a04901f32..61d007ddbefa3 100644 --- a/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols +++ b/tests/baselines/reference/tsxDefaultAttributesResolution2.symbols @@ -19,8 +19,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 5, 50)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols index cb18cd27d624b..273ea39281aed 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution1.symbols @@ -12,8 +12,8 @@ class Poisoned extends React.Component<{}, {}> { >render : Symbol(Poisoned.render, Decl(file.tsx, 2, 48)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols index 230e7b25dc5ae..5646934ef4155 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution11.symbols @@ -48,8 +48,8 @@ class OverWriteAttr extends React.Component { >render : Symbol(OverWriteAttr.render, Decl(file.tsx, 17, 55)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols index c136d72444d0e..05de039a49a68 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution3.symbols @@ -23,8 +23,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 7, 58)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols index 6cb0486be61a1..93d8535658e8c 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution4.symbols @@ -23,8 +23,8 @@ class Poisoned extends React.Component { >render : Symbol(Poisoned.render, Decl(file.tsx, 7, 58)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } @@ -56,8 +56,8 @@ class EmptyProp extends React.Component<{}, {}> { >render : Symbol(EmptyProp.render, Decl(file.tsx, 21, 49)) return
Default hi
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols index fd95004c914a1..8a6e3fd317b2e 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution7.symbols @@ -22,8 +22,8 @@ class TextComponent extends React.Component { >render : Symbol(TextComponent.render, Decl(file.tsx, 5, 60)) return Some Text..; ->span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2462, 51)) ->span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2462, 51)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2460, 51)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2460, 51)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols index 1d0429a1cd154..2dec493b88676 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution8.symbols @@ -45,8 +45,8 @@ class OverWriteAttr extends React.Component { >render : Symbol(OverWriteAttr.render, Decl(file.tsx, 17, 55)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols b/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols index 26bda335e4fcf..f55b20dfe64c4 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols +++ b/tests/baselines/reference/tsxSpreadAttributesResolution9.symbols @@ -23,8 +23,8 @@ class Opt extends React.Component { >render : Symbol(Opt.render, Decl(file.tsx, 7, 51)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } } diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols index 842c8b7b5d93a..a18da7954bc56 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols +++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.symbols @@ -5,7 +5,7 @@ import React = require('react'); const Foo = (props: any) =>
; >Foo : Symbol(Foo, Decl(file.tsx, 2, 5)) >props : Symbol(props, Decl(file.tsx, 2, 13)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) // Should be OK const foo = ; @@ -19,14 +19,14 @@ var MainMenu: React.StatelessComponent<{}> = (props) => (
>React : Symbol(React, Decl(file.tsx, 0, 0)) >StatelessComponent : Symbol(React.StatelessComponent, Decl(react.d.ts, 197, 40)) >props : Symbol(props, Decl(file.tsx, 8, 46)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45))

Main Menu

->h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2413, 48)) ->h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2413, 48)) +>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2411, 48)) +>h3 : Symbol(JSX.IntrinsicElements.h3, Decl(react.d.ts, 2411, 48))
); ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) var App: React.StatelessComponent<{ children }> = ({children}) => ( >App : Symbol(App, Decl(file.tsx, 12, 3)) @@ -36,12 +36,12 @@ var App: React.StatelessComponent<{ children }> = ({children}) => ( >children : Symbol(children, Decl(file.tsx, 12, 52))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) >MainMenu : Symbol(MainMenu, Decl(file.tsx, 8, 3))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ); diff --git a/tests/baselines/reference/tsxUnionElementType1.symbols b/tests/baselines/reference/tsxUnionElementType1.symbols index 72b9d96dbe6aa..728e559ee65d8 100644 --- a/tests/baselines/reference/tsxUnionElementType1.symbols +++ b/tests/baselines/reference/tsxUnionElementType1.symbols @@ -8,8 +8,8 @@ function SFC1(prop: { x: number }) { >x : Symbol(x, Decl(file.tsx, 2, 21)) return
hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) }; @@ -19,8 +19,8 @@ function SFC2(prop: { x: boolean }) { >x : Symbol(x, Decl(file.tsx, 6, 21)) return

World

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) } var SFCComp = SFC1 || SFC2; diff --git a/tests/baselines/reference/tsxUnionElementType5.symbols b/tests/baselines/reference/tsxUnionElementType5.symbols index 394e530231d6a..9a5e94f69a319 100644 --- a/tests/baselines/reference/tsxUnionElementType5.symbols +++ b/tests/baselines/reference/tsxUnionElementType5.symbols @@ -6,16 +6,16 @@ function EmptySFC1() { >EmptySFC1 : Symbol(EmptySFC1, Decl(file.tsx, 0, 32)) return
hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } function EmptySFC2() { >EmptySFC2 : Symbol(EmptySFC2, Decl(file.tsx, 4, 1)) return
Hello
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2401, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) } function SFC2(prop: { x: boolean }) { @@ -24,8 +24,8 @@ function SFC2(prop: { x: boolean }) { >x : Symbol(x, Decl(file.tsx, 10, 21)) return

World

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2411, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) } var EmptySFCComp = EmptySFC1 || EmptySFC2; diff --git a/tests/baselines/reference/tsxUnionTypeComponent1.symbols b/tests/baselines/reference/tsxUnionTypeComponent1.symbols index 81ebe5ec01529..4af712bf3fc3e 100644 --- a/tests/baselines/reference/tsxUnionTypeComponent1.symbols +++ b/tests/baselines/reference/tsxUnionTypeComponent1.symbols @@ -38,8 +38,8 @@ class MyComponent extends React.Component { }/> >MyComponent : Symbol(MyComponent, Decl(file.tsx, 4, 1)) >AnyComponent : Symbol(AnyComponent, Decl(file.tsx, 14, 12)) ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2387, 43)) ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2387, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) // Component Class as Props class MyButtonComponent extends React.Component<{},{}> { diff --git a/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts index 491188115ebbb..d849948775e62 100644 --- a/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts +++ b/tests/cases/fourslash/tsxCompletionInFunctionExpressionOfChildrenCallback1.ts @@ -7,9 +7,8 @@ //// interface Element { } //// interface IntrinsicElements { //// } -//// interface ElementAttributesProperty { -//// props: { children; } -//// } +//// interface ElementAttributesProperty { props; } +//// interface ElementChildrenAttribute { children; } //// } //// interface IUser { //// Name: string; From e03be4518265c6ff08a6f16e3c73fbb4772e418e Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 19 Apr 2017 22:42:07 -0700 Subject: [PATCH 23/32] Fix spelling and add comment --- src/compiler/checker.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0524c24a70047..e7939967a4b75 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13478,8 +13478,12 @@ namespace ts { } /** + * Look into JSX namespace and then look for container with matching name as nameOfAttribPropContainer. + * Get a single property from that container if existed. Report an error if there are more than one property. * - */ + * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer + * if other string is given or the container doesn't exist, return undefined. + **/ function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: string): string { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); @@ -14647,7 +14651,7 @@ namespace ts { // We can figure that out by resolving attributes property and check number of properties in the resolved type // If the call has correct arity, we will then check if the argument type and parameter type is assignable - const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incoplete + const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incomplete if (callIsIncomplete) { return true; } From ab7d5ee8c7465f1ba9f350a168d93f0c276e8897 Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Fri, 21 Apr 2017 09:38:55 +0800 Subject: [PATCH 24/32] add missing methods --- src/lib/dom.iterable.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index 1f047e33ba7fe..f5e0d6573135f 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -72,6 +72,18 @@ interface NodeListOf { } interface URLSearchParams { + /** + * Returns an array of key, value pairs for every entry in the search params + */ + entries(): IterableIterator<[string, string]>; + /** + * Returns a list of keys in the search params + */ + keys(): IterableIterator; + /** + * Returns a list of values in the search params + */ + values(): IterableIterator; /** * iterate over key/value pairs */ From 4ff180d8149a2b96aec15bd64064d5cc2a6aa55f Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 21 Apr 2017 07:53:09 -0700 Subject: [PATCH 25/32] Fix null error in importTracker: VariableDeclaration might not have a VariableStatement ancestor --- src/compiler/utilities.ts | 2 +- src/services/importTracker.ts | 17 ++++++++++++++--- tests/cases/fourslash/findAllRefsCatchClause.ts | 8 ++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsCatchClause.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f34c15ee3467f..646a7b22e3f33 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1870,7 +1870,7 @@ namespace ts { } } - export function getAncestor(node: Node | undefined, kind: SyntaxKind): Node { + export function getAncestor(node: Node | undefined, kind: SyntaxKind): Node | undefined { while (node) { if (node.kind === kind) { return node; diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 1d1f9d881e18a..0108d830dd153 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -387,6 +387,7 @@ namespace ts.FindAllReferences { symbol: Symbol; exportInfo: ExportInfo; } + /** * Given a local reference, we might notice that it's an import/export and recursively search for references of that. * If at an import, look locally for the symbol it imports. @@ -398,7 +399,7 @@ namespace ts.FindAllReferences { return comingFromExport ? getExport() : getExport() || getImport(); function getExport(): ExportedSymbol | ImportedSymbol | undefined { - const { parent } = node; + const parent = node.parent!; if (symbol.flags & SymbolFlags.Export) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. @@ -414,8 +415,8 @@ namespace ts.FindAllReferences { } } else { - const exportNode = parent.kind === SyntaxKind.VariableDeclaration ? getAncestor(parent, SyntaxKind.VariableStatement) : parent; - if (hasModifier(exportNode, ModifierFlags.Export)) { + const exportNode = getExportNode(parent); + if (exportNode && hasModifier(exportNode, ModifierFlags.Export)) { if (exportNode.kind === SyntaxKind.ImportEqualsDeclaration && (exportNode as ImportEqualsDeclaration).moduleReference === node) { // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. if (comingFromExport) { @@ -492,6 +493,16 @@ namespace ts.FindAllReferences { } } + // If a reference is a variable declaration, the exported node would be the variable statement. + function getExportNode(parent: Node): Node | undefined { + if (parent.kind === SyntaxKind.VariableDeclaration) { + const p = parent as ts.VariableDeclaration; + return p.parent.kind === ts.SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined; + } else { + return parent; + } + } + function isNodeImport(node: Node): { isNamedImport: boolean } | undefined { const { parent } = node; switch (parent.kind) { diff --git a/tests/cases/fourslash/findAllRefsCatchClause.ts b/tests/cases/fourslash/findAllRefsCatchClause.ts new file mode 100644 index 0000000000000..0e7e37998508c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsCatchClause.ts @@ -0,0 +1,8 @@ +/// + +////try { } +////catch ([|{| "isWriteAccess": true, "isDefinition": true |}err|]) { +//// [|err|]; +////} + +verify.singleReferenceGroup("var err: any"); From e7e13ecbfcd5207073cc1ff2b57cbd05ea84b9b0 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 21 Apr 2017 09:42:19 -0700 Subject: [PATCH 26/32] Fix linting --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e7939967a4b75..ff58a4e67ae8e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13477,13 +13477,13 @@ namespace ts { return getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true); } - /** + /** * Look into JSX namespace and then look for container with matching name as nameOfAttribPropContainer. * Get a single property from that container if existed. Report an error if there are more than one property. - * + * * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. - **/ + */ function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: string): string { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); From e3b4c9097006bca2d491c751bd5cadf026cf95f3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 22 Apr 2017 17:08:52 -0700 Subject: [PATCH 27/32] Properly account for 'this' parameter in type predicate checks --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb28cb0bd5c19..8549f63df6f12 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11565,7 +11565,7 @@ namespace ts { } if (isIdentifierTypePredicate(predicate)) { - const predicateArgument = callExpression.arguments[predicate.parameterIndex]; + const predicateArgument = callExpression.arguments[predicate.parameterIndex - (signature.thisParameter ? 1 : 0)]; if (predicateArgument) { if (isMatchingReference(reference, predicateArgument)) { return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf); From 85d459303315c9168b4857e16c55d8e3650bfc3a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 22 Apr 2017 17:09:20 -0700 Subject: [PATCH 28/32] Add regression test --- .../typePredicateWithThisParameter.js | 43 +++++++++++ .../typePredicateWithThisParameter.symbols | 62 ++++++++++++++++ .../typePredicateWithThisParameter.types | 72 +++++++++++++++++++ .../typePredicateWithThisParameter.ts | 26 +++++++ 4 files changed, 203 insertions(+) create mode 100644 tests/baselines/reference/typePredicateWithThisParameter.js create mode 100644 tests/baselines/reference/typePredicateWithThisParameter.symbols create mode 100644 tests/baselines/reference/typePredicateWithThisParameter.types create mode 100644 tests/cases/compiler/typePredicateWithThisParameter.ts diff --git a/tests/baselines/reference/typePredicateWithThisParameter.js b/tests/baselines/reference/typePredicateWithThisParameter.js new file mode 100644 index 0000000000000..38d84546372bd --- /dev/null +++ b/tests/baselines/reference/typePredicateWithThisParameter.js @@ -0,0 +1,43 @@ +//// [typePredicateWithThisParameter.ts] +// Repro from #15310 + +interface Foo { + foo: string; +} +interface Bar { + bar: string; +} + +function isFoo1(object: {}): object is Foo { + return 'foo' in object; +} + +function isFoo2(this: void, object: {}): object is Foo { + return 'foo' in object; +} + +declare let test: Foo | Bar; + +if (isFoo1(test)) { + test.foo = 'hi'; +} + +if (isFoo2(test)) { + test.foo = 'hi'; +} + + +//// [typePredicateWithThisParameter.js] +// Repro from #15310 +function isFoo1(object) { + return 'foo' in object; +} +function isFoo2(object) { + return 'foo' in object; +} +if (isFoo1(test)) { + test.foo = 'hi'; +} +if (isFoo2(test)) { + test.foo = 'hi'; +} diff --git a/tests/baselines/reference/typePredicateWithThisParameter.symbols b/tests/baselines/reference/typePredicateWithThisParameter.symbols new file mode 100644 index 0000000000000..e0de3073051bc --- /dev/null +++ b/tests/baselines/reference/typePredicateWithThisParameter.symbols @@ -0,0 +1,62 @@ +=== tests/cases/compiler/typePredicateWithThisParameter.ts === +// Repro from #15310 + +interface Foo { +>Foo : Symbol(Foo, Decl(typePredicateWithThisParameter.ts, 0, 0)) + + foo: string; +>foo : Symbol(Foo.foo, Decl(typePredicateWithThisParameter.ts, 2, 15)) +} +interface Bar { +>Bar : Symbol(Bar, Decl(typePredicateWithThisParameter.ts, 4, 1)) + + bar: string; +>bar : Symbol(Bar.bar, Decl(typePredicateWithThisParameter.ts, 5, 15)) +} + +function isFoo1(object: {}): object is Foo { +>isFoo1 : Symbol(isFoo1, Decl(typePredicateWithThisParameter.ts, 7, 1)) +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 9, 16)) +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 9, 16)) +>Foo : Symbol(Foo, Decl(typePredicateWithThisParameter.ts, 0, 0)) + + return 'foo' in object; +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 9, 16)) +} + +function isFoo2(this: void, object: {}): object is Foo { +>isFoo2 : Symbol(isFoo2, Decl(typePredicateWithThisParameter.ts, 11, 1)) +>this : Symbol(this, Decl(typePredicateWithThisParameter.ts, 13, 16)) +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 13, 27)) +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 13, 27)) +>Foo : Symbol(Foo, Decl(typePredicateWithThisParameter.ts, 0, 0)) + + return 'foo' in object; +>object : Symbol(object, Decl(typePredicateWithThisParameter.ts, 13, 27)) +} + +declare let test: Foo | Bar; +>test : Symbol(test, Decl(typePredicateWithThisParameter.ts, 17, 11)) +>Foo : Symbol(Foo, Decl(typePredicateWithThisParameter.ts, 0, 0)) +>Bar : Symbol(Bar, Decl(typePredicateWithThisParameter.ts, 4, 1)) + +if (isFoo1(test)) { +>isFoo1 : Symbol(isFoo1, Decl(typePredicateWithThisParameter.ts, 7, 1)) +>test : Symbol(test, Decl(typePredicateWithThisParameter.ts, 17, 11)) + + test.foo = 'hi'; +>test.foo : Symbol(Foo.foo, Decl(typePredicateWithThisParameter.ts, 2, 15)) +>test : Symbol(test, Decl(typePredicateWithThisParameter.ts, 17, 11)) +>foo : Symbol(Foo.foo, Decl(typePredicateWithThisParameter.ts, 2, 15)) +} + +if (isFoo2(test)) { +>isFoo2 : Symbol(isFoo2, Decl(typePredicateWithThisParameter.ts, 11, 1)) +>test : Symbol(test, Decl(typePredicateWithThisParameter.ts, 17, 11)) + + test.foo = 'hi'; +>test.foo : Symbol(Foo.foo, Decl(typePredicateWithThisParameter.ts, 2, 15)) +>test : Symbol(test, Decl(typePredicateWithThisParameter.ts, 17, 11)) +>foo : Symbol(Foo.foo, Decl(typePredicateWithThisParameter.ts, 2, 15)) +} + diff --git a/tests/baselines/reference/typePredicateWithThisParameter.types b/tests/baselines/reference/typePredicateWithThisParameter.types new file mode 100644 index 0000000000000..382a12faa9ddd --- /dev/null +++ b/tests/baselines/reference/typePredicateWithThisParameter.types @@ -0,0 +1,72 @@ +=== tests/cases/compiler/typePredicateWithThisParameter.ts === +// Repro from #15310 + +interface Foo { +>Foo : Foo + + foo: string; +>foo : string +} +interface Bar { +>Bar : Bar + + bar: string; +>bar : string +} + +function isFoo1(object: {}): object is Foo { +>isFoo1 : (object: {}) => object is Foo +>object : {} +>object : any +>Foo : Foo + + return 'foo' in object; +>'foo' in object : boolean +>'foo' : "foo" +>object : {} +} + +function isFoo2(this: void, object: {}): object is Foo { +>isFoo2 : (this: void, object: {}) => object is Foo +>this : void +>object : {} +>object : any +>Foo : Foo + + return 'foo' in object; +>'foo' in object : boolean +>'foo' : "foo" +>object : {} +} + +declare let test: Foo | Bar; +>test : Foo | Bar +>Foo : Foo +>Bar : Bar + +if (isFoo1(test)) { +>isFoo1(test) : boolean +>isFoo1 : (object: {}) => object is Foo +>test : Foo | Bar + + test.foo = 'hi'; +>test.foo = 'hi' : "hi" +>test.foo : string +>test : Foo +>foo : string +>'hi' : "hi" +} + +if (isFoo2(test)) { +>isFoo2(test) : boolean +>isFoo2 : (this: void, object: {}) => object is Foo +>test : Foo | Bar + + test.foo = 'hi'; +>test.foo = 'hi' : "hi" +>test.foo : string +>test : Foo +>foo : string +>'hi' : "hi" +} + diff --git a/tests/cases/compiler/typePredicateWithThisParameter.ts b/tests/cases/compiler/typePredicateWithThisParameter.ts new file mode 100644 index 0000000000000..de2b6eb94c8a3 --- /dev/null +++ b/tests/cases/compiler/typePredicateWithThisParameter.ts @@ -0,0 +1,26 @@ +// Repro from #15310 + +interface Foo { + foo: string; +} +interface Bar { + bar: string; +} + +function isFoo1(object: {}): object is Foo { + return 'foo' in object; +} + +function isFoo2(this: void, object: {}): object is Foo { + return 'foo' in object; +} + +declare let test: Foo | Bar; + +if (isFoo1(test)) { + test.foo = 'hi'; +} + +if (isFoo2(test)) { + test.foo = 'hi'; +} From d08960fbd3400d0581dde5c1cd92c972bc638bc2 Mon Sep 17 00:00:00 2001 From: gcnew Date: Sun, 23 Apr 2017 19:12:56 +0300 Subject: [PATCH 29/32] Allow exporting of consts even if `strictNullChecks` is on --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb28cb0bd5c19..d43bd907c4635 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11807,7 +11807,7 @@ namespace ts { // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). const assumeInitialized = isParameter || isOuterVariable || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node)) || + type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || isInAmbientContext(declaration); const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : From 9c2a74c26c9b161803a20f0c8fac09a88750ba8c Mon Sep 17 00:00:00 2001 From: gcnew Date: Sun, 23 Apr 2017 19:11:01 +0300 Subject: [PATCH 30/32] Update tests --- .../reference/exportBinding.errors.txt | 27 +++++++++++++++++++ tests/baselines/reference/exportBinding.js | 24 +++++++++++++++-- .../conformance/es6/modules/exportBinding.ts | 12 +++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/exportBinding.errors.txt diff --git a/tests/baselines/reference/exportBinding.errors.txt b/tests/baselines/reference/exportBinding.errors.txt new file mode 100644 index 0000000000000..552c048faf7a3 --- /dev/null +++ b/tests/baselines/reference/exportBinding.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/es6/modules/exportConsts.ts(3,16): error TS2448: Block-scoped variable 'x' used before its declaration. +tests/cases/conformance/es6/modules/exportConsts.ts(3,16): error TS2454: Variable 'x' is used before being assigned. +tests/cases/conformance/es6/modules/exportVars.ts(3,16): error TS2454: Variable 'y' is used before being assigned. + + +==== tests/cases/conformance/es6/modules/exportConsts.ts (2 errors) ==== + export { x } + export { x as xx } + export default x; + ~ +!!! error TS2448: Block-scoped variable 'x' used before its declaration. + ~ +!!! error TS2454: Variable 'x' is used before being assigned. + + const x = 'x' + + export { Y as Z } + class Y {} + +==== tests/cases/conformance/es6/modules/exportVars.ts (1 errors) ==== + export { y } + export { y as yy } + export default y; + ~ +!!! error TS2454: Variable 'y' is used before being assigned. + var y = 'y' + \ No newline at end of file diff --git a/tests/baselines/reference/exportBinding.js b/tests/baselines/reference/exportBinding.js index 5059c5356a376..3e0f23ad31d30 100644 --- a/tests/baselines/reference/exportBinding.js +++ b/tests/baselines/reference/exportBinding.js @@ -1,19 +1,39 @@ -//// [exportBinding.ts] +//// [tests/cases/conformance/es6/modules/exportBinding.ts] //// + +//// [exportConsts.ts] export { x } +export { x as xx } +export default x; + const x = 'x' export { Y as Z } class Y {} +//// [exportVars.ts] +export { y } +export { y as yy } +export default y; +var y = 'y' + -//// [exportBinding.js] +//// [exportConsts.js] "use strict"; exports.__esModule = true; +exports["default"] = x; var x = 'x'; exports.x = x; +exports.xx = x; var Y = (function () { function Y() { } return Y; }()); exports.Z = Y; +//// [exportVars.js] +"use strict"; +exports.__esModule = true; +exports["default"] = y; +var y = 'y'; +exports.y = y; +exports.yy = y; diff --git a/tests/cases/conformance/es6/modules/exportBinding.ts b/tests/cases/conformance/es6/modules/exportBinding.ts index 1e6b0314f0bd0..4d9fd7e09fbac 100644 --- a/tests/cases/conformance/es6/modules/exportBinding.ts +++ b/tests/cases/conformance/es6/modules/exportBinding.ts @@ -1,5 +1,17 @@ +// @filename: exportConsts.ts +// @strict: true export { x } +export { x as xx } +export default x; + const x = 'x' export { Y as Z } class Y {} + +// @filename: exportVars.ts +// @strict: true +export { y } +export { y as yy } +export default y; +var y = 'y' From 1fb010e7f8297d291b852682bc79c5910187052c Mon Sep 17 00:00:00 2001 From: Yuichi Nukiyama Date: Mon, 24 Apr 2017 23:42:23 +0900 Subject: [PATCH 31/32] add Symbol.iterator --- src/lib/dom.iterable.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index 94a710f648898..3701a185b703b 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -22,6 +22,7 @@ interface FormData { } interface Headers { + [Symbol.iterator](): IterableIterator<[String, String]>; /** * Returns an iterator allowing to go through all key/value pairs contained in this object. */ From 271350129815662b88242238a35366a3056e93c8 Mon Sep 17 00:00:00 2001 From: Yuichi Nukiyama Date: Tue, 25 Apr 2017 00:02:33 +0900 Subject: [PATCH 32/32] fix mistake --- src/lib/dom.iterable.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index 3701a185b703b..2a6cb16eab3e0 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -22,7 +22,7 @@ interface FormData { } interface Headers { - [Symbol.iterator](): IterableIterator<[String, String]>; + [Symbol.iterator](): IterableIterator<[string, string]>; /** * Returns an iterator allowing to go through all key/value pairs contained in this object. */