All files scope.js

95.74% Statements 45/47
83.33% Branches 20/24
100% Functions 6/6
100% Lines 45/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 922x                 29x   29x 29x   237x 237x 237x 145x   237x       29x                 2x 29x 29x 29x   29x   7x 7x   7x 7x 5x   7x 7x 2x   7x 7x 7x   7x     70x 70x 70x 70x 41x 41x       70x     406x 406x 151x   406x       29x 19x     29x 29x 29x   29x     2x      
const visit = require("ast-types").visit;
 
/**
 * Adds dependencies to the given dAst object based on the function calls in the AST.
 *
 * @param {Object} dAst - The dAst object.
 * @returns {Object} - The updated dAst object with added dependencies.
 */
function dependencies(dAst) {
  const functionNames = Object.keys(require("./support-lib.js"));
 
  dAst.dependencies = new Set([]);
  visit(dAst.ast, {
    visitCallExpression(path) {
      const node = path.node;
      let name = node.callee.name;
      if (functionNames.includes(name)) {
        dAst.dependencies.add(name);
      }
      this.traverse(path);
    }
  });
 
  return dAst;
}
 
/**
 * Analyzes the scope of a given abstract syntax tree (AST).
 *
 * @param {Object} dAst - The abstract syntax tree (AST) to analyze.
 * @returns {Object} - The modified abstract syntax tree (AST) with scope information.
 */
const scopeAnalysis = (dAst) => {
  const Scope = require('./scope-class.js');
  let scope = new Scope(null);
  let ast = dAst.ast;
 
  visit(ast, {
    visitFunctionExpression(path) {
      let node = path.node;
      scope = new Scope(scope);
 
      let params = node.params;
      for (let param of params) {
        scope.setAsInitialized(param.name);
      }
      this.traverse(path);
      if (scope.length > 0) {
        node.body.body.unshift(scope.buildDeclaration());
      }
      node.scope = scope;
      let d = scope.notDeclaredMessage();
      Iif (d) console.error(d + ' used in function scope');
 
      scope = scope.parent;
    },
    visitAssignmentExpression(path) {
      const node = path.node;
      Eif (node.left.type === 'Identifier') {
        let name = node.left.name;
        if (name && name && /^[$]/.test(name) && !scope.has(name)) {
          Eif (!dAst.dependencies.has(name)) {
            scope.add(name);
          }
        }
      }
      this.traverse(path);
    },
    visitIdentifier(path) {
      let name = path.node.name;
      if (/^[$]/.test(name) && !dAst.dependencies.has(name)) {
        scope.setAsUsed(name);
      }
      this.traverse(path);
    }
  });
 
  if (scope.length > 0) {
    ast.body.unshift(scope.buildDeclaration());
  }
 
  ast.scope = scope;
  let d = scope.notDeclaredMessage();
  Iif (d) console.error(d);
 
  return dAst;
}
 
module.exports = {
  scopeAnalysis,
  dependencies,
}