Skip to content

Commit f93a262

Browse files
authored
Improve error message if an import cannot be found (#1307)
1 parent 7d133cc commit f93a262

File tree

4 files changed

+71
-36
lines changed

4 files changed

+71
-36
lines changed

cli/asc.js

+19-12
Original file line numberDiff line numberDiff line change
@@ -207,20 +207,20 @@ exports.main = function main(argv, options, callback) {
207207
// Check for unknown arguments
208208
if (opts.unknown.length) {
209209
opts.unknown.forEach(arg => {
210-
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unknown option '" + arg + "'" + EOL);
210+
stderr.write(colorsUtil.stderr.yellow("WARNING ") + "Unknown option '" + arg + "'" + EOL);
211211
});
212212
}
213213

214214
// Check for trailing arguments
215215
if (opts.trailing.length) {
216-
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unsupported trailing arguments: " + opts.trailing.join(" ") + EOL);
216+
stderr.write(colorsUtil.stderr.yellow("WARNING ") + "Unsupported trailing arguments: " + opts.trailing.join(" ") + EOL);
217217
}
218218

219219
// Use default callback if none is provided
220220
if (!callback) callback = function defaultCallback(err) {
221221
var code = 0;
222222
if (err) {
223-
stderr.write(colorsUtil.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL);
223+
stderr.write(colorsUtil.stderr.red("FAILURE ") + err.stack.replace(/^ERROR: /i, "") + EOL);
224224
code = 1;
225225
}
226226
return code;
@@ -534,15 +534,20 @@ exports.main = function main(argv, options, callback) {
534534
var internalPath;
535535
while ((internalPath = assemblyscript.nextFile(program)) != null) {
536536
let file = getFile(internalPath, assemblyscript.getDependee(program, internalPath));
537-
if (!file) return callback(Error("Import '" + internalPath + "' not found."));
538-
stats.parseCount++;
539-
stats.parseTime += measure(() => {
540-
assemblyscript.parse(program, file.sourceText, file.sourcePath, false);
541-
});
537+
if (file) {
538+
stats.parseCount++;
539+
stats.parseTime += measure(() => {
540+
assemblyscript.parse(program, file.sourceText, file.sourcePath, false);
541+
});
542+
} else {
543+
assemblyscript.parse(program, null, internalPath + extension.ext, false);
544+
}
542545
}
543546
var numErrors = checkDiagnostics(program, stderr);
544547
if (numErrors) {
545-
return callback(Error(numErrors + " parse error(s)"));
548+
const err = Error(numErrors + " parse error(s)");
549+
err.stack = err.message; // omit stack
550+
return callback(err);
546551
}
547552
}
548553

@@ -577,8 +582,8 @@ exports.main = function main(argv, options, callback) {
577582
let sourceText = readFile(sourcePath + extension.ext, baseDir);
578583
if (sourceText == null) {
579584
sourceText = readFile(sourcePath + "/index" + extension.ext, baseDir);
580-
if (sourceText == null) return callback(Error("Entry file '" + sourcePath + extension.ext + "' not found."));
581-
sourcePath += "/index" + extension.ext;
585+
if (sourceText != null) sourcePath += "/index" + extension.ext;
586+
else sourcePath += extension.ext;
582587
} else {
583588
sourcePath += extension.ext;
584589
}
@@ -634,7 +639,9 @@ exports.main = function main(argv, options, callback) {
634639
var numErrors = checkDiagnostics(program, stderr);
635640
if (numErrors) {
636641
if (module) module.dispose();
637-
return callback(Error(numErrors + " compile error(s)"));
642+
const err = Error(numErrors + " compile error(s)");
643+
err.stack = err.message; // omit stack
644+
return callback(err);
638645
}
639646

640647
// Call afterCompile transform hook

src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ export function isError(message: DiagnosticMessage): bool {
214214
export function parse(
215215
/** Program reference. */
216216
program: Program,
217-
/** Source text of the file. */
218-
text: string,
217+
/** Source text of the file, or `null` to indicate not found. */
218+
text: string | null,
219219
/** Normalized path of the file. */
220220
path: string,
221221
/** Whether this is an entry file. */

src/parser.ts

+44-15
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ import {
8989
mangleInternalPath
9090
} from "./ast";
9191

92+
/** Represents a dependee. */
93+
class Dependee {
94+
constructor(
95+
public source: Source,
96+
public reportNode: Node
97+
) {}
98+
}
99+
92100
/** Parser interface. */
93101
export class Parser extends DiagnosticEmitter {
94102

@@ -102,8 +110,8 @@ export class Parser extends DiagnosticEmitter {
102110
onComment: CommentHandler | null = null;
103111
/** Current file being parsed. */
104112
currentSource: Source | null = null;
105-
/** Dependency map **/
106-
dependees: Map<string, Source> = new Map();
113+
/** Map of dependees being depended upon by a source, by path. */
114+
dependees: Map<string, Dependee> = new Map();
107115
/** An array of parsed sources. */
108116
sources: Source[];
109117

@@ -118,21 +126,37 @@ export class Parser extends DiagnosticEmitter {
118126

119127
/** Parses a file and adds its definitions to the program. */
120128
parseFile(
121-
/** Source text of the file. */
122-
text: string,
129+
/** Source text of the file, or `null` to indicate not found. */
130+
text: string | null,
123131
/** Normalized path of the file. */
124132
path: string,
125133
/** Whether this is an entry file. */
126134
isEntry: bool
127135
): void {
128136
// the frontend gives us paths with file extensions
129137
var normalizedPath = normalizePath(path);
130-
var internalPath = mangleInternalPath(normalizedPath);
138+
var internalPath = mangleInternalPath(path);
139+
131140
// check if already processed
132141
if (this.donelog.has(internalPath)) return;
133142
this.donelog.add(internalPath); // do not parse again
134143
this.seenlog.add(internalPath); // do not request again
135144

145+
// check if this is an error
146+
if (text === null) {
147+
let dependees = this.dependees;
148+
let dependee: Dependee | null = null;
149+
if (dependees.has(internalPath)) dependee = assert(dependees.get(internalPath));
150+
this.error(
151+
DiagnosticCode.File_0_not_found,
152+
dependee
153+
? dependee.reportNode.range
154+
: null,
155+
path
156+
);
157+
return;
158+
}
159+
136160
// create the source element
137161
var source = new Source(
138162
isEntry
@@ -402,10 +426,13 @@ export class Parser extends DiagnosticEmitter {
402426
return backlog.length ? assert(backlog.shift()) : null;
403427
}
404428

405-
/** Obtains the dependee of the given imported file. */
429+
/** Obtains the path of the dependee of the given imported file. */
406430
getDependee(dependent: string): string | null {
407-
var source = this.dependees.get(dependent);
408-
if (source) return source.internalPath;
431+
var dependees = this.dependees;
432+
if (dependees.has(dependent)) {
433+
let dependee = assert(dependees.get(dependent));
434+
return dependee.source.internalPath;
435+
}
409436
return null;
410437
}
411438

@@ -2447,11 +2474,13 @@ export class Parser extends DiagnosticEmitter {
24472474
}
24482475
}
24492476
let ret = Node.createExportStatement(members, path, isDeclare, tn.range(startPos, tn.pos));
2450-
let internalPath = ret.internalPath;
2451-
if (internalPath !== null && !this.seenlog.has(internalPath)) {
2452-
this.dependees.set(internalPath, currentSource);
2453-
this.backlog.push(internalPath);
2454-
this.seenlog.add(internalPath);
2477+
if (path !== null) {
2478+
let internalPath = assert(ret.internalPath);
2479+
if (!this.seenlog.has(internalPath)) {
2480+
this.dependees.set(internalPath, new Dependee(currentSource, path));
2481+
this.backlog.push(internalPath);
2482+
this.seenlog.add(internalPath);
2483+
}
24552484
}
24562485
tn.skip(Token.SEMICOLON);
24572486
return ret;
@@ -2466,7 +2495,7 @@ export class Parser extends DiagnosticEmitter {
24662495
if (!exportPaths) source.exportPaths = [ internalPath ];
24672496
else if (!exportPaths.includes(internalPath)) exportPaths.push(internalPath);
24682497
if (!this.seenlog.has(internalPath)) {
2469-
this.dependees.set(internalPath, currentSource);
2498+
this.dependees.set(internalPath, new Dependee(currentSource, path));
24702499
this.backlog.push(internalPath);
24712500
}
24722501
tn.skip(Token.SEMICOLON);
@@ -2638,7 +2667,7 @@ export class Parser extends DiagnosticEmitter {
26382667
}
26392668
let internalPath = ret.internalPath;
26402669
if (!this.seenlog.has(internalPath)) {
2641-
this.dependees.set(internalPath, assert(this.currentSource));
2670+
this.dependees.set(internalPath, new Dependee(assert(this.currentSource), path));
26422671
this.backlog.push(internalPath);
26432672
}
26442673
tn.skip(Token.SEMICOLON);

tests/packages/packages/g/test.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#!/usr/bin/env node
2-
let asc = require("../../../../cli/asc");
2+
const asc = require("../../../../cli/asc");
33

4-
let argv = [
4+
const stderr = asc.createMemoryStream();
5+
asc.main([
56
"assembly/index.ts",
67
"--noEmit",
78
"--runtime", "stub",
89
"--traceResolution"
9-
];
10-
11-
asc.main(argv, error => {
12-
if (/Import .*lib\/a.* not found/g.test(error.message)) {
10+
], { stderr }, err => {
11+
if (stderr.toString().includes("File '~lib/a.ts' not found.")) {
1312
process.exit(0);
1413
}
15-
console.error("Failed!\n" + error);
14+
console.error("Failed!\n" + err);
1615
process.exit(1);
1716
});

0 commit comments

Comments
 (0)