Checking of ES6 import declarations

This commit is contained in:
Anders Hejlsberg 2015-02-08 17:33:45 -08:00
parent 69d47ef854
commit e47f64c510
6 changed files with 100 additions and 71 deletions

View file

@ -9336,18 +9336,78 @@ module ts {
return <Identifier>node;
}
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
// Grammar checking
checkGrammarModifiers(node);
function checkExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration): boolean {
var moduleName = getImportedModuleName(node);
if (getFullWidth(moduleName) !== 0 && moduleName.kind !== SyntaxKind.StringLiteral) {
error(moduleName, Diagnostics.String_literal_expected);
return false;
}
var inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.StringLiteral;
if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) {
error(moduleName, Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
return false;
}
if (inAmbientExternalModule && isExternalModuleNameRelative((<LiteralExpression>moduleName).text)) {
// TypeScript 1.0 spec (April 2013): 12.1.6
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference
// other external modules only through top - level external module names.
// Relative external module names are not permitted.
error(node, Diagnostics.Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
return false;
}
return true;
}
function checkImportSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
var symbol = getSymbolOfNode(node);
var target = resolveImport(symbol);
if (target !== unknownSymbol) {
var excludedMeanings =
(symbol.flags & SymbolFlags.Value ? SymbolFlags.Value : 0) |
(symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
(symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
if (target.flags & excludedMeanings) {
error(node, Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0, symbolToString(symbol));
}
}
}
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
var symbol = getSymbolOfNode(node);
var target: Symbol;
checkImportSymbol(node);
}
function checkImportDeclaration(node: ImportDeclaration) {
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
}
if (checkExternalImportDeclaration(node)) {
var importClause = node.importClause;
if (importClause) {
if (importClause.name) {
// TODO: Check that import references an export default instance
checkImportBinding(importClause);
}
if (importClause.namedBindings) {
// TODO: Check that import references an export namespace
if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
checkImportBinding(<NamespaceImport>importClause.namedBindings);
}
else {
forEach((<NamedImports>importClause.namedBindings).elements, checkImportBinding);
}
}
}
}
}
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
checkGrammarModifiers(node);
if (isInternalModuleImportEqualsDeclaration(node)) {
target = resolveImport(symbol);
// Import declaration for an internal module
checkImportBinding(node);
var symbol = getSymbolOfNode(node);
var target = resolveImport(symbol);
if (target !== unknownSymbol) {
if (target.flags & SymbolFlags.Value) {
// Target is a value symbol, check that it is not hidden by a local declaration with the same name and
@ -9366,44 +9426,8 @@ module ts {
}
}
else {
var moduleNameExpr = getExternalModuleImportEqualsDeclarationExpression(node);
if (moduleNameExpr.kind !== SyntaxKind.StringLiteral) {
grammarErrorOnNode(moduleNameExpr, Diagnostics.String_literal_expected);
}
// Import declaration for an external module
if (node.parent.kind === SyntaxKind.SourceFile) {
target = resolveImport(symbol);
}
else if (node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.StringLiteral) {
// TypeScript 1.0 spec (April 2013): 12.1.6
// 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 (moduleNameExpr.kind === SyntaxKind.StringLiteral) {
if (isExternalModuleNameRelative((<LiteralExpression>moduleNameExpr).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 = unknownSymbol;
}
}
else {
// Parent is an internal module (syntax error is already reported)
target = unknownSymbol;
}
}
if (target !== unknownSymbol) {
var excludedMeanings =
(symbol.flags & SymbolFlags.Value ? SymbolFlags.Value : 0) |
(symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
(symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
if (target.flags & excludedMeanings) {
error(node, Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0, symbolToString(symbol));
if (checkExternalImportDeclaration(node)) {
checkImportBinding(node);
}
}
}
@ -9509,6 +9533,8 @@ module ts {
return checkEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
return checkModuleDeclaration(<ModuleDeclaration>node);
case SyntaxKind.ImportDeclaration:
return checkImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return checkImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ExportAssignment:
@ -10347,6 +10373,7 @@ module ts {
case SyntaxKind.VariableStatement:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.Parameter:
break;

View file

@ -147,6 +147,7 @@ module ts {
Merge_conflict_marker_encountered: { code: 1185, category: DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
A_rest_element_cannot_have_an_initializer: { code: 1186, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." },
An_import_declaration_cannot_have_modifiers: { code: 1188, category: DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },

View file

@ -579,6 +579,10 @@
"category": "Error",
"code": 1187
},
"An import declaration cannot have modifiers.": {
"category": "Error",
"code": 1188
},
"Duplicate identifier '{0}'.": {
"category": "Error",

View file

@ -3898,7 +3898,7 @@ module ts {
}
function emitRequire(moduleName: Expression) {
if (moduleName) {
if (moduleName.kind === SyntaxKind.StringLiteral) {
write("require(");
emitStart(moduleName);
emitLiteral(<LiteralExpression>moduleName);
@ -4080,8 +4080,8 @@ module ts {
forEach(externalImports, info => {
write(", ");
var moduleName = getImportedModuleName(info.importNode);
if (moduleName) {
emitLiteral(moduleName);
if (moduleName.kind === SyntaxKind.StringLiteral) {
emitLiteral(<LiteralExpression>moduleName);
}
else {
write("\"\"");

View file

@ -352,21 +352,22 @@ module ts {
function processImportedModules(file: SourceFile, basePath: string) {
forEach(file.statements, node => {
if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) {
var nameLiteral = getImportedModuleName(node);
var moduleName = nameLiteral && nameLiteral.text;
if (moduleName) {
var searchPath = basePath;
while (true) {
var searchName = normalizePath(combinePaths(searchPath, moduleName));
if (findModuleSourceFile(searchName + ".ts", nameLiteral) || findModuleSourceFile(searchName + ".d.ts", nameLiteral)) {
break;
var moduleNameExpr = getImportedModuleName(node);
if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) {
var moduleNameText = (<LiteralExpression>moduleNameExpr).text;
if (moduleNameText) {
var searchPath = basePath;
while (true) {
var searchName = normalizePath(combinePaths(searchPath, moduleNameText));
if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
break;
}
var parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) {
break;
}
searchPath = parentPath;
}
var parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) {
break;
}
searchPath = parentPath;
}
}
}
@ -397,7 +398,7 @@ module ts {
}
});
function findModuleSourceFile(fileName: string, nameLiteral: LiteralExpression) {
function findModuleSourceFile(fileName: string, nameLiteral: Expression) {
return findSourceFile(fileName, /* isDefaultLib */ false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
}
}

View file

@ -597,18 +597,14 @@ module ts {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}
function extractStringLiteral(node: Expression): StringLiteralExpression {
return node && node.kind === SyntaxKind.StringLiteral ? <StringLiteralExpression>node : undefined;
}
export function getImportedModuleName(node: Node): StringLiteralExpression {
export function getImportedModuleName(node: Node): Expression {
if (node.kind === SyntaxKind.ImportDeclaration) {
return extractStringLiteral((<ImportDeclaration>node).moduleSpecifier);
return (<ImportDeclaration>node).moduleSpecifier;
}
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
var reference = (<ImportEqualsDeclaration>node).moduleReference;
if (reference.kind === SyntaxKind.ExternalModuleReference) {
return extractStringLiteral((<ExternalModuleReference>reference).expression);
return (<ExternalModuleReference>reference).expression;
}
}
}