Skip to content

Commit 5904f00

Browse files
committed
fix Issue 13855 - multi-module selective import statements
- allow to add further `mod : sym1, sym2` blocks to import statement - only allow non-ambiguous variations (requiring look-ahead of 2 tokens)
1 parent 06e4b94 commit 5904f00

5 files changed

Lines changed: 46 additions & 1 deletion

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Allow multiple selective imports from different modules in a single import statement
2+
3+
It is now possible to add more imports after a selective import list,
4+
given that the imported module has a package or is followed by another
5+
selective import list.
6+
7+
-------
8+
import pkg.mod1 : sym1, sym2, pkg.mod2;
9+
import pkg.mod1 : sym1, mod2 : sym2;
10+
-------
11+
12+
Modules without package or renamed aliases will still get parsed as part of the selective import list.
13+
14+
-------
15+
import pkg.mod1 : sym1, mod2; // nope, imports symbol mod2 from pkg.mod1
16+
import pkg.mod1 : sym1, name=mod2; // nope, parsed as renamed import of symbol mod2 from pkg.mod1
17+
import pkg.mod1 : sym1, name=pkg1.mod1; // nope, fails to parse
18+
-------

src/ddmd/parse.d

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3280,9 +3280,15 @@ final class Parser : Lexer
32803280
_alias = null;
32813281
}
32823282
s.addAlias(name, _alias);
3283+
if (token.value != TOKcomma)
3284+
break;
3285+
// recognize import pkg.mod1 : a, b, pkg.mod2;
3286+
immutable afterIdent = peekNext2;
3287+
if (peekNext2 == TOKdot || // pkg . mod2
3288+
peekNext2 == TOKcolon) // mod2 : c
3289+
break; // parse another import
32833290
}
32843291
while (token.value == TOKcomma);
3285-
break; // no comma-separated imports of this form
32863292
}
32873293
aliasid = null;
32883294
}

test/compilable/enh13855.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import imports.pkg313.c313 : bug, imports.c314 : bug; // previously 2 import statements
2+
import imports.pkg313.c313 : bug, imports.c314; // also allows qualified module w/o selective import
3+
import imports.c314, imports.pkg313.c313 : bug; // unchanged

test/fail_compilation/enh13855a.d

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
TEST_OUTPUT:
3+
----
4+
fail_compilation/enh13855a.d(7): Error: module imports.c314 import 'enh13855a' not found
5+
----
6+
*/
7+
import imports.c314 : bug, enh13855a; // unqualified module would be ambiguous, parsed as symbol
8+
import enh13855a, imports.c314 : bug; // works unchanged

test/fail_compilation/enh13855b.d

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
REQUIRED_ARGS: -vcolumns
3+
TEST_OUTPUT:
4+
----
5+
fail_compilation/enh13855b.d(9,47): Error: ';' expected
6+
fail_compilation/enh13855b.d(9,52): Error: no identifier for declarator c314
7+
----
8+
*/
9+
import imports.pkg313.c313 : bug, name=imports.c314; // aliased module would require arbitrary lookahead
10+
import name=imports.c314, imports.pkg313.c313 : bug; // works, unchanged

0 commit comments

Comments
 (0)