Skip to content

Commit 9ae3fb0

Browse files
committed
innerDep contain the exports module
1 parent 427cc1d commit 9ae3fb0

File tree

5 files changed

+67
-5
lines changed

5 files changed

+67
-5
lines changed

lib/semantic.js

+39-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const {
2020

2121
const builtin = require('./builtin');
2222

23+
const existsChecker = new Map();
24+
2325
function replace(origin, target) {
2426
Object.keys(origin).forEach((key) => {
2527
delete origin[key];
@@ -507,6 +509,7 @@ class TypeChecker {
507509
} else {
508510
this.libraries = libraries;
509511
}
512+
existsChecker.set(filename, this);
510513
}
511514

512515
error(message, token) {
@@ -567,6 +570,7 @@ class TypeChecker {
567570
});
568571

569572
find = checker.findProperty(extendModel, propName, isException, moduleName, extendFrom);
573+
570574
if(!find) {
571575
return;
572576
}
@@ -744,7 +748,7 @@ class TypeChecker {
744748
const item = ast.imports[i];
745749
const aliasId = item.lexeme;
746750

747-
const innerModule = !!item.innerPath;
751+
let innerModule = !!item.innerPath;
748752
const mainModule = item.mainModule;
749753

750754
if (!mainModule && !innerModule && !pkg.libraries[aliasId] && pkg.name !== aliasId) {
@@ -776,6 +780,7 @@ class TypeChecker {
776780
this.error(`the submodule id "${module}" has not been exported in "${mainModule}"`, item);
777781
}
778782
realSpecPath = path.join(libPath, libMeta.exports[module]);
783+
innerModule = true;
779784
} else if(innerModule) {
780785
if (item.innerPath.endsWith('.dara') || item.innerPath.endsWith('.tea') || item.innerPath.endsWith('.spec')) {
781786
realSpecPath = path.join(pkgDir, item.innerPath);
@@ -808,7 +813,7 @@ class TypeChecker {
808813
const lexer = new Lexer(source, realSpecPath);
809814
const parser = new Parser(lexer);
810815
const depAst = parser.program();
811-
const checker = new TypeChecker(source, realSpecPath, this.root, this.libraries, innerModule).check(depAst);
816+
const checker = existsChecker.get(realSpecPath) || new TypeChecker(source, realSpecPath, this.root, this.libraries, innerModule).check(depAst);
812817
this.dependencies.set(aliasId, checker);
813818
if(innerModule) {
814819
this.innerDep.set(aliasId, checker.ast);
@@ -817,6 +822,34 @@ class TypeChecker {
817822
}
818823
}
819824

825+
checkExports(){
826+
const filePath = this.filename;
827+
const pkgDir = path.dirname(filePath);
828+
const pkgPath = this.inner ? getDarafile(this.root) : getDarafile(pkgDir);
829+
if (!fs.existsSync(pkgPath)) {
830+
return;
831+
}
832+
833+
const pkg = JSON.parse(stripComments(fs.readFileSync(pkgPath, 'utf-8')));
834+
if(!pkg.exports) {
835+
return;
836+
}
837+
const exports = Object.keys(pkg.exports);
838+
for (let i = 0; i < exports.length; i++) {
839+
const aliasId = exports[i];
840+
if(this.innerDep.has(aliasId)) {
841+
continue;
842+
}
843+
const exportSpec = path.join(pkgDir, pkg.exports[aliasId]);
844+
const source = fs.readFileSync(exportSpec, 'utf-8');
845+
const lexer = new Lexer(source, exportSpec);
846+
const parser = new Parser(lexer);
847+
const depAst = parser.program();
848+
const checker = existsChecker.get(exportSpec) || new TypeChecker(source, exportSpec, this.root, this.libraries, true).check(depAst);
849+
this.innerDep.set(aliasId, checker.ast);
850+
}
851+
}
852+
820853
check(ast) {
821854
assert.equal(ast.type, 'module');
822855
// 类型系统
@@ -845,6 +878,9 @@ class TypeChecker {
845878
this.postCheckInit(ast);
846879
// check unused virtualVariable & virtualMethod
847880
this.postCheckTypes(ast);
881+
if(!this.inner) {
882+
this.checkExports(ast);
883+
}
848884
ast.models = {};
849885
for (var [key, value] of this.models) {
850886
ast.models[key] = value;
@@ -2547,7 +2583,6 @@ class TypeChecker {
25472583
} else {
25482584
model = this.models.get(type.name);
25492585
}
2550-
25512586
const find = checker.findProperty(model, propName, model.isException);
25522587
if (!find) {
25532588
return;
@@ -3368,7 +3403,7 @@ function analyze(source, filePath) {
33683403
while(!key.done) {
33693404
const ast = builtin.get(key.value);
33703405
if(ast.type === 'module') {
3371-
builtin.set(key.value, new TypeChecker(source, filePath).check(ast));
3406+
builtin.set(key.value, new TypeChecker(source, filePath, null, null, true).check(ast));
33723407
}
33733408
key = it.next();
33743409
}

test/fixtures/multi_module/Darafile

+3
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@
55
"main": "./sdk.dara",
66
"libraries": {
77
"DARAUtil": "darabonba:Util:*"
8+
},
9+
"exports": {
10+
"Resource": "./model/resource.dara"
811
}
912
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
model Resource {
2+
name: string,
3+
age: integer,
4+
}

test/lexer.test.js

-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ describe('lexer', function () {
322322
{ tag: undefined, loc: loc(1, 14, 1, 14) }
323323
]);
324324

325-
console.log('%j', lex('@prop({ key = "value" })', '__filename'));
326325
expect(lex('@prop({ key = "value" })', '__filename')).to.be.eql([
327326
{ tag: 43, lexeme: '@prop',
328327
'loc': loc(1, 1, 1, 6)

test/semantic.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -6996,6 +6996,27 @@ describe('semantic', function () {
69966996

69976997
it('use inner module should ok', function () {
69986998
let ast = readAndParse('fixtures/multi_module/sdk.dara');
6999+
7000+
const ResourceAst = ast.innerDep.get('Resource');
7001+
const [resourceModel] = ResourceAst.moduleBody.nodes;
7002+
expect(resourceModel.type).to.be('model');
7003+
expect(resourceModel.modelName).to.eql({
7004+
'tag': 2,
7005+
'loc':
7006+
{
7007+
'start': {
7008+
'line': 1,
7009+
'column': 7
7010+
},
7011+
'end':
7012+
{
7013+
'line': 1,
7014+
'column': 15
7015+
}
7016+
},
7017+
'lexeme':'Resource',
7018+
'index': 2
7019+
});
69997020

70007021
const userAst = ast.innerDep.get('User');
70017022
const [model] = userAst.moduleBody.nodes;

0 commit comments

Comments
 (0)