@Override
  public void visitBlock(BlockTree tree) {
    if (isScopeAlreadyCreated(tree)) {
      super.visitBlock(tree);

    } else {
      newBlockScope(tree);
      super.visitBlock(tree);
      leaveScope();
    }
  }
  @Override
  public void visitClass(ClassTree tree) {
    newBlockScope(tree);

    super.visitClass(tree);

    leaveScope();
  }
  @Override
  public void visitForObjectStatement(ForObjectStatementTree tree) {
    newBlockScope(tree);

    skipBlock(tree.statement());
    super.visitForObjectStatement(tree);

    leaveScope();
  }
  @Override
  public void visitFunctionExpression(FunctionExpressionTree tree) {
    newFunctionScope(tree);

    skipBlock(tree.body());
    super.visitFunctionExpression(tree);

    leaveScope();
  }
  @Override
  public void visitCatchBlock(CatchBlockTree tree) {
    newBlockScope(tree);

    skipBlock(tree.block());
    super.visitCatchBlock(tree);

    leaveScope();
  }
  @Override
  public void visitMethodDeclaration(MethodDeclarationTree tree) {
    newFunctionScope(tree);

    skipBlock(tree.body());
    super.visitMethodDeclaration(tree);

    leaveScope();
  }
  @Override
  public void visitScript(ScriptTree tree) {
    this.symbolModel = (SymbolModelBuilder) getContext().getSymbolModel();
    this.currentScope = null;
    this.skippedBlocks = new ArrayList<>();
    this.treeScopeMap = new HashMap<>();

    newFunctionScope(tree);
    super.visitScript(tree);
    leaveScope();
  }
 @Override
 public void accept(DoubleDispatchVisitor visitor) {
   visitor.visitNamedExportDeclaration(this);
 }