CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-plato

JavaScript source analysis and visualizer that generates detailed complexity reports

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

reporters.mddocs/

Analysis Reporters

Specialized analysis modules for different code quality metrics and linting integration. Reporters provide the core analysis functionality for complexity calculation, JSHint integration, and ESLint integration.

Capabilities

Complexity Reporter

Analyzes JavaScript source code to calculate complexity metrics including cyclomatic complexity, Halstead metrics, and maintainability indices.

/**
 * Analyze JavaScript source code complexity metrics
 * @param {String} source - JavaScript source code to analyze
 * @param {Object} options - Analysis options and configuration
 * @param {Object} reportInfo - File information object for context
 * @returns {Object} Complexity analysis report with detailed metrics
 */
function process(source, options, reportInfo);

Parameters:

  • source (String): JavaScript source code to analyze
  • options (Object): Analysis options and configuration
  • reportInfo (Object): File information object containing file metadata

Returns: Object - Comprehensive complexity analysis report

Report Structure:

interface ComplexityReport {
  /** Cyclomatic complexity score */
  cyclomatic: number;
  
  /** Source lines of code metrics */
  sloc: {
    /** Physical lines of code (including comments and whitespace) */
    physical: number;
    /** Logical lines of code (executable statements) */
    logical: number;
  };
  
  /** Halstead complexity metrics */
  halstead: {
    /** Operator analysis */
    operators: {
      distinct: number;          // Number of unique operators
      total: number;             // Total operator count
      identifiers: string[];     // List of operators found
    };
    /** Operand analysis */
    operands: {
      distinct: number;          // Number of unique operands
      total: number;             // Total operand count
      identifiers: string[];     // List of operands found
    };
    length: number;              // Program length (N = N1 + N2)
    vocabulary: number;          // Program vocabulary (n = n1 + n2)
    difficulty: number;          // Programming difficulty
    volume: number;              // Program volume
    effort: number;              // Programming effort
    bugs: number;                // Estimated bugs
    time: number;                // Estimated programming time (seconds)
  };
  
  /** Maintainability index (0-100, higher is better) */
  maintainability: number;
  
  /** Function parameter count analysis */
  params: number;
  
  /** Additional complexity metrics */
  // ... other complexity measurements
}

Usage Examples:

const complexityReporter = require('plato/lib/reporters/complexity');

// Analyze source code
const sourceCode = `
function calculateSum(a, b, c) {
  if (a > 0) {
    return a + b + c;
  } else {
    return b + c;
  }
}
`;

const reportInfo = {
  file: 'calculator.js',
  fileShort: 'calculator.js'
};

const complexityReport = complexityReporter.process(sourceCode, {}, reportInfo);

console.log('Cyclomatic Complexity:', complexityReport.cyclomatic);
console.log('Maintainability Index:', complexityReport.maintainability);
console.log('Physical SLOC:', complexityReport.sloc.physical);
console.log('Logical SLOC:', complexityReport.sloc.logical);
console.log('Halstead Volume:', complexityReport.halstead.volume);

JSHint Reporter

Integrates JSHint linting analysis to identify potential issues and coding standard violations in JavaScript code.

/**
 * Run JSHint analysis on JavaScript source code
 * @param {String} source - JavaScript source code to analyze
 * @param {Object} options - JSHint configuration options
 * @returns {Object} JSHint analysis report with messages and metadata
 */
function process(source, options);

Parameters:

  • source (String): JavaScript source code to analyze
  • options (Object): JSHint configuration options and rules

Returns: Object - JSHint analysis report

Report Structure:

interface JSHintReport {
  /** Array of JSHint messages */
  messages: Array<{
    /** Message severity level */
    severity: 'error' | 'warning' | 'info';
    /** Line number where issue occurs */
    line: number;
    /** Column number where issue occurs */
    column: number;
    /** Human-readable message describing the issue */
    message: string;
    /** Source code evidence showing the problematic line */
    evidence: string;
    /** JSHint rule identifier */
    reason?: string;
    /** Character position in source */
    character?: number;
  }>;
}

Usage Examples:

const jshintReporter = require('plato/lib/reporters/jshint');

// Analyze with JSHint
const sourceCode = `
function badCode() {
  var unused = 1;
  undeclaredVar = 2;
  return "missing semicolon"
}
`;

const jshintOptions = {
  undef: true,      // Require variable declarations
  unused: true,     // Warn about unused variables
  asi: false        // Require semicolons
};

const jshintReport = jshintReporter.process(sourceCode, jshintOptions);

jshintReport.messages.forEach(msg => {
  console.log(`${msg.severity} at line ${msg.line}: ${msg.message}`);
  console.log(`Evidence: ${msg.evidence}`);
});

// Example output:
// error at line 3: 'unused' is defined but never used.
// error at line 4: 'undeclaredVar' is not defined.
// error at line 5: Missing semicolon.

ESLint Reporter

Integrates ESLint analysis for modern JavaScript linting with configurable rules and comprehensive error reporting.

/**
 * Run ESLint analysis on JavaScript source code
 * @param {String} source - JavaScript source code to analyze
 * @param {Object} options - ESLint configuration options and rules
 * @returns {Object} ESLint analysis report with messages and metadata
 */
function process(source, options);

Parameters:

  • source (String): JavaScript source code to analyze
  • options (Object): ESLint configuration options, rules, and environment settings

Returns: Object - ESLint analysis report

Report Structure:

