Skip to content

Commit ca6f1c3

Browse files
authored
Merge pull request #13640 from Microsoft/wip-master-statelessOverload
Using overload to figure out function signature for SFC
2 parents 9be853f + a52ccff commit ca6f1c3

File tree

268 files changed

+11474
-970
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

268 files changed

+11474
-970
lines changed

src/compiler/binder.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,7 @@ namespace ts {
13641364
case SyntaxKind.TypeLiteral:
13651365
case SyntaxKind.JSDocTypeLiteral:
13661366
case SyntaxKind.JSDocRecordType:
1367+
case SyntaxKind.JsxAttributes:
13671368
return ContainerFlags.IsContainer;
13681369

13691370
case SyntaxKind.InterfaceDeclaration:
@@ -1470,6 +1471,7 @@ namespace ts {
14701471
case SyntaxKind.InterfaceDeclaration:
14711472
case SyntaxKind.JSDocRecordType:
14721473
case SyntaxKind.JSDocTypeLiteral:
1474+
case SyntaxKind.JsxAttributes:
14731475
// Interface/Object-types always have their children added to the 'members' of
14741476
// their container. They are only accessible through an instance of their
14751477
// container, and are never in scope otherwise (even inside the body of the
@@ -1659,6 +1661,14 @@ namespace ts {
16591661
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
16601662
}
16611663

1664+
function bindJsxAttributes(node: JsxAttributes) {
1665+
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes");
1666+
}
1667+
1668+
function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
1669+
return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
1670+
}
1671+
16621672
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
16631673
const symbol = createSymbol(symbolFlags, name);
16641674
addDeclarationToSymbol(symbol, node, symbolFlags);
@@ -2080,6 +2090,12 @@ namespace ts {
20802090
case SyntaxKind.ModuleDeclaration:
20812091
return bindModuleDeclaration(<ModuleDeclaration>node);
20822092

2093+
// Jsx-attributes
2094+
case SyntaxKind.JsxAttributes:
2095+
return bindJsxAttributes(<JsxAttributes>node);
2096+
case SyntaxKind.JsxAttribute:
2097+
return bindJsxAttribute(<JsxAttribute>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
2098+
20832099
// Imports and exports
20842100
case SyntaxKind.ImportEqualsDeclaration:
20852101
case SyntaxKind.NamespaceImport:
@@ -3156,6 +3172,7 @@ namespace ts {
31563172
case SyntaxKind.JsxText:
31573173
case SyntaxKind.JsxClosingElement:
31583174
case SyntaxKind.JsxAttribute:
3175+
case SyntaxKind.JsxAttributes:
31593176
case SyntaxKind.JsxSpreadAttribute:
31603177
case SyntaxKind.JsxExpression:
31613178
// These nodes are Jsx syntax.

src/compiler/checker.ts

Lines changed: 480 additions & 168 deletions
Large diffs are not rendered by default.

src/compiler/emitter.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ namespace ts {
604604
return emitJsxClosingElement(<JsxClosingElement>node);
605605
case SyntaxKind.JsxAttribute:
606606
return emitJsxAttribute(<JsxAttribute>node);
607+
case SyntaxKind.JsxAttributes:
608+
return emitJsxAttributes(<JsxAttributes>node);
607609
case SyntaxKind.JsxSpreadAttribute:
608610
return emitJsxSpreadAttribute(<JsxSpreadAttribute>node);
609611
case SyntaxKind.JsxExpression:
@@ -1891,15 +1893,21 @@ namespace ts {
18911893
write("<");
18921894
emitJsxTagName(node.tagName);
18931895
write(" ");
1894-
emitList(node, node.attributes, ListFormat.JsxElementAttributes);
1896+
// We are checking here so we won't re-enter the emiting pipeline and emit extra sourcemap
1897+
if (node.attributes.properties && node.attributes.properties.length > 0) {
1898+
emit(node.attributes);
1899+
}
18951900
write("/>");
18961901
}
18971902

18981903
function emitJsxOpeningElement(node: JsxOpeningElement) {
18991904
write("<");
19001905
emitJsxTagName(node.tagName);
1901-
writeIfAny(node.attributes, " ");
1902-
emitList(node, node.attributes, ListFormat.JsxElementAttributes);
1906+
writeIfAny(node.attributes.properties, " ");
1907+
// We are checking here so we won't re-enter the emitting pipeline and emit extra sourcemap
1908+
if (node.attributes.properties && node.attributes.properties.length > 0) {
1909+
emit(node.attributes);
1910+
}
19031911
write(">");
19041912
}
19051913

@@ -1913,6 +1921,10 @@ namespace ts {
19131921
write(">");
19141922
}
19151923

1924+
function emitJsxAttributes(node: JsxAttributes) {
1925+
emitList(node, node.properties, ListFormat.JsxElementAttributes);
1926+
}
1927+
19161928
function emitJsxAttribute(node: JsxAttribute) {
19171929
emit(node.name);
19181930
emitWithPrefix("=", node.initializer);

src/compiler/factory.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,28 +1381,28 @@ namespace ts {
13811381
: node;
13821382
}
13831383

1384-
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
1384+
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
13851385
const node = <JsxSelfClosingElement>createSynthesizedNode(SyntaxKind.JsxSelfClosingElement);
13861386
node.tagName = tagName;
1387-
node.attributes = createNodeArray(attributes);
1387+
node.attributes = attributes;
13881388
return node;
13891389
}
13901390

1391-
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
1391+
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
13921392
return node.tagName !== tagName
13931393
|| node.attributes !== attributes
13941394
? updateNode(createJsxSelfClosingElement(tagName, attributes), node)
13951395
: node;
13961396
}
13971397

1398-
export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
1398+
export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
13991399
const node = <JsxOpeningElement>createSynthesizedNode(SyntaxKind.JsxOpeningElement);
14001400
node.tagName = tagName;
1401-
node.attributes = createNodeArray(attributes);
1401+
node.attributes = attributes;
14021402
return node;
14031403
}
14041404

1405-
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) {
1405+
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
14061406
return node.tagName !== tagName
14071407
|| node.attributes !== attributes
14081408
? updateNode(createJsxOpeningElement(tagName, attributes), node)
@@ -1421,6 +1421,19 @@ namespace ts {
14211421
: node;
14221422
}
14231423

1424+
export function createJsxAttributes(properties: JsxAttributeLike[]) {
1425+
const jsxAttributes = <JsxAttributes>createSynthesizedNode(SyntaxKind.JsxAttributes);
1426+
jsxAttributes.properties = createNodeArray(properties);
1427+
return jsxAttributes;
1428+
}
1429+
1430+
export function updateJsxAttributes(jsxAttributes: JsxAttributes, properties: JsxAttributeLike[]) {
1431+
if (jsxAttributes.properties !== properties) {
1432+
return updateNode(createJsxAttributes(properties), jsxAttributes);
1433+
}
1434+
return jsxAttributes;
1435+
}
1436+
14241437
export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression) {
14251438
const node = <JsxAttribute>createSynthesizedNode(SyntaxKind.JsxAttribute);
14261439
node.name = name;

src/compiler/parser.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ namespace ts {
369369
case SyntaxKind.JsxSelfClosingElement:
370370
case SyntaxKind.JsxOpeningElement:
371371
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
372-
visitNodes(cbNodes, (<JsxOpeningLikeElement>node).attributes);
372+
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
373+
case SyntaxKind.JsxAttributes:
374+
return visitNodes(cbNodes, (<JsxAttributes>node).properties);
373375
case SyntaxKind.JsxAttribute:
374376
return visitNode(cbNode, (<JsxAttribute>node).name) ||
375377
visitNode(cbNode, (<JsxAttribute>node).initializer);
@@ -3870,14 +3872,20 @@ namespace ts {
38703872
return result;
38713873
}
38723874

3875+
function parseJsxAttributes(): JsxAttributes {
3876+
const jsxAttributes = <JsxAttributes>createNode(SyntaxKind.JsxAttributes);
3877+
jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
3878+
return finishNode(jsxAttributes);
3879+
}
3880+
38733881
function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement {
38743882
const fullStart = scanner.getStartPos();
38753883

38763884
parseExpected(SyntaxKind.LessThanToken);
38773885

38783886
const tagName = parseJsxElementName();
3887+
const attributes = parseJsxAttributes();
38793888

3880-
const attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
38813889
let node: JsxOpeningLikeElement;
38823890

38833891
if (token() === SyntaxKind.GreaterThanToken) {

src/compiler/transformers/jsx.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ namespace ts {
8585
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) {
8686
const tagName = getTagName(node);
8787
let objectProperties: Expression;
88-
const attrs = node.attributes;
88+
const attrs = node.attributes.properties;
8989
if (attrs.length === 0) {
9090
// When there are no attributes, React wants "null"
9191
objectProperties = createNull();

src/compiler/types.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330
JsxOpeningElement,
331331
JsxClosingElement,
332332
JsxAttribute,
333+
JsxAttributes,
333334
JsxSpreadAttribute,
334335
JsxExpression,
335336

@@ -727,6 +728,7 @@
727728
// SyntaxKind.BindingElement
728729
// SyntaxKind.Property
729730
// SyntaxKind.PropertyAssignment
731+
// SyntaxKind.JsxAttribute
730732
// SyntaxKind.ShorthandPropertyAssignment
731733
// SyntaxKind.EnumMember
732734
// SyntaxKind.JSDocPropertyTag
@@ -1445,7 +1447,7 @@
14451447
template: TemplateLiteral;
14461448
}
14471449

1448-
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator;
1450+
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement;
14491451

14501452
export interface AsExpression extends Expression {
14511453
kind: SyntaxKind.AsExpression;
@@ -1482,35 +1484,38 @@
14821484
closingElement: JsxClosingElement;
14831485
}
14841486

1487+
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
1488+
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
1489+
1490+
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
1491+
14851492
export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression;
14861493

1494+
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
1495+
}
1496+
14871497
/// The opening element of a <Tag>...</Tag> JsxElement
14881498
export interface JsxOpeningElement extends Expression {
14891499
kind: SyntaxKind.JsxOpeningElement;
14901500
tagName: JsxTagNameExpression;
1491-
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
1501+
attributes: JsxAttributes;
14921502
}
14931503

14941504
/// A JSX expression of the form <TagName attrs />
14951505
export interface JsxSelfClosingElement extends PrimaryExpression {
14961506
kind: SyntaxKind.JsxSelfClosingElement;
14971507
tagName: JsxTagNameExpression;
1498-
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
1508+
attributes: JsxAttributes;
14991509
}
15001510

1501-
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
1502-
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
1503-
1504-
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
1505-
1506-
export interface JsxAttribute extends Node {
1511+
export interface JsxAttribute extends ObjectLiteralElement {
15071512
kind: SyntaxKind.JsxAttribute;
15081513
name: Identifier;
15091514
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
15101515
initializer?: StringLiteral | JsxExpression;
15111516
}
15121517

1513-
export interface JsxSpreadAttribute extends Node {
1518+
export interface JsxSpreadAttribute extends ObjectLiteralElement {
15141519
kind: SyntaxKind.JsxSpreadAttribute;
15151520
expression: Expression;
15161521
}
@@ -2421,7 +2426,7 @@
24212426
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
24222427
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
24232428

2424-
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
2429+
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type;
24252430
getJsxIntrinsicTagNames(): Symbol[];
24262431
isOptionalParameter(node: ParameterDeclaration): boolean;
24272432
getAmbientModules(): Symbol[];
@@ -2814,7 +2819,7 @@
28142819
isVisible?: boolean; // Is this node visible
28152820
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
28162821
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
2817-
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
2822+
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
28182823
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
28192824
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
28202825
switchTypes?: Type[]; // Cached array of switch case expression types
@@ -2850,6 +2855,8 @@
28502855
/* @internal */
28512856
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
28522857
NonPrimitive = 1 << 24, // intrinsic object type
2858+
/* @internal */
2859+
JsxAttributes = 1 << 25, // Jsx attributes type
28532860

28542861
/* @internal */
28552862
Nullable = Undefined | Null,
@@ -3039,7 +3046,7 @@
30393046

30403047
/* @internal */
30413048
// Object literals are initially marked fresh. Freshness disappears following an assignment,
3042-
// before a type assertion, or when when an object literal's type is widened. The regular
3049+
// before a type assertion, or when an object literal's type is widened. The regular
30433050
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
30443051
export interface FreshObjectLiteralType extends ResolvedType {
30453052
regularType: ResolvedType; // Regular version of fresh type

src/compiler/utilities.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,8 @@ namespace ts {
11781178

11791179
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
11801180
switch (node.kind) {
1181+
case SyntaxKind.JsxOpeningElement:
1182+
case SyntaxKind.JsxSelfClosingElement:
11811183
case SyntaxKind.CallExpression:
11821184
case SyntaxKind.NewExpression:
11831185
case SyntaxKind.TaggedTemplateExpression:
@@ -1192,6 +1194,9 @@ namespace ts {
11921194
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
11931195
return (<TaggedTemplateExpression>node).tag;
11941196
}
1197+
else if (isJsxOpeningLikeElement(node)) {
1198+
return node.tagName;
1199+
}
11951200

11961201
// Will either be a CallExpression, NewExpression, or Decorator.
11971202
return (<CallExpression | Decorator>node).expression;
@@ -3963,6 +3968,7 @@ namespace ts {
39633968
|| kind === SyntaxKind.ImportEqualsDeclaration
39643969
|| kind === SyntaxKind.ImportSpecifier
39653970
|| kind === SyntaxKind.InterfaceDeclaration
3971+
|| kind === SyntaxKind.JsxAttribute
39663972
|| kind === SyntaxKind.MethodDeclaration
39673973
|| kind === SyntaxKind.MethodSignature
39683974
|| kind === SyntaxKind.ModuleDeclaration
@@ -4075,6 +4081,11 @@ namespace ts {
40754081
|| kind === SyntaxKind.JsxText;
40764082
}
40774083

4084+
export function isJsxAttributes(node: Node): node is JsxAttributes {
4085+
const kind = node.kind;
4086+
return kind === SyntaxKind.JsxAttributes;
4087+
}
4088+
40784089
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
40794090
const kind = node.kind;
40804091
return kind === SyntaxKind.JsxAttribute
@@ -4089,6 +4100,10 @@ namespace ts {
40894100
return node.kind === SyntaxKind.JsxAttribute;
40904101
}
40914102

4103+
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
4104+
return node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement;
4105+
}
4106+
40924107
export function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression {
40934108
const kind = node.kind;
40944109
return kind === SyntaxKind.StringLiteral

src/compiler/visitor.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,17 @@ namespace ts {
426426
case SyntaxKind.JsxSelfClosingElement:
427427
case SyntaxKind.JsxOpeningElement:
428428
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
429-
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNodes, result);
429+
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNode, result);
430430
break;
431431

432432
case SyntaxKind.JsxClosingElement:
433433
result = reduceNode((<JsxClosingElement>node).tagName, cbNode, result);
434434
break;
435435

436+
case SyntaxKind.JsxAttributes:
437+
result = reduceNodes((<JsxAttributes>node).properties, cbNodes, result);
438+
break;
439+
436440
case SyntaxKind.JsxAttribute:
437441
result = reduceNode((<JsxAttribute>node).name, cbNode, result);
438442
result = reduceNode((<JsxAttribute>node).initializer, cbNode, result);
@@ -1108,15 +1112,19 @@ namespace ts {
11081112
visitNodes((<JsxElement>node).children, visitor, isJsxChild),
11091113
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
11101114

1115+
case SyntaxKind.JsxAttributes:
1116+
return updateJsxAttributes(<JsxAttributes>node,
1117+
visitNodes((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
1118+
11111119
case SyntaxKind.JsxSelfClosingElement:
11121120
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
11131121
visitNode((<JsxSelfClosingElement>node).tagName, visitor, isJsxTagNameExpression),
1114-
visitNodes((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributeLike));
1122+
visitNode((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributes));
11151123

11161124
case SyntaxKind.JsxOpeningElement:
11171125
return updateJsxOpeningElement(<JsxOpeningElement>node,
11181126
visitNode((<JsxOpeningElement>node).tagName, visitor, isJsxTagNameExpression),
1119-
visitNodes((<JsxOpeningElement>node).attributes, visitor, isJsxAttributeLike));
1127+
visitNode((<JsxOpeningElement>node).attributes, visitor, isJsxAttributes));
11201128

11211129
case SyntaxKind.JsxClosingElement:
11221130
return updateJsxClosingElement(<JsxClosingElement>node,

0 commit comments

Comments
 (0)