mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-18 12:21:37 -06:00
Resolve external helpers module and report errors for missing module/exports
This commit is contained in:
parent
6ad04375c4
commit
76b34939d0
@ -1264,10 +1264,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
const moduleReferenceLiteral = <LiteralExpression>moduleReferenceExpression;
|
||||
return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral);
|
||||
}
|
||||
|
||||
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node): Symbol {
|
||||
// Module names are escaped in our symbol table. However, string literal values aren't.
|
||||
// Escape the name in the "require(...)" clause to ensure we find the right symbol.
|
||||
const moduleName = escapeIdentifier(moduleReferenceLiteral.text);
|
||||
const moduleName = escapeIdentifier(moduleReference);
|
||||
|
||||
if (moduleName === undefined) {
|
||||
return;
|
||||
@ -1282,7 +1285,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReferenceLiteral.text);
|
||||
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference);
|
||||
const sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName);
|
||||
if (sourceFile) {
|
||||
if (sourceFile.symbol) {
|
||||
@ -1291,7 +1294,7 @@ namespace ts {
|
||||
}
|
||||
if (moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
error(moduleReferenceLiteral, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
|
||||
error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -1305,7 +1308,7 @@ namespace ts {
|
||||
|
||||
if (moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
error(moduleReferenceLiteral, moduleNotFoundError, moduleName);
|
||||
error(errorNode, moduleNotFoundError, moduleName);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -17843,6 +17846,46 @@ namespace ts {
|
||||
const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined);
|
||||
globalReadonlyArrayType = symbol && <GenericType>getTypeOfGlobalSymbol(symbol, /*arity*/ 1);
|
||||
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
|
||||
|
||||
// If we have specified that we are importing helpers, we should report global
|
||||
// errors if we cannot resolve the helpers external module, or if it does not have
|
||||
// the necessary helpers exported.
|
||||
if (compilerOptions.importHelpers) {
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
const requestedHelpers = sourceFile.flags & NodeFlags.EmitHelperFlags;
|
||||
if (requestedHelpers && (compilerOptions.isolatedModules || isExternalModule(sourceFile))) {
|
||||
const helpers = resolveExternalModule(sourceFile, externalHelpersModuleNameText, Diagnostics.Cannot_find_module_0, /*errorNode*/ undefined);
|
||||
if (helpers) {
|
||||
const exports = helpers.exports;
|
||||
if (requestedHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES6) {
|
||||
verifyHelperSymbol(exports, "__extends", SymbolFlags.Function);
|
||||
}
|
||||
if (requestedHelpers & NodeFlags.HasJsxSpreadAttributes && compilerOptions.jsx !== JsxEmit.Preserve) {
|
||||
verifyHelperSymbol(exports, "__assign", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedHelpers & NodeFlags.HasDecorators) {
|
||||
verifyHelperSymbol(exports, "__decorate", SymbolFlags.Value);
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
verifyHelperSymbol(exports, "__metadata", SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
if (requestedHelpers & NodeFlags.HasParamDecorators) {
|
||||
verifyHelperSymbol(exports, "__param", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedHelpers & NodeFlags.HasAsyncFunctions) {
|
||||
verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function verifyHelperSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags) {
|
||||
const symbol = getSymbol(symbols, escapeIdentifier(name), meaning);
|
||||
if (!symbol) {
|
||||
error(/*location*/ undefined, Diagnostics.Module_0_has_no_exported_member_1, externalHelpersModuleNameText, name);
|
||||
}
|
||||
}
|
||||
|
||||
function createInstantiatedPromiseLikeType(): ObjectType {
|
||||
|
||||
@ -824,7 +824,7 @@ namespace ts {
|
||||
if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
|
||||
if (node.imports !== undefined) updated.imports = node.imports;
|
||||
if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations;
|
||||
if (node.tslib !== undefined) updated.tslib = node.tslib;
|
||||
if (node.externalHelpersModuleName !== undefined) updated.externalHelpersModuleName = node.externalHelpersModuleName;
|
||||
return updateNode(updated, node);
|
||||
}
|
||||
|
||||
@ -1065,15 +1065,15 @@ namespace ts {
|
||||
|
||||
// Helpers
|
||||
|
||||
export function createHelperName(tslib: Identifier | undefined, name: string) {
|
||||
return tslib
|
||||
? createPropertyAccess(tslib, name)
|
||||
export function createHelperName(externalHelpersModuleName: Identifier | undefined, name: string) {
|
||||
return externalHelpersModuleName
|
||||
? createPropertyAccess(externalHelpersModuleName, name)
|
||||
: createIdentifier(name);
|
||||
}
|
||||
|
||||
export function createExtendsHelper(tslib: Identifier | undefined, name: Identifier) {
|
||||
export function createExtendsHelper(externalHelpersModuleName: Identifier | undefined, name: Identifier) {
|
||||
return createCall(
|
||||
createHelperName(tslib, "__extends"),
|
||||
createHelperName(externalHelpersModuleName, "__extends"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
name,
|
||||
@ -1082,17 +1082,17 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
export function createAssignHelper(tslib: Identifier | undefined, attributesSegments: Expression[]) {
|
||||
export function createAssignHelper(externalHelpersModuleName: Identifier | undefined, attributesSegments: Expression[]) {
|
||||
return createCall(
|
||||
createHelperName(tslib, "__assign"),
|
||||
createHelperName(externalHelpersModuleName, "__assign"),
|
||||
/*typeArguments*/ undefined,
|
||||
attributesSegments
|
||||
);
|
||||
}
|
||||
|
||||
export function createParamHelper(tslib: Identifier | undefined, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
export function createParamHelper(externalHelpersModuleName: Identifier | undefined, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
return createCall(
|
||||
createHelperName(tslib, "__param"),
|
||||
createHelperName(externalHelpersModuleName, "__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
@ -1102,9 +1102,9 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
export function createMetadataHelper(tslib: Identifier | undefined, metadataKey: string, metadataValue: Expression) {
|
||||
export function createMetadataHelper(externalHelpersModuleName: Identifier | undefined, metadataKey: string, metadataValue: Expression) {
|
||||
return createCall(
|
||||
createHelperName(tslib, "__metadata"),
|
||||
createHelperName(externalHelpersModuleName, "__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
@ -1113,7 +1113,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
export function createDecorateHelper(tslib: Identifier | undefined, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
export function createDecorateHelper(externalHelpersModuleName: Identifier | undefined, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
|
||||
argumentsArray.push(target);
|
||||
@ -1124,12 +1124,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return createCall(createHelperName(tslib, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
|
||||
return createCall(createHelperName(externalHelpersModuleName, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
|
||||
}
|
||||
|
||||
export function createAwaiterHelper(tslib: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
export function createAwaiterHelper(externalHelpersModuleName: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
return createCall(
|
||||
createHelperName(tslib, "__awaiter"),
|
||||
createHelperName(externalHelpersModuleName, "__awaiter"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
|
||||
@ -1723,6 +1723,17 @@ namespace ts {
|
||||
let imports: LiteralExpression[];
|
||||
let moduleAugmentations: LiteralExpression[];
|
||||
|
||||
// If we are importing helpers, we need to add a synthetic reference to resolve the
|
||||
// helpers library.
|
||||
if (options.importHelpers
|
||||
&& (options.isolatedModules || isExternalModuleFile)
|
||||
&& !file.isDeclarationFile) {
|
||||
const externalHelpersModuleReference = <StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
externalHelpersModuleReference.text = externalHelpersModuleNameText;
|
||||
externalHelpersModuleReference.parent = file;
|
||||
imports = [externalHelpersModuleReference];
|
||||
}
|
||||
|
||||
for (const node of file.statements) {
|
||||
collectModuleReferences(node, /*inAmbientModule*/ false);
|
||||
if (isJavaScriptFile) {
|
||||
|
||||
@ -702,7 +702,7 @@ namespace ts {
|
||||
if (extendsClauseElement) {
|
||||
statements.push(
|
||||
createStatement(
|
||||
createExtendsHelper(currentSourceFile.tslib, getDeclarationName(node)),
|
||||
createExtendsHelper(currentSourceFile.externalHelpersModuleName, getDeclarationName(node)),
|
||||
/*location*/ extendsClauseElement
|
||||
)
|
||||
);
|
||||
|
||||
@ -106,7 +106,7 @@ namespace ts {
|
||||
// Either emit one big object literal (no spread attribs), or
|
||||
// a call to the __assign helper.
|
||||
objectProperties = singleOrUndefined(segments)
|
||||
|| createAssignHelper(currentSourceFile.tslib, segments);
|
||||
|| createAssignHelper(currentSourceFile.externalHelpersModuleName, segments);
|
||||
}
|
||||
|
||||
const element = createReactCreateElement(
|
||||
|
||||
@ -51,7 +51,7 @@ namespace ts {
|
||||
let currentNamespace: ModuleDeclaration;
|
||||
let currentNamespaceContainerName: Identifier;
|
||||
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
|
||||
let currentSourceFileTslib: Identifier;
|
||||
let currentSourceFileExternalHelpersModuleName: Identifier;
|
||||
|
||||
/**
|
||||
* Keeps track of whether expression substitution has been enabled for specific edge cases.
|
||||
@ -432,22 +432,22 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements);
|
||||
const tslib = createUniqueName("tslib");
|
||||
const tslibImport = createImportDeclaration(
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(tslib)),
|
||||
createLiteral("tslib")
|
||||
const externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText);
|
||||
const externalHelpersModuleImport = createImportDeclaration(
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
);
|
||||
tslibImport.parent = node;
|
||||
tslibImport.flags &= ~NodeFlags.Synthesized;
|
||||
statements.push(tslibImport);
|
||||
externalHelpersModuleImport.parent = node;
|
||||
externalHelpersModuleImport.flags &= ~NodeFlags.Synthesized;
|
||||
statements.push(externalHelpersModuleImport);
|
||||
|
||||
currentSourceFileTslib = tslib;
|
||||
currentSourceFileExternalHelpersModuleName = externalHelpersModuleName;
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
currentSourceFileTslib = undefined;
|
||||
currentSourceFileExternalHelpersModuleName = undefined;
|
||||
|
||||
node = updateSourceFileNode(node, createNodeArray(statements, node.statements));
|
||||
node.tslib = tslib;
|
||||
node.externalHelpersModuleName = externalHelpersModuleName;
|
||||
}
|
||||
else {
|
||||
node = visitEachChild(node, visitor, context);
|
||||
@ -1382,7 +1382,7 @@ namespace ts {
|
||||
: undefined;
|
||||
|
||||
const helper = createDecorateHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
prefix,
|
||||
memberName,
|
||||
@ -1432,7 +1432,7 @@ namespace ts {
|
||||
const expression = createAssignment(
|
||||
decoratedClassAlias,
|
||||
createDecorateHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
getDeclarationName(node)
|
||||
)
|
||||
@ -1456,7 +1456,7 @@ namespace ts {
|
||||
const result = createAssignment(
|
||||
getDeclarationName(node),
|
||||
createDecorateHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
getDeclarationName(node)
|
||||
),
|
||||
@ -1489,7 +1489,7 @@ namespace ts {
|
||||
expressions = [];
|
||||
for (const decorator of decorators) {
|
||||
const helper = createParamHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
transformDecorator(decorator),
|
||||
parameterOffset,
|
||||
/*location*/ decorator.expression);
|
||||
@ -1519,13 +1519,13 @@ namespace ts {
|
||||
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileTslib, "design:type", serializeTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:type", serializeTypeOfNode(node)));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileTslib, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileTslib, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1543,7 +1543,7 @@ namespace ts {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeReturnTypeOfNode(node))));
|
||||
}
|
||||
if (properties) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileTslib, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2234,7 +2234,7 @@ namespace ts {
|
||||
statements.push(
|
||||
createReturn(
|
||||
createAwaiterHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
transformFunctionBodyWorker(<Block>node.body)
|
||||
@ -2261,7 +2261,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
return createAwaiterHelper(
|
||||
currentSourceFileTslib,
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
<Block>transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)
|
||||
|
||||
@ -1726,8 +1726,8 @@ namespace ts {
|
||||
/* @internal */ imports: LiteralExpression[];
|
||||
/* @internal */ moduleAugmentations: LiteralExpression[];
|
||||
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
|
||||
// The synthesized identifier for an imported tslib helpers runtime.
|
||||
/* @internal */ tslib?: Identifier;
|
||||
// The synthesized identifier for an imported external helpers module.
|
||||
/* @internal */ externalHelpersModuleName?: Identifier;
|
||||
}
|
||||
|
||||
export interface ScriptReferenceHost {
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const externalHelpersModuleNameText = "tslib";
|
||||
|
||||
export interface ReferencePathMatchResult {
|
||||
fileReference?: FileReference;
|
||||
diagnosticMessage?: DiagnosticMessage;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user