mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Parse, bind and check rest elements
This commit is contained in:
+61
-11
@@ -1916,6 +1916,9 @@ namespace ts {
|
||||
return bindParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
if ((node as BindingElement).dotDotDotToken && node.parent.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
emitFlags |= NodeFlags.HasRestAttribute;
|
||||
}
|
||||
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
@@ -1931,7 +1934,11 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
emitFlags |= NodeFlags.HasSpreadAttribute;
|
||||
let root = container;
|
||||
while (root && root.kind !== SyntaxKind.BinaryExpression) {
|
||||
root = root.parent;
|
||||
}
|
||||
emitFlags |= root && isDestructuringAssignment(root) ? NodeFlags.HasRestAttribute : NodeFlags.HasSpreadAttribute;
|
||||
return;
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
@@ -2542,10 +2549,13 @@ namespace ts {
|
||||
const operatorTokenKind = node.operatorToken.kind;
|
||||
const leftKind = node.left.kind;
|
||||
|
||||
if (operatorTokenKind === SyntaxKind.EqualsToken
|
||||
&& (leftKind === SyntaxKind.ObjectLiteralExpression
|
||||
|| leftKind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
// Destructuring assignments are ES6 syntax.
|
||||
if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// Destructuring object assignments with are ES2015 syntax
|
||||
// and possibly ESNext if they contain rest
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ArrayLiteralExpression) {
|
||||
// Destructuring assignments are ES2015 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken
|
||||
@@ -2579,6 +2589,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
|
||||
}
|
||||
|
||||
// parameters with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
|
||||
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
|
||||
if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) {
|
||||
@@ -2812,6 +2827,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a FunctionDeclaration's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
@@ -2849,6 +2869,12 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function expressions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
|
||||
// If a FunctionExpression's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
@@ -2886,6 +2912,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// arrow functions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
|
||||
@@ -2914,8 +2945,13 @@ namespace ts {
|
||||
let transformFlags = subtreeFlags;
|
||||
const nameKind = node.name.kind;
|
||||
|
||||
// A VariableDeclaration with a binding pattern is ES6 syntax.
|
||||
if (nameKind === SyntaxKind.ObjectBindingPattern || nameKind === SyntaxKind.ArrayBindingPattern) {
|
||||
// A VariableDeclaration with an object binding pattern is ES2015 syntax
|
||||
// and possibly ESNext syntax if it contains an object binding pattern
|
||||
if (nameKind === SyntaxKind.ObjectBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
// A VariableDeclaration with an object binding pattern is ES2015 syntax.
|
||||
else if (nameKind === SyntaxKind.ArrayBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
|
||||
@@ -3056,6 +3092,10 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// for-of might be ESNext if it has a rest destructuring
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
// FALLTHROUGH
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
@@ -3063,7 +3103,6 @@ namespace ts {
|
||||
case SyntaxKind.TemplateExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.StaticKeyword:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@@ -3129,10 +3168,16 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.SpreadExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
// This node is ES6 or ES future syntax, but is handled by a containing node.
|
||||
// This node is ES2015 or ES next syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadExpression;
|
||||
break;
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
if ((node as BindingElement).dotDotDotToken) {
|
||||
// this node is ES2015 or ES next syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadExpression;
|
||||
}
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@@ -3145,8 +3190,13 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
// These nodes are ES2015 or ES Next syntax.
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
else {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
|
||||
+59
-39
@@ -2245,7 +2245,7 @@ namespace ts {
|
||||
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Spread) {
|
||||
writeSpreadType(<SpreadType>type);
|
||||
writeSpreadType(type as SpreadType);
|
||||
}
|
||||
else if (getObjectFlags(type) & ObjectFlags.Anonymous) {
|
||||
writeAnonymousType(<ObjectType>type, nextFlags);
|
||||
@@ -3028,26 +3028,31 @@ namespace ts {
|
||||
return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false);
|
||||
}
|
||||
|
||||
function getTextOfPropertyName(name: PropertyName): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return (<Identifier>name).text;
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return (<LiteralExpression>name).text;
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
|
||||
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isComputedNonLiteralName(name: PropertyName): boolean {
|
||||
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind);
|
||||
}
|
||||
|
||||
function getRestType(source: Type, properties: PropertyName[], symbol: Symbol): Type {
|
||||
Debug.assert(!!(source.flags & TypeFlags.Object), "Rest types only support object types right now.");
|
||||
const members = createMap<Symbol>();
|
||||
const names = createMap<true>();
|
||||
for (const name of properties) {
|
||||
names[getTextOfPropertyName(name)] = true;
|
||||
}
|
||||
for (const prop of getPropertiesOfType(source)) {
|
||||
const inNamesToRemove = prop.name in names;
|
||||
const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected);
|
||||
const isMethod = prop.flags & SymbolFlags.Method;
|
||||
const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
|
||||
if (!inNamesToRemove && !isPrivate && !isMethod && !isSetOnlyAccessor) {
|
||||
members[prop.name] = prop;
|
||||
}
|
||||
}
|
||||
const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number);
|
||||
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
}
|
||||
|
||||
/** Return the inferred type for a binding element */
|
||||
function getTypeForBindingElement(declaration: BindingElement): Type {
|
||||
const pattern = <BindingPattern>declaration.parent;
|
||||
@@ -3068,26 +3073,41 @@ namespace ts {
|
||||
|
||||
let type: Type;
|
||||
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
|
||||
const name = declaration.propertyName || <Identifier>declaration.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// computed properties with non-literal names are treated as 'any'
|
||||
return anyType;
|
||||
}
|
||||
if (declaration.initializer) {
|
||||
getContextualType(declaration.initializer);
|
||||
if (declaration.dotDotDotToken) {
|
||||
if (!(parentType.flags & TypeFlags.Object)) {
|
||||
error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
|
||||
return unknownType;
|
||||
}
|
||||
const literalMembers: PropertyName[] = [];
|
||||
for (const element of pattern.elements) {
|
||||
if (element.kind !== SyntaxKind.OmittedExpression && !(element as BindingElement).dotDotDotToken) {
|
||||
literalMembers.push(element.propertyName || element.name as Identifier);
|
||||
}
|
||||
}
|
||||
type = getRestType(parentType, literalMembers, declaration.symbol);
|
||||
}
|
||||
else {
|
||||
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
|
||||
const name = declaration.propertyName || <Identifier>declaration.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// computed properties with non-literal names are treated as 'any'
|
||||
return anyType;
|
||||
}
|
||||
if (declaration.initializer) {
|
||||
getContextualType(declaration.initializer);
|
||||
}
|
||||
|
||||
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
|
||||
// or otherwise the type of the string index signature.
|
||||
const text = getTextOfPropertyName(name);
|
||||
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
|
||||
// or otherwise the type of the string index signature.
|
||||
const text = getTextOfPropertyName(name);
|
||||
|
||||
type = getTypeOfPropertyOfType(parentType, text) ||
|
||||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(parentType, IndexKind.String);
|
||||
if (!type) {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
|
||||
return unknownType;
|
||||
type = getTypeOfPropertyOfType(parentType, text) ||
|
||||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(parentType, IndexKind.String);
|
||||
if (!type) {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -3295,8 +3315,8 @@ namespace ts {
|
||||
let hasComputedProperties = false;
|
||||
forEach(pattern.elements, e => {
|
||||
const name = e.propertyName || <Identifier>e.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// do not include computed properties in the implied type
|
||||
if (isComputedNonLiteralName(name) || e.dotDotDotToken) {
|
||||
// do not include computed properties or rests in the implied type
|
||||
hasComputedProperties = true;
|
||||
return;
|
||||
}
|
||||
@@ -14097,7 +14117,7 @@ namespace ts {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (property.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
error(property, Diagnostics.Property_assignment_expected);
|
||||
}
|
||||
}
|
||||
@@ -14143,7 +14163,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
if (elementIndex < elements.length - 1) {
|
||||
error(element, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
|
||||
}
|
||||
else {
|
||||
const restExpression = (<SpreadExpression>element).expression;
|
||||
@@ -21058,7 +21078,7 @@ namespace ts {
|
||||
if (node.dotDotDotToken) {
|
||||
const elements = (<BindingPattern>node.parent).elements;
|
||||
if (node !== lastOrUndefined(elements)) {
|
||||
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
|
||||
}
|
||||
|
||||
if (node.name.kind === SyntaxKind.ArrayBindingPattern || node.name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
|
||||
@@ -1455,7 +1455,7 @@
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
"A rest element must be last in an array destructuring pattern": {
|
||||
"A rest element must be last in a destructuring pattern": {
|
||||
"category": "Error",
|
||||
"code": 2462
|
||||
},
|
||||
@@ -1991,6 +1991,10 @@
|
||||
"category": "Error",
|
||||
"code": 2699
|
||||
},
|
||||
"Rest types may only be created from object types.": {
|
||||
"category": "Error",
|
||||
"code": 2700
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
+10
-1
@@ -1274,8 +1274,10 @@ namespace ts {
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.RestProperties:
|
||||
return isLiteralPropertyName();
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
// If we see { } then only consume it as an expression if it is followed by , or {
|
||||
// That way we won't consume the body of a class in its heritage clause.
|
||||
@@ -1402,6 +1404,7 @@ namespace ts {
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
return token() === SyntaxKind.CloseBracketToken;
|
||||
case ParsingContext.Parameters:
|
||||
case ParsingContext.RestProperties:
|
||||
// Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
|
||||
return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
|
||||
case ParsingContext.TypeArguments:
|
||||
@@ -1587,6 +1590,9 @@ namespace ts {
|
||||
case ParsingContext.Parameters:
|
||||
return isReusableParameter(node);
|
||||
|
||||
case ParsingContext.RestProperties:
|
||||
return false;
|
||||
|
||||
// Any other lists we do not care about reusing nodes in. But feel free to add if
|
||||
// you can do so safely. Danger areas involve nodes that may involve speculative
|
||||
// parsing. If speculative parsing is involved with the node, then the range the
|
||||
@@ -1784,6 +1790,7 @@ namespace ts {
|
||||
case ParsingContext.BlockStatements: return Diagnostics.Declaration_or_statement_expected;
|
||||
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
|
||||
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
|
||||
case ParsingContext.RestProperties: // fallthrough
|
||||
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
|
||||
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
|
||||
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
|
||||
@@ -4890,6 +4897,7 @@ namespace ts {
|
||||
|
||||
function parseObjectBindingElement(): BindingElement {
|
||||
const node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
const tokenIsIdentifier = isIdentifier();
|
||||
const propertyName = parsePropertyName();
|
||||
if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
|
||||
@@ -5834,6 +5842,7 @@ namespace ts {
|
||||
JsxChildren, // Things between opening and closing JSX tags
|
||||
ArrayLiteralMembers, // Members in array literal
|
||||
Parameters, // Parameters in parameter list
|
||||
RestProperties, // Property names in a rest type list
|
||||
TypeParameters, // Type parameters in type parameter list
|
||||
TypeArguments, // Type arguments in type argument list
|
||||
TupleElementTypes, // Element types in tuple element type list
|
||||
|
||||
+10
-9
@@ -422,14 +422,15 @@ namespace ts {
|
||||
HasParamDecorators = 1 << 12, // If the file has parameter decorators (initialized by binding)
|
||||
HasAsyncFunctions = 1 << 13, // If the file has async functions (initialized by binding)
|
||||
HasSpreadAttribute = 1 << 14, // If the file as JSX spread attributes (initialized by binding)
|
||||
DisallowInContext = 1 << 15, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 16, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 17, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 18, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 19, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 20, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 21, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
|
||||
HasRestAttribute = 1 << 15, // If the file has object destructure elements
|
||||
DisallowInContext = 1 << 16, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 17, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 18, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 19, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 20, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 21, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 22, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 23, // If we've computed data from children and cached it in this node
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@@ -651,7 +652,7 @@ namespace ts {
|
||||
export interface BindingElement extends Declaration {
|
||||
kind: SyntaxKind.BindingElement;
|
||||
propertyName?: PropertyName; // Binding property name (in object binding pattern)
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest binding element
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern)
|
||||
name: BindingName; // Declared binding element name
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
@@ -485,6 +485,22 @@ namespace ts {
|
||||
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
||||
}
|
||||
|
||||
export function getTextOfPropertyName(name: PropertyName): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return (<Identifier>name).text;
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return (<LiteralExpression>name).text;
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
|
||||
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function entityNameToString(name: EntityNameOrEntityNameExpression): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
|
||||
Reference in New Issue
Block a user