interface ESLintReport {
  /** Array of ESLint messages */
  messages: Array<{
    /** Message severity level */
    severity: 'error' | 'warning';
    /** Line number where issue occurs */
    line: number;
    /** Column number where issue occurs */
    column: number;
    /** Human-readable message describing the issue */
    message: string;
    /** ESLint rule identifier that triggered the message */
    ruleId: string;
    /** End line number for multi-line issues */
    endLine?: number;
    /** End column number for multi-line issues */
    endColumn?: number;
    /** Node type that triggered the rule */
    nodeType?: string;
    /** Source code excerpt */
    source?: string;
  }>;
}

Usage Examples:

const eslintReporter = require('plato/lib/reporters/eslint');

// Analyze with ESLint
const sourceCode = `
const unusedVar = 1;

function inconsistentQuotes() {
  console.log("double quotes");
  console.log('single quotes');
  return `template literal`;
}

if(true){
  console.log("no spacing");
}
`;

const eslintOptions = {
  env: {
    es6: true,
    node: true
  },
  rules: {
    'no-unused-vars': 'error',
    'quotes': ['error', 'single'],
    'space-before-blocks': 'error',
    'keyword-spacing': 'error'
  }
};

const eslintReport = eslintReporter.process(sourceCode, eslintOptions);

eslintReport.messages.forEach(msg => {
  console.log(`${msg.severity}: ${msg.message} (${msg.ruleId})`);
  console.log(`  at line ${msg.line}, column ${msg.column}`);
});

// Example output:
// error: 'unusedVar' is defined but never used. (no-unused-vars)
//   at line 2, column 7
// error: Strings must use single quote. (quotes)
//   at line 5, column 15

Integration with Main Analysis

The reporters integrate seamlessly with Plato's main analysis workflow:

Reporter Configuration

const plato = require('plato');

// Configure analysis with multiple reporters
plato.inspect(['src/**/*.js'], 'reports', {
  // JSHint configuration
  jshint: {
    node: true,
    browser: true,
    camelcase: true,
    curly: true,
    immed: true,
    indent: 2,
    latedef: true,
    newcap: true,
    nonew: true,
    quotmark: 'single',
    undef: true,
    unused: true,
    strict: true,
    maxparams: 4,
    maxdepth: 3,
    maxcomplexity: 10
  },
  
  // ESLint configuration
  eslint: {
    env: {
      node: true,
      es6: true
    },
    extends: ['eslint:recommended'],
    rules: {
      'no-console': 'warn',
      'no-unused-vars': 'error',
      'quotes': ['error', 'single'],
      'semi': ['error', 'always']
    }
  }
}, function(reports) {
  reports.forEach(report => {
    console.log(`\n--- ${report.info.file} ---`);
    
    // Complexity metrics
    console.log(`Complexity: ${report.complexity.cyclomatic}`);
    console.log(`Maintainability: ${report.complexity.maintainability}`);
    
    // JSHint results
    if (report.jshint && report.jshint.messages.length > 0) {
      console.log(`JSHint issues: ${report.jshint.messages.length}`);
    }
    
    // ESLint results
    if (report.eslint && report.eslint.messages.length > 0) {
      console.log(`ESLint issues: ${report.eslint.messages.length}`);
    }
  });
});

Custom Reporter Integration

// Example of using reporters independently
const complexityReporter = require('plato/lib/reporters/complexity');
const jshintReporter = require('plato/lib/reporters/jshint');
const eslintReporter = require('plato/lib/reporters/eslint');
const fs = require('fs');

function analyzeFile(filePath) {
  const source = fs.readFileSync(filePath, 'utf8');
  const reportInfo = { file: filePath };
  
  // Run all analyses
  const complexity = complexityReporter.process(source, {}, reportInfo);
  const jshint = jshintReporter.process(source, { undef: true, unused: true });
  const eslint = eslintReporter.process(source, { 
    rules: { 'no-unused-vars': 'error' }
  });
  
  return {
    file: filePath,
    complexity,
    jshint,
    eslint
  };
}

// Analyze specific file
const analysis = analyzeFile('src/app.js');
console.log('Analysis complete:', analysis);

Reporter Output Integration

Reporter outputs are combined into the final analysis reports:

Combined Report Structure

// Final report structure combining all reporters
const combinedReport = {
  info: {
    file: 'src/app.js',
    fileShort: 'app.js',
    // ... other file info
  },
  
  // From complexity reporter
  complexity: {
    cyclomatic: 8,
    maintainability: 75.2,
    sloc: { physical: 120, logical: 95 },
    halstead: { /* ... */ }
  },
  
  // From JSHint reporter (if enabled)
  jshint: {
    messages: [
      { severity: 'error', line: 15, message: 'Undefined variable' }
    ]
  },
  
  // From ESLint reporter (if enabled)
  eslint: {
    messages: [
      { severity: 'warning', line: 20, ruleId: 'no-console', message: 'Unexpected console statement.' }
    ]
  }
};

Error Handling

Reporters handle various error scenarios gracefully:

Source Code Parsing Errors

// Reporters handle malformed JavaScript
const malformedCode = `
function broken() {
  if (condition {  // Missing closing parenthesis
    return true;
  }
`;

try {
  const report = complexityReporter.process(malformedCode, {}, { file: 'broken.js' });
  // Report may contain partial analysis or error information
} catch (error) {
  console.error('Analysis failed:', error.message);
}

Configuration Errors

// Reporters validate configuration options
const invalidConfig = {
  rules: {
    'nonexistent-rule': 'error'
  }
};

const report = eslintReporter.process(sourceCode, invalidConfig);
// Report will include configuration error messages

Each reporter is designed to provide useful information even when encountering errors, ensuring that the overall analysis process can continue and provide valuable insights about code quality.

Install with Tessl CLI

npx tessl i tessl/npm-plato

docs

cli-api.md

index.md

models.md

programmatic-api.md

reporters.md

utilities.md

tile.json