/
ExternalModule.ts
108 lines (97 loc) · 3.32 KB
/
ExternalModule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import ExternalVariable from './ast/variables/ExternalVariable';
import type { CustomPluginOptions, ModuleInfo, NormalizedInputOptions } from './rollup/types';
import { EMPTY_ARRAY } from './utils/blank';
import { errUnusedExternalImports, warnDeprecation } from './utils/error';
import { makeLegal } from './utils/identifierHelpers';
export default class ExternalModule {
readonly dynamicImporters: string[] = [];
execIndex = Infinity;
readonly exportedVariables = new Map<ExternalVariable, string>();
readonly importers: string[] = [];
readonly info: ModuleInfo;
reexported = false;
suggestedVariableName: string;
used = false;
private readonly declarations = new Map<string, ExternalVariable>();
private mostCommonSuggestion = 0;
private readonly nameSuggestions = new Map<string, number>();
constructor(
private readonly options: NormalizedInputOptions,
public readonly id: string,
moduleSideEffects: boolean | 'no-treeshake',
meta: CustomPluginOptions,
public readonly renormalizeRenderPath: boolean
) {
this.suggestedVariableName = makeLegal(id.split(/[\\/]/).pop()!);
const { importers, dynamicImporters } = this;
const info: ModuleInfo = (this.info = {
ast: null,
code: null,
dynamicallyImportedIdResolutions: EMPTY_ARRAY,
dynamicallyImportedIds: EMPTY_ARRAY,
get dynamicImporters() {
return dynamicImporters.sort();
},
hasDefaultExport: null,
get hasModuleSideEffects() {
warnDeprecation(
'Accessing ModuleInfo.hasModuleSideEffects from plugins is deprecated. Please use ModuleInfo.moduleSideEffects instead.',
true,
options
);
return info.moduleSideEffects;
},
id,
implicitlyLoadedAfterOneOf: EMPTY_ARRAY,
implicitlyLoadedBefore: EMPTY_ARRAY,
importedIdResolutions: EMPTY_ARRAY,
importedIds: EMPTY_ARRAY,
get importers() {
return importers.sort();
},
isEntry: false,
isExternal: true,
isIncluded: null,
meta,
moduleSideEffects,
syntheticNamedExports: false
});
// Hide the deprecated key so that it only warns when accessed explicitly
Object.defineProperty(this.info, 'hasModuleSideEffects', {
enumerable: false
});
}
getVariableForExportName(name: string): [variable: ExternalVariable] {
const declaration = this.declarations.get(name);
if (declaration) return [declaration];
const externalVariable = new ExternalVariable(this, name);
this.declarations.set(name, externalVariable);
this.exportedVariables.set(externalVariable, name);
return [externalVariable];
}
suggestName(name: string): void {
const value = (this.nameSuggestions.get(name) ?? 0) + 1;
this.nameSuggestions.set(name, value);
if (value > this.mostCommonSuggestion) {
this.mostCommonSuggestion = value;
this.suggestedVariableName = name;
}
}
warnUnusedImports(): void {
const unused = Array.from(this.declarations)
.filter(
([name, declaration]) =>
name !== '*' && !declaration.included && !this.reexported && !declaration.referenced
)
.map(([name]) => name);
if (unused.length === 0) return;
const importersSet = new Set<string>();
for (const name of unused) {
for (const importer of this.declarations.get(name)!.module.importers) {
importersSet.add(importer);
}
}
const importersArray = [...importersSet];
this.options.onwarn(errUnusedExternalImports(this.id, unused, importersArray));
}
}