Closed kaby76 closed 11 months ago
In a A imports B scenario, you have 3 theoretical options:
Option 1 would make sense but doesn't work because unfortunately tsc does not convert .ts extensions to .js. This is well-known and painful problem with Typescript.
Option 2 works, but requires B to be compiled beforehand, otherwise some IDEs will complain that B cannot be found, and will not import the definitions (required for edit-time type checking)
Option 3 works in IDEs, and in node if packaged (using webpack or similar), but will fail in edge cases.
My preferred approach is 3 (as you can see in the runtime) and works perfectly with .d.ts files (they never make it to node anyway). All the .js files follow the node spec you mentioned: https://nodejs.org/api/esm.html#import-specifiers. However, the generated lexers and parsers are plain Typescript files, and there is no corresponding spec for Typescript. Since they are not packaged (yet!), they have to follow option 2. This was necessary for the antlr test suite to pass (we don't webpack each unit test).
In another plain Typescript project, I also use option 3 with ts-node, successfully running mocha unit tests as follows:
mocha --loader=ts-node/esm require ts-node/register my_test_file.ts
From the above though, it seems we do have an inconsistency in generated imports i.e. they should follow option 2. That could be worth fixing.
The reason for having 2 types of imports is because there is only 1 object to export from the generated Listener and Visitor, so that's the default export. It is assumed that the abstract parser is also a default import. But the generated Lexer and Parser must export more than 1 object, hence the need for { .. } style imports.
Thanks. That makes sense. Option 3 seems right. Just need to try packaging it up. But of course no idea how to yet. :)
See for example:
@kaby76 Fixed, but it will require a tool release (or a local build from dev branch)
This is a possible problem with the TypeScript target. It is best demonstrated by the plsql grammar. This grammar is different than most because it contains a "superClass" option for lexer and parser.
If you generate the target TypeScript code for the grammar (
antlr4 -v 4.13.1 -encoding utf-8 -Dlanguage=TypeScript PlSqlLexer.g4; antlr4 -v 4.13.1 -encoding utf-8 -Dlanguage=TypeScript PlSqlParser.g4
), you get code with two types of "import" statements, many with curly braces around an imported class:and others without curly braces:
My tsconfig.json file is this:
This code compiles fine with tsc. However, I cannot execute using
node
or thets-node
wrapper package because I get import errors:What's disturbing is that I do know 6 days ago Microsoft made a release of the typescript package, and since then, nothing works. I've been trying to rollback the environment but haven't found a fix.
I noticed that the Antlr Tool generates an inconsistent import syntax for the superClass vs the Listener,
import PlSqlParserListener from "./PlSqlParserListener.js";
, which contains a ".js".As a hunch, I changed the PlSqlParser.ts and PlSqlLexer.ts files to use an explicit ".js" for the import for the base class, and now it works.
Analysis
According to the most recent node.js documentation, https://nodejs.org/api/esm.html#import-specifiers, a relative specifier must have a suffix.
The file extension is always necessary for these.
The Antlr tool does not comply with this as the base class specifier is relative but does not have a suffix.Questions
Why does the Antlr tool generate PlSqlParser.ts with
import PlSqlParserListener from "./PlSqlParserListener.js";
, which contains ".js", andimport PlSqlParserBase from './PlSqlParserBase';
, which does not contain the ".js"?Is there a workaround, besides running a "sed" script to fix the generated files?