mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Parse JSX attributes as its own unique AST node and bind the node
This commit is contained in:
@@ -1331,6 +1331,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return ContainerFlags.IsContainer;
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
@@ -1437,6 +1438,7 @@ namespace ts {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
// Interface/Object-types always have their children added to the 'members' of
|
||||
// their container. They are only accessible through an instance of their
|
||||
// container, and are never in scope otherwise (even inside the body of the
|
||||
@@ -1621,6 +1623,14 @@ namespace ts {
|
||||
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
|
||||
}
|
||||
|
||||
function bindJsxAttributes(node: JsxAttributes) {
|
||||
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes");
|
||||
}
|
||||
|
||||
function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
|
||||
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
|
||||
const symbol = createSymbol(symbolFlags, name);
|
||||
addDeclarationToSymbol(symbol, node, symbolFlags);
|
||||
@@ -2042,6 +2052,12 @@ namespace ts {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return bindModuleDeclaration(<ModuleDeclaration>node);
|
||||
|
||||
// Jsx-attributes
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return bindJsxAttributes(<JsxAttributes>node);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return bindJsxAttribute(<JsxAttribute>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
|
||||
// Imports and exports
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
@@ -3118,6 +3134,7 @@ namespace ts {
|
||||
case SyntaxKind.JsxText:
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
case SyntaxKind.JsxExpression:
|
||||
// These nodes are Jsx syntax.
|
||||
|
||||
+10
-2
@@ -368,7 +368,9 @@ namespace ts {
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
|
||||
visitNodes(cbNodes, (<JsxOpeningLikeElement>node).attributes);
|
||||
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return visitNodes(cbNodes, (<JsxAttributes>node).properties);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return visitNode(cbNode, (<JsxAttribute>node).name) ||
|
||||
visitNode(cbNode, (<JsxAttribute>node).initializer);
|
||||
@@ -3865,14 +3867,20 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseJsxAttributes(): JsxAttributes {
|
||||
const jsxAttributes = <JsxAttributes>createNode(SyntaxKind.JsxAttributes);
|
||||
jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
|
||||
return finishNode(jsxAttributes);
|
||||
}
|
||||
|
||||
function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement {
|
||||
const fullStart = scanner.getStartPos();
|
||||
|
||||
parseExpected(SyntaxKind.LessThanToken);
|
||||
|
||||
const tagName = parseJsxElementName();
|
||||
const attributes = parseJsxAttributes();
|
||||
|
||||
const attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
|
||||
let node: JsxOpeningLikeElement;
|
||||
|
||||
if (token() === SyntaxKind.GreaterThanToken) {
|
||||
|
||||
+23
-14
@@ -330,6 +330,7 @@
|
||||
JsxOpeningElement,
|
||||
JsxClosingElement,
|
||||
JsxAttribute,
|
||||
JsxAttributes,
|
||||
JsxSpreadAttribute,
|
||||
JsxExpression,
|
||||
|
||||
@@ -725,6 +726,7 @@
|
||||
// SyntaxKind.BindingElement
|
||||
// SyntaxKind.Property
|
||||
// SyntaxKind.PropertyAssignment
|
||||
// SyntaxKind.JsxAttribute
|
||||
// SyntaxKind.ShorthandPropertyAssignment
|
||||
// SyntaxKind.EnumMember
|
||||
// SyntaxKind.JSDocPropertyTag
|
||||
@@ -1444,7 +1446,7 @@
|
||||
template: TemplateLiteral;
|
||||
}
|
||||
|
||||
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator;
|
||||
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement;
|
||||
|
||||
export interface AsExpression extends Expression {
|
||||
kind: SyntaxKind.AsExpression;
|
||||
@@ -1481,35 +1483,39 @@
|
||||
closingElement: JsxClosingElement;
|
||||
}
|
||||
|
||||
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
|
||||
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
|
||||
|
||||
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
|
||||
|
||||
export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression;
|
||||
|
||||
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
|
||||
}
|
||||
|
||||
/// The opening element of a <Tag>...</Tag> JsxElement
|
||||
export interface JsxOpeningElement extends Expression {
|
||||
kind: SyntaxKind.JsxOpeningElement;
|
||||
tagName: JsxTagNameExpression;
|
||||
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
|
||||
attributes: JsxAttributes;
|
||||
}
|
||||
|
||||
/// A JSX expression of the form <TagName attrs />
|
||||
export interface JsxSelfClosingElement extends PrimaryExpression {
|
||||
kind: SyntaxKind.JsxSelfClosingElement;
|
||||
tagName: JsxTagNameExpression;
|
||||
attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>;
|
||||
attributes: JsxAttributes;
|
||||
}
|
||||
|
||||
/// Either the opening tag in a <Tag>...</Tag> pair, or the lone <Tag /> in a self-closing form
|
||||
export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
|
||||
|
||||
export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute;
|
||||
|
||||
export interface JsxAttribute extends Node {
|
||||
kind: SyntaxKind.JsxAttribute;
|
||||
// @kind(SyntaxKind.JsxAttribute)
|
||||
export interface JsxAttribute extends ObjectLiteralElement {
|
||||
name: Identifier;
|
||||
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
|
||||
initializer?: StringLiteral | JsxExpression;
|
||||
}
|
||||
|
||||
export interface JsxSpreadAttribute extends Node {
|
||||
// @kind(SyntaxKind.JsxSpreadAttribute)
|
||||
export interface JsxSpreadAttribute extends ObjectLiteralElement {
|
||||
kind: SyntaxKind.JsxSpreadAttribute;
|
||||
expression: Expression;
|
||||
}
|
||||
@@ -2397,7 +2403,7 @@
|
||||
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
|
||||
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
|
||||
|
||||
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
|
||||
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type;
|
||||
getJsxIntrinsicTagNames(): Symbol[];
|
||||
isOptionalParameter(node: ParameterDeclaration): boolean;
|
||||
getAmbientModules(): Symbol[];
|
||||
@@ -2697,6 +2703,7 @@
|
||||
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
|
||||
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
|
||||
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
|
||||
/* @internal */ syntheticKind?: SyntheticSymbolKind; // Synthetic symbols are either spread or union/intersection
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2778,7 +2785,7 @@
|
||||
isVisible?: boolean; // Is this node visible
|
||||
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
|
||||
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
|
||||
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
|
||||
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
|
||||
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.
|
||||
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
switchTypes?: Type[]; // Cached array of switch case expression types
|
||||
@@ -2814,6 +2821,8 @@
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
|
||||
NonPrimitive = 1 << 24, // intrinsic object type
|
||||
/* @internal */
|
||||
JsxAttributes = 1 << 25, // Jsx attributes type
|
||||
|
||||
/* @internal */
|
||||
Nullable = Undefined | Null,
|
||||
@@ -2995,7 +3004,7 @@
|
||||
|
||||
/* @internal */
|
||||
// Object literals are initially marked fresh. Freshness disappears following an assignment,
|
||||
// before a type assertion, or when when an object literal's type is widened. The regular
|
||||
// before a type assertion, or when an object literal's type is widened. The regular
|
||||
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
|
||||
export interface FreshObjectLiteralType extends ResolvedType {
|
||||
regularType: ResolvedType; // Regular version of fresh type
|
||||
|
||||
@@ -1133,6 +1133,8 @@ namespace ts {
|
||||
|
||||
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
@@ -1147,6 +1149,9 @@ namespace ts {
|
||||
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
return (<TaggedTemplateExpression>node).tag;
|
||||
}
|
||||
else if (isJsxOpeningLikeElement(node)) {
|
||||
return node.tagName;
|
||||
}
|
||||
|
||||
// Will either be a CallExpression, NewExpression, or Decorator.
|
||||
return (<CallExpression | Decorator>node).expression;
|
||||
@@ -4048,6 +4053,7 @@ namespace ts {
|
||||
|| kind === SyntaxKind.ImportEqualsDeclaration
|
||||
|| kind === SyntaxKind.ImportSpecifier
|
||||
|| kind === SyntaxKind.InterfaceDeclaration
|
||||
|| kind === SyntaxKind.JsxAttribute
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.MethodSignature
|
||||
|| kind === SyntaxKind.ModuleDeclaration
|
||||
@@ -4160,6 +4166,11 @@ namespace ts {
|
||||
|| kind === SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
export function isJsxAttributes(node: Node): node is JsxAttributes {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxAttributes;
|
||||
}
|
||||
|
||||
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxAttribute
|
||||
@@ -4174,6 +4185,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.JsxAttribute;
|
||||
}
|
||||
|
||||
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
|
||||
return node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement;
|
||||
}
|
||||
|
||||
export function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.StringLiteral
|
||||
|
||||
Reference in New Issue
Block a user