<commit_before>import { File } from "embark-utils";
import * as fs from "fs-extra";
import * as path from "path";
import parser, { LineColumn, Location, SourceUnit } from "solidity-parser-antlr";
import { EventLog } from "web3/types";

import { decrypt } from "./eventId";
import { Injector } from "./injector";
import { Instrumenter } from "./instrumenter";
import { InstrumentWalker } from "./instrumentWalker";
import { coverageContractsPath } from "./path";
import { Printer } from "./printer";
import { BranchType, Coverage } from "./types";

const STATEMENT_EVENT = "__StatementCoverage";
const POINT_FACTOR = 1000000000;

let id = 0;
function nextId() {
  id++;
  return id;
}

export class ContractEnhanced {
  public id: number;
  public coverage: Coverage;
  public coverageFilepath: string;
  public originalSource: string;
  public source: string;
  private ast!: SourceUnit;
  private functionsBodyLocation: {[id: number]: Location} = {};

  constructor(public filepath: string, public solcVersion: string) {
    this.id = nextId();

    // silence compiler warnings.
    this.source = this.originalSource = "";

    try {
      this.source = fs.readFileSync(filepath, "utf-8");
      this.originalSource = this.source;
      this.ast = parser.parse(this.source, {loc: true, range: true}) as SourceUnit;
    } catch (error) {
      const {line, column, message} = error.errors[0];
      console.warn(`Error on ${this.filepath}:${line}:${column}: "${message}". Could not setup for coverage.`);
    }

    this.coverageFilepath = path.join(coverageContractsPath(), this.filepath);

    this.coverage = {
      b: {},
      branchMap: {},
      code: this.originalSource,
      f: {},
      fnMap: {},
      l: {},
      path: filepath,
      s: {},
      statementMap: {},
    };
  }

  public instrument() {
    if (!this.ast) {
      return;
    }
    const instrumenter = new Instrumenter(this);
    const instrumentWalker = new InstrumentWalker(instrumenter);
    instrumentWalker.walk(this.ast);

    const injector = new Injector(this, this.solcVersion);
    instrumenter.getInjectionPoints().forEach(injector.process.bind(injector));
  }

  public save() {
    fs.ensureFileSync(this.coverageFilepath);

    if (!this.ast) {
      return fs.writeFileSync(this.coverageFilepath, this.source);
    }

    try {
      const printer = new Printer(this.ast);
      this.source = printer.print();
    } catch (err) {
      // Something might have happened with the printer. Write the original source.
      console.warn(`Error with coverage printer for ${this.filepath}. Please submit an issue with this code.`);
    } finally {
      fs.writeFileSync(this.coverageFilepath, this.source);
    }
  }

  public updateCoverage(events: EventLog[]) {
    events.filter(this.filterCoverageEvent).forEach((event) => {
      const value = parseInt(event.returnValues[0], 10);
      const {contractId, injectionPointId} = decrypt(value);

      if (contractId !== this.id) {
        return;
      }

      this.coverage.s[injectionPointId] += 1;
      const location = this.coverage.statementMap[injectionPointId];
      this.coverage.l[location.start.line] += 1;

      const fnMapId = this.findFnMapId(location);
      if (fnMapId) {
        this.coverage.f[fnMapId] += 1;
      }

      const [fnBranchId, locationId] = this.findFnBranchIdAndLocationId(location);
      if (fnBranchId) {
        this.coverage.b[fnBranchId][locationId] += 1;
      }
    });
  }

  public addStatement(location: Location) {
    const coverageId = this.getNewCoverageId(this.coverage.statementMap);
    this.coverage.statementMap[coverageId] = location;
    this.coverage.s[coverageId] = 0;
    this.coverage.l[location.start.line] = 0;
    return coverageId;
  }

  public addBranch(line: number, type: BranchType, locations: Location[]) {
    const coverageId = this.getNewCoverageId(this.coverage.branchMap);
    this.coverage.branchMap[coverageId] = {
      line,
      locations,
      type,
    };
    this.coverage.b[coverageId] = locations.map(() => 0);
    this.coverage.l[line] = 0;
    return coverageId;
  }

  public addFunction(location: Location, name: string, bodyLocation: Location) {
    const coverageId = this.getNewCoverageId(this.coverage.fnMap);
    const line = location.start.line;
    this.coverage.fnMap[coverageId] = {
      line,
      loc: location,
      decl: location,
      name,
    };
    this.coverage.f[coverageId] = 0;
    this.functionsBodyLocation[coverageId] = bodyLocation;
    return coverageId;
  }

