Skip to content

Commit 91d31c7

Browse files
committed
Add error about missing module flag to createProgram
1 parent f7d7623 commit 91d31c7

5 files changed

Lines changed: 55 additions & 27 deletions

File tree

src/compiler/binder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ module ts {
168168
declareModuleMember(node, symbolKind, symbolExcludes);
169169
break;
170170
case SyntaxKind.SourceFile:
171-
if (container.flags & NodeFlags.ExternalModule) {
171+
if (isExternalModule(<SourceFile>container)) {
172172
declareModuleMember(node, symbolKind, symbolExcludes);
173173
break;
174174
}
@@ -323,7 +323,7 @@ module ts {
323323
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes);
324324
break;
325325
case SyntaxKind.SourceFile:
326-
if (node.flags & NodeFlags.ExternalModule) {
326+
if (isExternalModule(<SourceFile>node)) {
327327
bindAnonymousDeclaration(node, SymbolFlags.ValueModule, '"' + getModuleNameFromFilename((<SourceFile>node).filename) + '"');
328328
break;
329329
}

src/compiler/checker.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ module ts {
183183
}
184184

185185
function isGlobalSourceFile(node: Node) {
186-
return node.kind === SyntaxKind.SourceFile && !(node.flags & NodeFlags.ExternalModule);
186+
return node.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>node);
187187
}
188188

189189
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
@@ -238,7 +238,7 @@ module ts {
238238
}
239239
switch (location.kind) {
240240
case SyntaxKind.SourceFile:
241-
if (!(location.flags & NodeFlags.ExternalModule)) break;
241+
if (!isExternalModule(<SourceFile>location)) break;
242242
case SyntaxKind.ModuleDeclaration:
243243
if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.ModuleMember)) {
244244
return returnResolvedSymbol(result);
@@ -610,7 +610,7 @@ module ts {
610610
}
611611
switch (location.kind) {
612612
case SyntaxKind.SourceFile:
613-
if (!(location.flags & NodeFlags.ExternalModule)) {
613+
if (!isExternalModule(<SourceFile>location)) {
614614
break;
615615
}
616616
case SyntaxKind.ModuleDeclaration:
@@ -942,7 +942,7 @@ module ts {
942942
}
943943
}
944944
else if (node.kind === SyntaxKind.SourceFile) {
945-
return (node.flags & NodeFlags.ExternalModule) ? node : undefined;
945+
return isExternalModule(<SourceFile>node) ? node : undefined;
946946
}
947947
}
948948
Debug.fail("getContainingModule cant reach here");
@@ -5799,7 +5799,7 @@ module ts {
57995799
emitExtends = false;
58005800
potentialThisCollisions.length = 0;
58015801
forEach(node.statements, checkSourceElement);
5802-
if (node.flags & NodeFlags.ExternalModule) {
5802+
if (isExternalModule(node)) {
58035803
var symbol = getExportAssignmentSymbol(node.symbol);
58045804
if (symbol && symbol.flags & SymbolFlags.Import) {
58055805
// Mark the import as referenced so that we emit it in the final .js file.
@@ -5883,7 +5883,7 @@ module ts {
58835883
}
58845884
switch (location.kind) {
58855885
case SyntaxKind.SourceFile:
5886-
if (!(location.flags & NodeFlags.ExternalModule)) break;
5886+
if (!isExternalModule(<SourceFile>location)) break;
58875887
case SyntaxKind.ModuleDeclaration:
58885888
copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.ModuleMember);
58895889
break;
@@ -6036,7 +6036,7 @@ module ts {
60366036
return getSourceTextOfNode(node.name);
60376037
}
60386038

6039-
function isExternalModule(symbol: Symbol): boolean {
6039+
function isExternalModuleSymbol(symbol: Symbol): boolean {
60406040
return symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length === 1 && symbol.declarations[0].kind === SyntaxKind.SourceFile;
60416041
}
60426042

@@ -6057,7 +6057,7 @@ module ts {
60576057

60586058
// symbol will have a parent if it is an export symbol
60596059
if (symbol.parent) {
6060-
return isExternalModule(symbol.parent) ? "exports" : symbolToString(symbol.parent);
6060+
return isExternalModuleSymbol(symbol.parent) ? "exports" : symbolToString(symbol.parent);
60616061
}
60626062
}
60636063
}
@@ -6170,7 +6170,7 @@ module ts {
61706170
});
61716171
// Initialize global symbol table
61726172
forEach(program.getSourceFiles(), file => {
6173-
if (!(file.flags & NodeFlags.ExternalModule)) {
6173+
if (!isExternalModule(file)) {
61746174
extendSymbolTable(globals, file.locals);
61756175
}
61766176
});

src/compiler/emitter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ module ts {
3131

3232
function shouldEmitToOwnFile(sourceFile: SourceFile) {
3333
if (!(sourceFile.flags & NodeFlags.DeclarationFile)) {
34-
if ((sourceFile.flags & NodeFlags.ExternalModule || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
34+
if ((isExternalModule(sourceFile) || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
3535
return true;
3636
}
3737
}
@@ -49,7 +49,7 @@ module ts {
4949
}
5050

5151
function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
52-
return !!(sourceFile.flags & (NodeFlags.ExternalModule | NodeFlags.DeclarationFile));
52+
return isExternalModule(sourceFile) || (sourceFile.flags & NodeFlags.DeclarationFile) !== 0;
5353
}
5454

5555
function getFirstConstructorWithBody(node: ClassDeclaration): ConstructorDeclaration {
@@ -1552,7 +1552,7 @@ module ts {
15521552
// preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
15531553
// - current file is not external module
15541554
// - import declaration is top level and target is value imported by entity name
1555-
emitImportDeclaration = !(currentSourceFile.flags & NodeFlags.ExternalModule) && resolver.isTopLevelValueImportedViaEntityName(node);
1555+
emitImportDeclaration = !isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportedViaEntityName(node);
15561556
}
15571557

15581558
if (emitImportDeclaration) {
@@ -1701,7 +1701,7 @@ module ts {
17011701
write("};");
17021702
extendsEmitted = true;
17031703
}
1704-
if (node.flags & NodeFlags.ExternalModule) {
1704+
if (isExternalModule(node)) {
17051705
if (compilerOptions.module === ModuleKind.AMD) {
17061706
emitAMDModule(node, startIndex);
17071707
}

src/compiler/parser.ts

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ module ts {
8585
return flattenDiagnosticChain(file, start, length, messageChain);
8686
}
8787

88+
export function getErrorSpanForNode(node: Node): TextRange {
89+
var errorSpan: TextRange;
90+
switch (node.kind) {
91+
// This list is a work in progress. Add missing node kinds to improve their error
92+
// spans.
93+
}
94+
return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node;
95+
}
96+
97+
export function isExternalModule(file: SourceFile): boolean {
98+
return file.externalModuleIndicator !== undefined;
99+
}
100+
88101
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
89102
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
90103
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
@@ -377,8 +390,9 @@ module ts {
377390
// words, this function is called once we have already parsed the node, and are just
378391
// applying some stricter checks on that node.
379392
function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
380-
var start = skipTrivia(file.text, node.pos);
381-
var length = node.end - start;
393+
var span = getErrorSpanForNode(node);
394+
var start = skipTrivia(file.text, span.pos);
395+
var length = span.end - start;
382396

383397
file.syntacticErrors.push(createFileDiagnostic(file, start, length, message, arg0, arg1, arg2));
384398
}
@@ -1838,8 +1852,8 @@ module ts {
18381852
return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, name, sig, body);
18391853
}
18401854

1841-
function makeFunctionExpression(kind: SyntaxKind, pos: number, name: Identifier, sig: ParsedSignature, body: Node) {
1842-
var node = <FunctionDeclaration>createNode(kind, pos);
1855+
function makeFunctionExpression(kind: SyntaxKind, pos: number, name: Identifier, sig: ParsedSignature, body: Node): FunctionExpression {
1856+
var node = <FunctionExpression>createNode(kind, pos);
18431857
node.name = name;
18441858
node.typeParameters = sig.typeParameters;
18451859
node.parameters = sig.parameters;
@@ -2939,10 +2953,13 @@ module ts {
29392953
};
29402954
}
29412955

2942-
function isExternalModule() {
2943-
return forEach(file.statements, node => node.flags & NodeFlags.Export ||
2944-
node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).externalModuleName ||
2945-
node.kind === SyntaxKind.ExportAssignment ? true : false);
2956+
function getExternalModuleIndicator() {
2957+
return forEach(file.statements, node =>
2958+
node.flags & NodeFlags.Export
2959+
|| node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).externalModuleName
2960+
|| node.kind === SyntaxKind.ExportAssignment
2961+
? node
2962+
: undefined);
29462963
}
29472964

29482965
scanner = createScanner(languageVersion, sourceText, scanError, onComment);
@@ -2961,7 +2978,7 @@ module ts {
29612978
file.referencedFiles = referenceComments.referencedFiles;
29622979
file.amdDependencies = referenceComments.amdDependencies;
29632980
file.statements = parseList(ParsingContext.SourceElements, parseSourceElement);
2964-
if (isExternalModule()) file.flags |= NodeFlags.ExternalModule;
2981+
file.externalModuleIndicator = getExternalModuleIndicator();
29652982
file.nodeCount = nodeCount;
29662983
file.identifierCount = identifierCount;
29672984
return file;
@@ -3130,12 +3147,21 @@ module ts {
31303147
return;
31313148
}
31323149

3150+
var firstExternalModule = forEach(files, f => isExternalModule(f) ? f : undefined);
3151+
if (firstExternalModule && options.module === ModuleKind.None) {
3152+
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
3153+
var externalModuleIndicatorNode = firstExternalModule.externalModuleIndicator;
3154+
var errorStart = skipTrivia(firstExternalModule.text, externalModuleIndicatorNode.pos);
3155+
var errorLength = externalModuleIndicatorNode.end - errorStart;
3156+
errors.push(createFileDiagnostic(firstExternalModule, errorStart, errorLength, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
3157+
}
3158+
31333159
// there has to be common source directory if user specified --outdir || --sourcRoot
31343160
// if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
31353161
if (options.outDir || // there is --outDir specified
31363162
options.sourceRoot || // there is --sourceRoot specified
31373163
(options.mapRoot && // there is --mapRoot Specified and there would be multiple js files generated
3138-
(!options.out || !!filter(files, sourceFile => !!(sourceFile.flags & NodeFlags.ExternalModule)).length))) {
3164+
(!options.out || firstExternalModule !== undefined))) {
31393165

31403166
var commonPathComponents: string[];
31413167
forEach(files, sourceFile => {

src/compiler/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ module ts {
229229
MultiLine = 0x00000080, // Multi-line array or object literal
230230
Synthetic = 0x00000100, // Synthetic node (for full fidelity)
231231
DeclarationFile = 0x00000200, // Node is a .d.ts file
232-
ExternalModule = 0x00000400, // Node is an external module
233232

234233
Modifier = Export | Ambient | Public | Private | Static
235234
}
@@ -336,7 +335,9 @@ module ts {
336335
whenFalse: Expression;
337336
}
338337

339-
export interface FunctionExpression extends Expression, FunctionDeclaration { }
338+
export interface FunctionExpression extends Expression, FunctionDeclaration {
339+
body: Node; // Required, whereas the member inherited from FunctionDeclaration is optional
340+
}
340341

341342
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral
342343
// this means quotes have been removed and escapes have been converted to actual characters. For a NumericLiteral, the
@@ -514,6 +515,7 @@ module ts {
514515
syntacticErrors: Diagnostic[];
515516
semanticErrors: Diagnostic[];
516517
hasNoDefaultLib: boolean;
518+
externalModuleIndicator: Node; // The first node that causes this file to be an external module
517519
nodeCount: number;
518520
identifierCount: number;
519521
symbolCount: number;

0 commit comments

Comments
 (0)