Don't parse nodes, only to not include them in the tree. This will break incremental parsing scenarios.

Properly store the data for an external module reference in the AST.
This commit is contained in:
Cyrus Najmabadi 2014-12-01 03:00:27 -08:00
parent 4db6d3136c
commit ada6cebef3
6 changed files with 85 additions and 45 deletions

View file

@ -467,9 +467,9 @@ module ts {
if (!links.target) {
links.target = resolvingSymbol;
var node = <ImportDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ImportDeclaration);
var target = node.externalModuleName ?
resolveExternalModuleName(node, node.externalModuleName) :
getSymbolOfPartOfRightHandSideOfImport(node.entityName, node);
var target = node.externalModuleName
? resolveExternalModuleName(node, node.externalModuleName.expression)
: getSymbolOfPartOfRightHandSideOfImport(node.entityName, node);
if (links.target === resolvingSymbol) {
links.target = target || unknownSymbol;
}
@ -546,7 +546,12 @@ module ts {
return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\";
}
function resolveExternalModuleName(location: Node, moduleLiteral: LiteralExpression): Symbol {
function resolveExternalModuleName(location: Node, moduleExpression: Expression): Symbol {
if (moduleExpression.kind !== SyntaxKind.StringLiteral) {
return;
}
var moduleLiteral = <LiteralExpression>moduleExpression;
var searchPath = getDirectoryPath(getSourceFile(location).filename);
var moduleName = moduleLiteral.text;
if (!moduleName) return;
@ -8368,12 +8373,17 @@ module ts {
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference
// other external modules only through top - level external module names.
// Relative external module names are not permitted.
if (isExternalModuleNameRelative(node.externalModuleName.text)) {
error(node, Diagnostics.Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
target = unknownSymbol;
if (node.externalModuleName.expression.kind === SyntaxKind.StringLiteral) {
if (isExternalModuleNameRelative((<LiteralExpression>node.externalModuleName.expression).text)) {
error(node, Diagnostics.Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
target = unknownSymbol;
}
else {
target = resolveImport(symbol);
}
}
else {
target = resolveImport(symbol);
target = unknownSymbol;
}
}
else {
@ -8948,8 +8958,8 @@ module ts {
case SyntaxKind.StringLiteral:
// External module name in an import declaration
if (node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node) {
var importSymbol = getSymbolOfNode(node.parent);
if (node.parent.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent.parent).externalModuleName.expression === node) {
var importSymbol = getSymbolOfNode(node.parent.parent);
var moduleType = getTypeOfSymbol(importSymbol);
return moduleType ? moduleType.symbol : undefined;
}

View file

@ -671,7 +671,7 @@ module ts {
}
else {
write("require(");
writeTextOfNode(currentSourceFile, node.externalModuleName);
writeTextOfNode(currentSourceFile, node.externalModuleName.expression);
write(");");
}
writer.writeLine();
@ -3312,11 +3312,12 @@ module ts {
emit(node.entityName);
}
else {
var literal = <LiteralExpression>node.externalModuleName.expression;
write("require(");
emitStart(node.externalModuleName);
emitLiteral(node.externalModuleName);
emitEnd(node.externalModuleName);
emitToken(SyntaxKind.CloseParenToken, node.externalModuleName.end);
emitStart(literal);
emitLiteral(literal);
emitEnd(literal);
emitToken(SyntaxKind.CloseParenToken, literal.end);
}
write(";");
emitEnd(node);
@ -3356,7 +3357,7 @@ module ts {
write("[\"require\", \"exports\"");
forEach(imports, imp => {
write(", ");
emitLiteral(imp.externalModuleName);
emitLiteral(<LiteralExpression>imp.externalModuleName.expression);
});
forEach(node.amdDependencies, amdDependency => {
var text = "\"" + amdDependency + "\"";

View file

@ -394,6 +394,8 @@ module ts {
return child((<ComputedPropertyName>node).expression);
case SyntaxKind.HeritageClause:
return children((<HeritageClause>node).types);
case SyntaxKind.ExternalModuleReference:
return child((<ExternalModuleReference>node).expression);
}
}
@ -1726,14 +1728,6 @@ module ts {
return node;
}
function parseStringLiteral(): LiteralExpression {
if (token === SyntaxKind.StringLiteral) {
return parseLiteralNode(/*internName:*/ true);
}
error(Diagnostics.String_literal_expected);
return <LiteralExpression>createMissingNode();
}
// TYPES
function parseTypeReference(): TypeReferenceNode {
@ -1786,9 +1780,7 @@ module ts {
function parseParameterType(): TypeNode {
return parseOptional(SyntaxKind.ColonToken)
? token === SyntaxKind.StringLiteral
? parseStringLiteral()
: parseType()
? token === SyntaxKind.StringLiteral ? parseLiteralNode(/*internName:*/ true) : parseType()
: undefined;
}
@ -3940,7 +3932,7 @@ module ts {
function parseAmbientExternalModuleDeclaration(fullStart: number, flags: NodeFlags): ModuleDeclaration {
var node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
node.flags = flags;
node.name = parseStringLiteral();
node.name = parseLiteralNode(/*internName:*/ true);
node.body = parseModuleBlock();
return finishNode(node);
}
@ -3952,24 +3944,45 @@ module ts {
: parseInternalModuleTail(fullStart, flags);
}
function isExternalModuleReference() {
if (token === SyntaxKind.RequireKeyword) {
return lookAhead(() => {
nextToken();
return token === SyntaxKind.OpenParenToken;
});
}
return false;
}
function parseImportDeclaration(fullStart: number, modifiers: ModifiersArray): ImportDeclaration {
var node = <ImportDeclaration>createNode(SyntaxKind.ImportDeclaration, fullStart);
setModifiers(node, modifiers);
parseExpected(SyntaxKind.ImportKeyword);
node.name = parseIdentifier();
parseExpected(SyntaxKind.EqualsToken);
var entityName = parseEntityName(/*allowReservedWords*/ false);
if (entityName.kind === SyntaxKind.Identifier && (<Identifier>entityName).text === "require" && parseOptional(SyntaxKind.OpenParenToken)) {
node.externalModuleName = parseStringLiteral();
parseExpected(SyntaxKind.CloseParenToken);
if (isExternalModuleReference()) {
node.externalModuleName = parseExternalModuleReference();
}
else {
node.entityName = entityName;
node.entityName = parseEntityName(/*allowReservedWords*/ false);
}
parseSemicolon();
return finishNode(node);
}
function parseExternalModuleReference() {
var node = <ExternalModuleReference>createNode(SyntaxKind.ExternalModuleReference);
parseExpected(SyntaxKind.RequireKeyword);
parseExpected(SyntaxKind.OpenParenToken);
node.expression = parseExpression();
if (node.expression.kind === SyntaxKind.StringLiteral) {
internIdentifier((<LiteralExpression>node.expression).text);
}
parseExpected(SyntaxKind.CloseParenToken);
return finishNode(node);
}
function parseExportAssignmentTail(fullStart: number, modifiers: ModifiersArray): ExportAssignment {
var node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment, fullStart);
setModifiers(node, modifiers);
@ -4307,6 +4320,7 @@ module ts {
case SyntaxKind.DeleteExpression: return checkDeleteExpression(<DeleteExpression> node);
case SyntaxKind.ElementAccessExpression: return checkElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.ExportAssignment: return checkExportAssignment(<ExportAssignment>node);
case SyntaxKind.ExternalModuleReference: return checkExternalModuleReference(<ExternalModuleReference>node);
case SyntaxKind.ForInStatement: return checkForInStatement(<ForInStatement>node);
case SyntaxKind.ForStatement: return checkForStatement(<ForStatement>node);
case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(<FunctionLikeDeclaration>node);
@ -4704,6 +4718,12 @@ module ts {
}
}
function checkExternalModuleReference(node: ExternalModuleReference) {
if (node.expression.kind !== SyntaxKind.StringLiteral) {
return grammarErrorOnNode(node.expression, Diagnostics.String_literal_expected);
}
}
function checkForInStatement(node: ForInStatement) {
return checkVariableDeclarations(node.declarations) ||
checkForMoreThanOneDeclaration(node.declarations);
@ -4905,7 +4925,7 @@ module ts {
return grammarErrorOnNode(statement, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
}
else if (statement.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>statement).externalModuleName) {
return grammarErrorOnNode((<ImportDeclaration>statement).externalModuleName, Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
return grammarErrorOnNode((<ImportDeclaration>statement).externalModuleName.expression, Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
}
}
}
@ -5627,8 +5647,11 @@ module ts {
function processImportedModules(file: SourceFile, basePath: string) {
forEach(file.statements, node => {
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).externalModuleName) {
var nameLiteral = (<ImportDeclaration>node).externalModuleName;
if (node.kind === SyntaxKind.ImportDeclaration &&
(<ImportDeclaration>node).externalModuleName &&
(<ImportDeclaration>node).externalModuleName.expression.kind === SyntaxKind.StringLiteral) {
var nameLiteral = <LiteralExpression>(<ImportDeclaration>node).externalModuleName.expression;
var moduleName = nameLiteral.text;
if (moduleName) {
var searchPath = basePath;
@ -5653,8 +5676,11 @@ module ts {
// The StringLiteral must specify a top - level external module name.
// Relative external module names are not permitted
forEachChild((<ModuleDeclaration>node).body, node => {
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).externalModuleName) {
var nameLiteral = (<ImportDeclaration>node).externalModuleName;
if (node.kind === SyntaxKind.ImportDeclaration &&
(<ImportDeclaration>node).externalModuleName &&
(<ImportDeclaration>node).externalModuleName.expression.kind === SyntaxKind.StringLiteral) {
var nameLiteral = <LiteralExpression>(<ImportDeclaration>node).externalModuleName.expression;
var moduleName = nameLiteral.text;
if (moduleName) {
// TypeScript 1.0 spec (April 2014): 12.1.6

View file

@ -221,6 +221,8 @@ module ts {
ModuleBlock,
ImportDeclaration,
ExportAssignment,
// Module references
ExternalModuleReference,
// Clauses
CaseClause,
DefaultClause,
@ -730,7 +732,11 @@ module ts {
export interface ImportDeclaration extends Declaration, ModuleElement {
name: Identifier;
entityName?: EntityName;
externalModuleName?: LiteralExpression;
externalModuleName?: ExternalModuleReference;
}
export interface ExternalModuleReference extends Node {
expression?: Expression;
}
export interface ExportAssignment extends Statement, ModuleElement {

View file

@ -1982,7 +1982,7 @@ module ts {
function isNameOfExternalModuleImportOrDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.StringLiteral &&
(isNameOfModuleDeclaration(node) ||
(node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node));
(node.parent.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent.parent).externalModuleName.expression === node));
}
/** Returns true if the position is within a comment */
@ -3086,7 +3086,7 @@ module ts {
displayParts.push(spacePart());
displayParts.push(keywordPart(SyntaxKind.RequireKeyword));
displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
displayParts.push(displayPart(getTextOfNode(importDeclaration.externalModuleName), SymbolDisplayPartKind.stringLiteral));
displayParts.push(displayPart(getTextOfNode(importDeclaration.externalModuleName.expression), SymbolDisplayPartKind.stringLiteral));
displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
else {

View file

@ -1,12 +1,9 @@
tests/cases/conformance/externalModules/importNonStringLiteral.ts(2,22): error TS1141: String literal expected.
tests/cases/conformance/externalModules/importNonStringLiteral.ts(2,23): error TS1005: ';' expected.
==== tests/cases/conformance/externalModules/importNonStringLiteral.ts (2 errors) ====
==== tests/cases/conformance/externalModules/importNonStringLiteral.ts (1 errors) ====
var x = "filename";
import foo = require(x); // invalid
~
!!! error TS1141: String literal expected.
~
!!! error TS1005: ';' expected.