  private getNewCoverageId(object: {[key: string]: any}) {
    const lastId = Object.keys(object).map(Number).sort((a, b) => b - a)[0] || 0;
    return lastId + 1;
  }<commit_msg>style(@embark/plugins/coverage): fix linter errors<commit_after>import {File} from "embark-utils";
import * as fs from "fs-extra";
import * as path from "path";
import parser, {LineColumn, Location, SourceUnit} from "solidity-parser-antlr";
import {EventLog} from "web3/types";

import {decrypt} from "./eventId";
import {Injector} from "./injector";
import {Instrumenter} from "./instrumenter";
import {InstrumentWalker} from "./instrumentWalker";
import {coverageContractsPath} from "./path";
import {Printer} from "./printer";
import {BranchType, Coverage} from "./types";

const STATEMENT_EVENT = "__StatementCoverage";
const POINT_FACTOR = 1000000000;

let id = 0;
function nextId() {
  id++;
  return id;
}

export class ContractEnhanced {
  public id: number;
  public coverage: Coverage;
  public coverageFilepath: string;
  public originalSource: string;
  public source: string;
  private ast!: SourceUnit;
  private functionsBodyLocation: {[id: number]: Location} = {};

  constructor(public filepath: string, public solcVersion: string) {
    this.id = nextId();

    // silence compiler warnings.
    this.source = this.originalSource = "";

    try {
      this.source = fs.readFileSync(filepath, "utf-8");
      this.originalSource = this.source;
      this.ast = parser.parse(this.source, {loc: true, range: true}) as SourceUnit;
    } catch (error) {
      const {line, column, message} = error.errors[0];
      console.warn(`Error on ${this.filepath}:${line}:${column}: "${message}". Could not setup for coverage.`);
    }

    this.coverageFilepath = path.join(coverageContractsPath(), this.filepath);

    this.coverage = {
      b: {},
      branchMap: {},
      code: this.originalSource,
      f: {},
      fnMap: {},
      l: {},
      path: filepath,
      s: {},
      statementMap: {},
    };
  }

  public instrument() {
    if (!this.ast) {
      return;
    }
    const instrumenter = new Instrumenter(this);
    const instrumentWalker = new InstrumentWalker(instrumenter);
    instrumentWalker.walk(this.ast);

    const injector = new Injector(this, this.solcVersion);
    instrumenter.getInjectionPoints().forEach(injector.process.bind(injector));
  }

  public save() {
    fs.ensureFileSync(this.coverageFilepath);

    if (!this.ast) {
      return fs.writeFileSync(this.coverageFilepath, this.source);
    }

    try {
      const printer = new Printer(this.ast);
      this.source = printer.print();
    } catch (err) {
      // Something might have happened with the printer. Write the original source.
      console.warn(`Error with coverage printer for ${this.filepath}. Please submit an issue with this code.`);
    } finally {
      fs.writeFileSync(this.coverageFilepath, this.source);
    }
  }

  public updateCoverage(events: EventLog[]) {
    events.filter(this.filterCoverageEvent).forEach((event) => {
      const value = parseInt(event.returnValues[0], 10);
      const {contractId, injectionPointId} = decrypt(value);

      if (contractId !== this.id) {
        return;
      }

      this.coverage.s[injectionPointId] += 1;
      const location = this.coverage.statementMap[injectionPointId];
      this.coverage.l[location.start.line] += 1;

      const fnMapId = this.findFnMapId(location);
      if (fnMapId) {
        this.coverage.f[fnMapId] += 1;
      }

      const [fnBranchId, locationId] = this.findFnBranchIdAndLocationId(location);
      if (fnBranchId) {
        this.coverage.b[fnBranchId][locationId] += 1;
      }
    });
  }

  public addStatement(location: Location) {
    const coverageId = this.getNewCoverageId(this.coverage.statementMap);
    this.coverage.statementMap[coverageId] = location;
    this.coverage.s[coverageId] = 0;
    this.coverage.l[location.start.line] = 0;
    return coverageId;
  }

  public addBranch(line: number, type: BranchType, locations: Location[]) {
    const coverageId = this.getNewCoverageId(this.coverage.branchMap);
    this.coverage.branchMap[coverageId] = {
      line,
      locations,
      type,
    };
    this.coverage.b[coverageId] = locations.map(() => 0);
    this.coverage.l[line] = 0;
    return coverageId;
  }

  public addFunction(location: Location, name: string, bodyLocation: Location) {
    const coverageId = this.getNewCoverageId(this.coverage.fnMap);
    const line = location.start.line;
    this.coverage.fnMap[coverageId] = {
      decl: location,
      line,
      loc: location,
      name,
    };
    this.coverage.f[coverageId] = 0;
    this.functionsBodyLocation[coverageId] = bodyLocation;
    return coverageId;
  }

  private getNewCoverageId(object: {[key: string]: any}) {
    const lastId = Object.keys(object).map(Number).sort((a, b) => b - a)[0] || 0;
    return lastId + 1;
  }
{'fraction_non_alphanumeric': 0.1349433322741235, 'fraction_numerical': 0.0061434170109098615, 'mean_word_length': 3.2996357012750455, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1212364', 'n_tokens_mistral': 3034, 'n_tokens_neox': 2936, 'n_words': 663}