checkImports()

in lib/semantic.js [733:823]


  checkImports(ast) {
    if (ast.imports.length === 0) {
      return;
    }

    const filePath = this.filename;
    const pkgDir = path.dirname(filePath);
    const pkgPath = this.mainPkg ? getDarafile(this.mainPkg) : getDarafile(pkgDir);
    if (!fs.existsSync(pkgPath)) {
      this.error(`the Darafile not exists`);
    }

    const pkg = JSON.parse(stripComments(fs.readFileSync(pkgPath, 'utf-8')));
    pkg.libraries = pkg.libraries || {};

    for (let i = 0; i < ast.imports.length; i++) {
      const item = ast.imports[i];
      const aliasId = item.lexeme;
      
      let mainPkg = !!item.innerPath && path.dirname(pkgPath);
      const mainModule = item.mainModule;
      if (!mainModule && !mainPkg && !pkg.libraries[aliasId] && pkg.name !== aliasId) {
        this.error(`the import "${aliasId}" not defined in Darafile`, item);
      }

      if(mainModule && !pkg.libraries[mainModule] && pkg.name !== mainModule) {
        this.error(`the import "${mainModule}" not defined in Darafile`, item);
      }

      if (this.dependencies.has(aliasId)) {
        this.error(`the module id "${aliasId}" has been imported`, item);
      }
      const specPath = pkg.libraries[aliasId] || pkg.main;
      let realSpecPath;
      

      if(mainModule) {
        const key = pkg.libraries[mainModule];
        const module = item.module;
        if (!this.libraries[key]) {
          this.error(`the module id "${aliasId}" has not installed, use \`dara install\` first`, item);
        }
       
        const libPath = path.join(this.root, this.libraries[key]);
        const libMetaPath = getDarafile(libPath);
        const libMeta = JSON.parse(stripComments(fs.readFileSync(libMetaPath, 'utf-8')));
        if(!libMeta.exports || !libMeta.exports[module]) {
          this.error(`the submodule id "${module}" has not been exported in "${mainModule}"`, item);
        }
        realSpecPath = path.join(libPath, libMeta.exports[module]);
        mainPkg = libPath;
      } else if(mainPkg) {
        if (item.innerPath.endsWith('.dara') || item.innerPath.endsWith('.tea') || item.innerPath.endsWith('.spec')) {
          realSpecPath = path.join(pkgDir, item.innerPath);
        } else if(fs.existsSync(path.join(pkgDir, `${item.innerPath}.dara`))){
          realSpecPath = path.join(pkgDir, `${item.innerPath}.dara`);
        } else if(fs.existsSync(path.join(pkgDir, `${item.innerPath}.tea`))){
          realSpecPath = path.join(pkgDir, `${item.innerPath}.tea`);
        } else if(fs.existsSync(path.join(pkgDir, `${item.innerPath}.spec`))){
          realSpecPath = path.join(pkgDir, `${item.innerPath}.spec`);
        }
      } else if (specPath.startsWith('./') || specPath.startsWith('../')) {
        if (specPath.endsWith('.dara') || specPath.endsWith('.tea') || specPath.endsWith('.spec')) {
          realSpecPath = path.join(pkgDir, specPath);
        } else {
          const libMetaPath = getDarafile(path.join(pkgDir, specPath));
          const libMeta = JSON.parse(stripComments(fs.readFileSync(libMetaPath, 'utf-8')));
          realSpecPath = path.join(pkgDir, specPath, libMeta.main);
        }
      } else {
        const key = `${specPath}`;
        if (!this.libraries[key]) {
          this.error(`the module id "${aliasId}" has not installed, use \`dara install\` first`, item);
        }
        const libPath = path.join(this.root, this.libraries[key]);
        const libMetaPath = getDarafile(libPath);
        const libMeta = JSON.parse(stripComments(fs.readFileSync(libMetaPath, 'utf-8')));
        realSpecPath = path.join(libPath, libMeta.main);
      }
      const source = fs.readFileSync(realSpecPath, 'utf-8');
      const lexer = new Lexer(source, realSpecPath);
      const parser = new Parser(lexer);
      const depAst = parser.program();
      const checker = existsChecker.get(realSpecPath) || new TypeChecker(source, realSpecPath, this.root, this.libraries, mainPkg).check(depAst);
      this.dependencies.set(aliasId, checker);
      if(mainPkg) {
        this.innerDep.set(aliasId, checker.ast);
      }
      this.usedExternModel.set(aliasId, new Set());
    }
  }