Remove 'missing' syntax kind.

This commit is contained in:
Cyrus Najmabadi 2014-12-01 16:17:04 -08:00
parent af7b8d624f
commit d730e5ca55
11 changed files with 91 additions and 68 deletions

View File

@ -338,7 +338,6 @@ module ts {
// the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
// the given name can be found.
function resolveName(location: Node, name: string, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, nameArg: string | Identifier): Symbol {
var result: Symbol;
var lastLocation: Node;
var propertyWithInvalidInitializer: Node;
@ -516,26 +515,27 @@ module ts {
// Resolves a qualified name and any involved import aliases
function resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol {
if (getFullWidth(name) === 0) {
return undefined;
}
if (name.kind === SyntaxKind.Identifier) {
var symbol = resolveName(location, (<Identifier>name).text, meaning, Diagnostics.Cannot_find_name_0, <Identifier>name);
var symbol = resolveName(location,(<Identifier>name).text, meaning, Diagnostics.Cannot_find_name_0, <Identifier>name);
if (!symbol) {
return;
}
}
else if (name.kind === SyntaxKind.QualifiedName) {
var namespace = resolveEntityName(location, (<QualifiedName>name).left, SymbolFlags.Namespace);
if (!namespace || namespace === unknownSymbol || (<QualifiedName>name).right.kind === SyntaxKind.Missing) return;
var symbol = getSymbol(namespace.exports, (<QualifiedName>name).right.text, meaning);
var namespace = resolveEntityName(location,(<QualifiedName>name).left, SymbolFlags.Namespace);
if (!namespace || namespace === unknownSymbol || getFullWidth((<QualifiedName>name).right) === 0) return;
var symbol = getSymbol(namespace.exports,(<QualifiedName>name).right.text, meaning);
if (!symbol) {
error(location, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace),
declarationNameToString((<QualifiedName>name).right));
return;
}
}
else {
// Missing identifier
return;
}
Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
return symbol.flags & meaning ? symbol : resolveImport(symbol);
}
@ -4256,7 +4256,7 @@ module ts {
function getResolvedSymbol(node: Identifier): Symbol {
var links = getNodeLinks(node);
if (!links.resolvedSymbol) {
links.resolvedSymbol = resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node) || unknownSymbol;
links.resolvedSymbol = (getFullWidth(node) > 0 && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node)) || unknownSymbol;
}
return links.resolvedSymbol;
}
@ -5344,7 +5344,7 @@ module ts {
var templateExpression = <TemplateExpression>tagExpression.template;
var lastSpan = lastOrUndefined(templateExpression.templateSpans);
Debug.assert(lastSpan !== undefined); // we should always have at least one span.
callIsIncomplete = lastSpan.literal.kind === SyntaxKind.Missing || isUnterminatedTemplateEnd(lastSpan.literal);
callIsIncomplete = getFullWidth(lastSpan.literal) === 0 || isUnterminatedTemplateEnd(lastSpan.literal);
}
else {
// If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
@ -7051,7 +7051,7 @@ module ts {
var isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0;
function reportImplementationExpectedError(node: FunctionLikeDeclaration): void {
if (node.name && node.name.kind === SyntaxKind.Missing) {
if (node.name && getFullWidth(node.name) === 0) {
return;
}
@ -8889,6 +8889,11 @@ module ts {
}
if (isExpression(entityName)) {
if (getFullWidth(entityName) === 0) {
// Missing entity name.
return undefined;
}
if (entityName.kind === SyntaxKind.Identifier) {
// Include Import in the meaning, this ensures that we do not follow aliases to where they point and instead
// return the alias symbol.
@ -8909,10 +8914,6 @@ module ts {
}
return getNodeLinks(entityName).resolvedSymbol;
}
else {
// Missing identifier
return;
}
}
else if (isTypeReferenceIdentifier(<EntityName>entityName)) {
var meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;

View File

@ -5,6 +5,10 @@
module ts {
var nodeConstructors = new Array<new () => Node>(SyntaxKind.Count);
export function getFullWidth(node: Node) {
return node.end - node.pos;
}
export function getNodeConstructor(kind: SyntaxKind): new () => Node {
return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
}
@ -75,13 +79,14 @@ module ts {
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
// text of the expression in the computed property.
export function declarationNameToString(name: DeclarationName) {
return name.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(name);
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = node.kind === SyntaxKind.Missing ? node.pos : skipTrivia(file.text, node.pos);
var start = getFullWidth(node) === 0 ? node.pos : skipTrivia(file.text, node.pos);
var length = node.end - start;
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
@ -1200,14 +1205,14 @@ module ts {
return inStrictModeContext() ? token > SyntaxKind.LastFutureReservedWord : token > SyntaxKind.LastReservedWord;
}
function parseExpected(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean {
function parseExpected(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): boolean {
if (token === t) {
nextToken();
return true;
}
if (diagnosticMessage) {
error(diagnosticMessage);
error(diagnosticMessage, arg0);
}
else {
error(Diagnostics._0_expected, tokenToString(t));
@ -1276,8 +1281,24 @@ module ts {
return node;
}
function createMissingNode(pos?: number): Node {
return createNode(SyntaxKind.Missing, pos);
function createMissingNode(kind: SyntaxKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Node {
if (diagnosticMessage) {
if (reportAtCurrentPosition) {
errorAtPos(scanner.getStartPos(), 0, diagnosticMessage, arg0);
}
else {
var start = scanner.getTokenPos();
errorAtPos(start, scanner.getTextPos() - start, diagnosticMessage, arg0);
}
}
return createMissingNodeWithoutError(kind);
}
function createMissingNodeWithoutError(kind: SyntaxKind) {
var result = createNode(kind, scanner.getStartPos());
(<Identifier>result).text = "";
return finishNode(result);
}
function internIdentifier(text: string): string {
@ -1297,14 +1318,7 @@ module ts {
return finishNode(node);
}
error(diagnosticMessage || Diagnostics.Identifier_expected);
return createMissingIdentifier();
}
function createMissingIdentifier() {
var node = <Identifier>createMissingNode();
node.text = "";
return node;
return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition:*/ false, diagnosticMessage || Diagnostics.Identifier_expected);
}
function parseIdentifier(diagnosticMessage?: DiagnosticMessage): Identifier {
@ -1660,8 +1674,10 @@ module ts {
});
if (matchesPattern) {
errorAtPos(scanner.getTokenPos(), 0, Diagnostics.Identifier_expected);
return <Identifier>createMissingNode();
// Report that we need an identifier. However, report it right after the dot,
// and not on the next token. This is because the next token might actually
// be an identifier and the error woudl be quite confusing.
return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken:*/ true, Diagnostics.Identifier_expected);
}
}
@ -1705,8 +1721,8 @@ module ts {
literal = parseLiteralNode();
}
else {
parseExpected(SyntaxKind.CloseBraceToken);
literal = createMissingIdentifier();
literal = <LiteralExpression>createMissingNode(
SyntaxKind.TemplateTail, /*reportAtCurrentPosition:*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken));
}
span.literal = literal;
@ -1821,7 +1837,7 @@ module ts {
? doInYieldContext(parseIdentifier)
: parseIdentifier();
if (node.name.kind === SyntaxKind.Missing && node.flags === 0 && isModifier(token)) {
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
// in cases like
// 'use strict'
// function foo(static)
@ -3009,7 +3025,9 @@ module ts {
// don't want to rollback just because we were missing a type arg. The grammar checker
// will report the actual error later on.
if (token === SyntaxKind.CommaToken) {
return createNode(SyntaxKind.Missing);
var result = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
result.typeName = <Identifier>createMissingNodeWithoutError(SyntaxKind.Identifier);
return finishNode(result);
}
return parseType();
@ -4202,7 +4220,6 @@ module ts {
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.Identifier:
case SyntaxKind.Missing:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
@ -4533,7 +4550,7 @@ module ts {
if (typeArguments) {
for (var i = 0, n = typeArguments.length; i < n; i++) {
var arg = typeArguments[i];
if (arg.kind === SyntaxKind.Missing) {
if (arg.kind === SyntaxKind.TypeReference && getFullWidth((<TypeReferenceNode>arg).typeName) === 0) {
return grammarErrorAtPos(arg.pos, 0, Diagnostics.Type_expected);
}
}

View File

@ -137,8 +137,9 @@ module ts {
SetKeyword,
StringKeyword,
TypeKeyword,
// Parse tree nodes
Missing,
// Names
QualifiedName,
ComputedPropertyName,
@ -235,6 +236,7 @@ module ts {
// Top-level nodes
SourceFile,
Program,
// Synthesized list
SyntaxList,
// Enum value count
@ -263,7 +265,8 @@ module ts {
FirstOperator = SemicolonToken,
LastOperator = CaretEqualsToken,
FirstBinaryOperator = LessThanToken,
LastBinaryOperator = CaretEqualsToken
LastBinaryOperator = CaretEqualsToken,
FirstNode = QualifiedName,
}
export const enum NodeFlags {

View File

@ -483,8 +483,8 @@ module ts.formatting {
if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
return inheritedIndentation;
}
if (child.kind === SyntaxKind.Missing) {
if (child.getFullWidth() === 0) {
return inheritedIndentation;
}

View File

@ -218,7 +218,7 @@ module ts {
}
private createChildren(sourceFile?: SourceFile) {
if (this.kind > SyntaxKind.Missing) {
if (this.kind >= SyntaxKind.FirstNode) {
scanner.setText((sourceFile || this.getSourceFile()).text);
var children: Node[] = [];
var pos = this.pos;
@ -264,8 +264,11 @@ module ts {
var children = this.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.kind < SyntaxKind.Missing) return child;
if (child.kind > SyntaxKind.Missing) return child.getFirstToken(sourceFile);
if (child.kind < SyntaxKind.FirstNode) {
return child;
}
return child.getFirstToken(sourceFile);
}
}
@ -273,8 +276,11 @@ module ts {
var children = this.getChildren(sourceFile);
for (var i = children.length - 1; i >= 0; i--) {
var child = children[i];
if (child.kind < SyntaxKind.Missing) return child;
if (child.kind > SyntaxKind.Missing) return child.getLastToken(sourceFile);
if (child.kind < SyntaxKind.FirstNode) {
return child;
}
return child.getLastToken(sourceFile);
}
}
}
@ -758,7 +764,7 @@ module ts {
case SyntaxKind.Method:
var functionDeclaration = <FunctionLikeDeclaration>node;
if (functionDeclaration.name && functionDeclaration.name.kind !== SyntaxKind.Missing) {
if (functionDeclaration.name && functionDeclaration.name.getFullWidth() > 0) {
var lastDeclaration = namedDeclarations.length > 0 ?
namedDeclarations[namedDeclarations.length - 1] :
undefined;
@ -2888,7 +2894,7 @@ module ts {
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
var right = (<PropertyAccessExpression>location.parent).name;
// Either the location is on the right of a property access, or on the left and the right is missing
if (right === location || (right && right.kind === SyntaxKind.Missing)){
if (right === location || (right && right.getFullWidth() === 0)){
location = location.parent;
}
}

View File

@ -386,7 +386,7 @@ module ts.SignatureHelp {
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
if (template.kind === SyntaxKind.TemplateExpression) {
var lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
if (lastSpan.literal.kind === SyntaxKind.Missing) {
if (lastSpan.literal.getFullWidth() === 0) {
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
}
}

View File

@ -393,6 +393,10 @@ module ts.formatting {
* This function is always called when position of the cursor is located after the node
*/
function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
if (n.getFullWidth() === 0) {
return false;
}
switch (n.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
@ -426,8 +430,6 @@ module ts.formatting {
return isCompletedNode((<ExpressionStatement>n).expression, sourceFile);
case SyntaxKind.ArrayLiteralExpression:
return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
case SyntaxKind.Missing:
return false;
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
// there is no such thing as terminator token for CaseClause\DefaultClause so for simplicitly always consider them non-completed

View File

@ -1,4 +1,4 @@
tests/cases/compiler/enumConflictsWithGlobalIdentifier.ts(5,1): error TS1003: Identifier expected.
tests/cases/compiler/enumConflictsWithGlobalIdentifier.ts(4,29): error TS1003: Identifier expected.
tests/cases/compiler/enumConflictsWithGlobalIdentifier.ts(4,9): error TS2304: Cannot find name 'IgnoreRulesSpecific'.
@ -7,9 +7,9 @@ tests/cases/compiler/enumConflictsWithGlobalIdentifier.ts(4,9): error TS2304: Ca
IgnoreRulesSpecific = 0,
}
var x = IgnoreRulesSpecific.
!!! error TS1003: Identifier expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'IgnoreRulesSpecific'.
var y = Position.IgnoreRulesSpecific;
!!! error TS1003: Identifier expected.

View File

@ -1,4 +1,4 @@
tests/cases/compiler/enumMemberResolution.ts(5,1): error TS1003: Identifier expected.
tests/cases/compiler/enumMemberResolution.ts(4,29): error TS1003: Identifier expected.
tests/cases/compiler/enumMemberResolution.ts(4,9): error TS2304: Cannot find name 'IgnoreRulesSpecific'.
@ -7,10 +7,10 @@ tests/cases/compiler/enumMemberResolution.ts(4,9): error TS2304: Cannot find nam
IgnoreRulesSpecific = 0
}
var x = IgnoreRulesSpecific. // error
!!! error TS1003: Identifier expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'IgnoreRulesSpecific'.
var y = 1;
!!! error TS1003: Identifier expected.
var z = Position2.IgnoreRulesSpecific; // no error

View File

@ -1,16 +1,13 @@
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts(1,5): error TS1005: ';' expected.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts(1,7): error TS1109: Expression expected.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts(1,1): error TS2304: Cannot find name 'a'.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts(1,7): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
==== tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts (4 errors) ====
==== tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixPostfixExpression1.ts (3 errors) ====
a++ ++;
~~
!!! error TS1005: ';' expected.
~
!!! error TS1109: Expression expected.
~
!!! error TS2304: Cannot find name 'a'.
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
!!! error TS2304: Cannot find name 'a'.

View File

@ -1,16 +1,13 @@
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts(1,8): error TS1005: ';' expected.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts(1,10): error TS1109: Expression expected.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts(1,1): error TS2304: Cannot find name 'foo'.
tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts(1,10): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
==== tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts (4 errors) ====
==== tests/cases/conformance/parser/ecmascript5/Expressions/parserPostfixUnaryExpression1.ts (3 errors) ====
foo ++ ++;
~~
!!! error TS1005: ';' expected.
~
!!! error TS1109: Expression expected.
~~~
!!! error TS2304: Cannot find name 'foo'.
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
!!! error TS2304: Cannot find name 'foo'.