parent
6e97479586
commit
bf35a216d1
@ -0,0 +1,7 @@
|
||||
import { getCityList } from 'redux/actions/getFavoriteCity';
|
||||
|
||||
describe("Actions tests", () => {
|
||||
it('should create an action with FETCH_FAVORITE_CITY type', () => {
|
||||
expect(getFavoriteCity().toEqual({type: 'FETCH_FAVORITE_CITY'}));
|
||||
})
|
||||
})
|
@ -0,0 +1 @@
|
||||
../escodegen/bin/escodegen.js
|
@ -0,0 +1 @@
|
||||
../escodegen/bin/esgenerate.js
|
@ -0,0 +1 @@
|
||||
../jest/bin/jest.js
|
@ -0,0 +1 @@
|
||||
../resolve/bin/resolve
|
@ -0,0 +1 @@
|
||||
../which/bin/which
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
# @babel/plugin-syntax-bigint
|
||||
|
||||
> Allow parsing of BigInt literals
|
||||
|
||||
See our website [@babel/plugin-syntax-bigint](https://babeljs.io/docs/en/next/babel-plugin-syntax-bigint.html) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/plugin-syntax-bigint
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/plugin-syntax-bigint --dev
|
||||
```
|
@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
|
||||
var _helperPluginUtils = require("@babel/helper-plugin-utils");
|
||||
|
||||
var _default = (0, _helperPluginUtils.declare)(api => {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
name: "syntax-bigint",
|
||||
|
||||
manipulateOptions(opts, parserOpts) {
|
||||
parserOpts.plugins.push("bigInt");
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
exports.default = _default;
|
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "@babel/plugin-syntax-bigint",
|
||||
"version": "7.8.3",
|
||||
"description": "Allow parsing of BigInt literals",
|
||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-bigint",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"keywords": [
|
||||
"babel-plugin"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.8.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
# @babel/plugin-syntax-import-meta
|
||||
|
||||
> Allow parsing of import.meta
|
||||
|
||||
See our website [@babel/plugin-syntax-import-meta](https://babeljs.io/docs/en/next/babel-plugin-syntax-import-meta.html) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/plugin-syntax-import-meta
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/plugin-syntax-import-meta --dev
|
||||
```
|
@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
|
||||
var _helperPluginUtils = require("@babel/helper-plugin-utils");
|
||||
|
||||
var _default = (0, _helperPluginUtils.declare)(api => {
|
||||
api.assertVersion(7);
|
||||
return {
|
||||
name: "syntax-import-meta",
|
||||
|
||||
manipulateOptions(opts, parserOpts) {
|
||||
parserOpts.plugins.push("importMeta");
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
exports.default = _default;
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@babel/plugin-syntax-import-meta",
|
||||
"version": "7.10.4",
|
||||
"description": "Allow parsing of import.meta",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel.git",
|
||||
"directory": "packages/babel-plugin-syntax-import-meta"
|
||||
},
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"keywords": [
|
||||
"babel-plugin"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.10.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.4"
|
||||
},
|
||||
"gitHead": "7fd40d86a0d03ff0e9c3ea16b29689945433d4df"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
@ -0,0 +1,2 @@
|
||||
# Enforce `lf` for text files (even on Windows)
|
||||
text eol=lf
|
@ -0,0 +1,250 @@
|
||||
## Next
|
||||
|
||||
- **[Breaking change]** Replace `OutModules` enum by custom compiler option `mjsModule`.
|
||||
- **[Breaking change]** Drop support for Pug, Sass, Angular & Webpack.
|
||||
- **[Feature]** Expose custom registries for each target.
|
||||
- **[Feature]** Add `dist.tscOptions` for `lib` target to override options for
|
||||
distribution builds.
|
||||
- **[Feature]** Native ESM tests with mocha.
|
||||
- **[Fix]** Disable deprecated TsLint rules from the default config
|
||||
- **[Fix]** Remove use of experimental `fs/promises` module.
|
||||
- **[Internal]** Fix continuous deployment script (stop confusing PRs to master
|
||||
with push to master)
|
||||
- **[Internal]** Update dependencies
|
||||
- **[Internal]** Fix deprecated Mocha types.
|
||||
|
||||
## 0.17.1 (2017-05-03)
|
||||
|
||||
- **[Fix]** Update dependencies, remove `std/esm` warning.
|
||||
|
||||
## 0.17.0 (2017-04-22)
|
||||
|
||||
- **[Breaking change]** Update dependencies. Use `esm` instead of `@std/esm`, update Typescript to `2.8.3`.
|
||||
- **[Fix]** Fix Node processes spawn on Windows (Mocha, Nyc)
|
||||
|
||||
## 0.16.2 (2017-02-07)
|
||||
|
||||
- **[Fix]** Fix Typedoc generation: use `tsconfig.json` generated for the lib.
|
||||
- **[Fix]** Write source map for `.mjs` files
|
||||
- **[Fix]** Copy sources to `_src` when publishing a lib (#87).
|
||||
- **[Internal]** Restore continuous deployment of documentation.
|
||||
|
||||
## 0.16.1 (2017-01-20)
|
||||
|
||||
- **[Feature]** Support `mocha` tests on `.mjs` files (using `@std/esm`). Enabled by default
|
||||
if `outModules` is configured to emit `.mjs`. **You currently need to add
|
||||
`"@std/esm": {"esm": "cjs"}` to your `package.json`.**
|
||||
|
||||
## 0.16.0 (2017-01-09)
|
||||
|
||||
- **[Breaking change]** Enable `allowSyntheticDefaultImports` and `esModuleInterop` by default
|
||||
- **[Fix]** Allow deep module imports in default Tslint rules
|
||||
- **[Fix]** Drop dependency on deprecated `gulp-util`
|
||||
- **[Internal]** Replace most custom typings by types from `@types`
|
||||
|
||||
## 0.15.8 (2017-12-05)
|
||||
|
||||
- **[Fix]** Exit with non-zero code if command tested with coverage fails
|
||||
- **[Fix]** Solve duplicated error message when using the `run` mocha task.
|
||||
- **[Fix]** Exit with non-zero code when building scripts fails.
|
||||
|
||||
## 0.15.7 (2017-11-29)
|
||||
|
||||
- **[Feature]** Add `coverage` task to `mocha` target, use it for the default task
|
||||
|
||||
## 0.15.6 (2017-11-29)
|
||||
|
||||
- **[Fix]** Fix path to source in source maps.
|
||||
- **[Fix]** Disable `number-literal-format` in default Tslint rules. It enforced uppercase for hex.
|
||||
- **[Internal]** Enable integration with Greenkeeper.
|
||||
- **[Internal]** Enable integration with Codecov
|
||||
- **[Internal]** Enable code coverage
|
||||
|
||||
## 0.15.5 (2017-11-10)
|
||||
|
||||
- **[Feature]** Enable the following TsLint rules: `no-duplicate-switch-case`, `no-implicit-dependencies`,
|
||||
`no-return-await`
|
||||
- **[Internal]** Update self-dependency `0.15.4`, this restores the README on _npm_
|
||||
- **[Internal]** Add homepage and author fields to package.json
|
||||
|
||||
## 0.15.4 (2017-11-10)
|
||||
|
||||
- **[Fix]** Add support for custom additional copy for distribution builds. [#49](https://github.com/demurgos/turbo-gulp/issues/49)
|
||||
- **[Internal]** Update self-dependency to `turbo-gulp`
|
||||
- **[Internal]** Add link to license in `README.md`
|
||||
|
||||
## 0.15.3 (2017-11-09)
|
||||
|
||||
**Rename to `turbo-gulp`**. This package was previously named `demurgos-web-build-tools`.
|
||||
This version is fully compatible: you can just change the name of your dependency.
|
||||
|
||||
## 0.15.2 (2017-11-09)
|
||||
|
||||
**The package is prepared to be renamed `turbo-gulp`.**
|
||||
This is the last version released as `demurgos-web-build-tools`.
|
||||
|
||||
- **[Feature]** Add support for watch mode for library targets.
|
||||
- **[Fix]** Disable experimental support for `*.mjs` by default.
|
||||
- **[Fix]** Do not emit duplicate TS errors
|
||||
|
||||
## 0.15.1 (2017-10-19)
|
||||
|
||||
- **[Feature]** Add experimental support for `*.mjs` files
|
||||
- **[Fix]** Fix support of releases from Continuous Deployment using Travis.
|
||||
|
||||
## 0.15.0 (2017-10-18)
|
||||
|
||||
- **[Fix]** Add error handling for git deployment.
|
||||
- **[Internal]** Enable continuous deployment of the `master` branch.
|
||||
|
||||
## 0.15.0-beta.11 (2017-08-29)
|
||||
|
||||
- **[Feature]** Add `LibTarget.dist.copySrc` option to disable copy of source files to the dist directory.
|
||||
This allows to prevent issues with missing custom typings.
|
||||
- **[Fix]** Mark `deploy` property of `LibTarget.typedoc` as optional.
|
||||
- **[Internal]** Update self-dependency to `v0.15.0-beta.10`.
|
||||
|
||||
## 0.15.0-beta.10 (2017-08-28)
|
||||
|
||||
- **[Breaking]** Update Tslint rules to use `tslint@5.7.0`.
|
||||
- **[Fix]** Set `allowJs` to false in default TSC options.
|
||||
- **[Fix]** Do not pipe output of git commands to stdout.
|
||||
- **[Internal]** Update self-dependency to `v0.15.0-beta.9`.
|
||||
|
||||
## 0.15.0-beta.9 (2017-08-28)
|
||||
|
||||
- **[Breaking]** Drop old-style `test` target.
|
||||
- **[Breaking]** Drop old-style `node` target.
|
||||
- **[Feature]** Add `mocha` target to run tests in `spec.ts` files.
|
||||
- **[Feature]** Add `node` target to build and run top-level Node applications.
|
||||
- **[Feature]** Provide `generateNodeTasks`, `generateLibTasks` and `generateMochaTasks` functions.
|
||||
They create the tasks but do not register them.
|
||||
- **[Fix]** Run `clean` before `dist`, if defined.
|
||||
- **[Fix]** Run `dist` before `publish`.
|
||||
|
||||
## 0.15.0-beta.8 (2017-08-26)
|
||||
|
||||
- **[Fix]** Remove auth token and registry options for `<lib>:dist:publish`. It is better served
|
||||
by configuring the environment appropriately.
|
||||
|
||||
## 0.15.0-beta.7 (2017-08-26)
|
||||
|
||||
- **[Feature]** Add `clean` task to `lib` targets.
|
||||
- **[Fix]** Ensure that `gitHead` is defined when publishing a package to npm.
|
||||
|
||||
## 0.15.0-beta.6 (2017-08-22)
|
||||
|
||||
- **[Feature]** Add support for Typedoc deployment to a remote git branch (such as `gh-pages`)
|
||||
- **[Feature]** Add support for `copy` tasks in new library target.
|
||||
- **[Fix]** Resolve absolute paths when compiling scripts with custom typings.
|
||||
|
||||
## 0.15.0-beta.5 (2017-08-14)
|
||||
|
||||
- **[Fix]** Fix package entry for the main module.
|
||||
|
||||
## 0.15.0-beta.4 (2017-08-14)
|
||||
|
||||
- **[Breaking]** Drop ES5 build exposed to browsers with the `browser` field in `package.json`.
|
||||
- **[Feature]** Introduce first new-style target (`LibTarget`). it supports typedoc generation, dev builds and
|
||||
simple distribution.
|
||||
|
||||
## 0.15.0-beta.3 (2017-08-11)
|
||||
|
||||
- **[Breaking]** Update default lib target to use target-specific `srcDir`.
|
||||
- **[Feature]** Allow to complete `srcDir` in target.
|
||||
- **[Feature]** Add experimental library distribution supporting deep requires.
|
||||
|
||||
## 0.15.0-beta.2 (2017-08-10)
|
||||
|
||||
- **[Fix]** Default to CommonJS for project tsconfig.json
|
||||
- **[Fix]** Add Typescript configuration for default project.
|
||||
- **[Internal]** Update self-dependency to `0.15.0-beta.1`.
|
||||
|
||||
## 0.15.0-beta.1 (2017-08-09)
|
||||
|
||||
- **[Feature]** Support typed TSLint rules.
|
||||
- **[Internal]** Update gulpfile.ts to use build tools `0.15.0-beta.0`.
|
||||
- **[Fix]** Fix regressions caused by `0.15.0-beta.0` (missing type definition).
|
||||
|
||||
## 0.15.0-beta.0 (2017-08-09)
|
||||
|
||||
- **[Breaking]** Expose option interfaces directly in the main module instead of the `config` namespace.
|
||||
- **[Breaking]** Rename `DEFAULT_PROJECT_OPTIONS` to `DEFAULT_PROJECT`.
|
||||
- **[Feature]** Emit project-wide `tsconfig.json`.
|
||||
- **[Internal]** Convert gulpfile to Typescript, use `ts-node` to run it.
|
||||
- **[Internal]** Update dependencies
|
||||
|
||||
## 0.14.3 (2017-07-16)
|
||||
|
||||
- **[Feature]** Add `:lint:fix` project task to fix some lint errors.
|
||||
|
||||
## 0.14.2 (2017-07-10)
|
||||
|
||||
- **[Internal]** Update dependencies: add `package-lock.json` and update `tslint`.
|
||||
|
||||
## 0.14.1 (2017-06-17)
|
||||
|
||||
- **[Internal]** Update dependencies.
|
||||
- **[Internal]** Drop dependency on _Bluebird_.
|
||||
- **[Internal]** Drop dependency on _typings_.
|
||||
|
||||
## 0.14.0 (2017-05-10)
|
||||
|
||||
- **[Breaking]** Enforce trailing commas by default for multiline objects
|
||||
- **[Feature]** Allow bump from either `master` or a branch with the same name as the tag (exampel: `v1.2.3`)
|
||||
- **[Feature]** Support TSLint 8, allow to extend the default rules
|
||||
- **[Patch]** Allow mergeable namespaces
|
||||
|
||||
# 0.13.1
|
||||
|
||||
- **[Patch]** Allow namespaces in the default TS-Lint config
|
||||
|
||||
# 0.13.0
|
||||
|
||||
- **[Breaking]** Major overhaul of the angular target. The server build no longer depends on the client.
|
||||
- **[Breaking]** Update to `gulp@4` (from `gulp@3`)
|
||||
- **[Breaking]** Update to `tslint@7` (from `tslint@6`), add stricter default rules
|
||||
- **[Breaking]** Update signature of targetGenerators and project tasks: it only uses
|
||||
`ProjectOptions` and `Target` now, the additional options are embedded in those two objects.
|
||||
- **[Breaking]** Remove `:install`, `:instal:npm` and `:install:typings`. Use the `prepare` script in
|
||||
your `package.json` file instead.
|
||||
- Add `:tslint.json` project task to generate configuration for `tslint`
|
||||
- Add first class support for processing of `pug` and `sass` files, similar to `copy`
|
||||
- Implement end-to-end tests
|
||||
- Enable `emitDecoratorMetadata` in default typescript options.
|
||||
- Allow configuration of `:lint` with the `tslintOptions` property of the project configuration.
|
||||
- Add `<target>:watch` tasks for incremental builds.
|
||||
|
||||
# 0.12.3
|
||||
|
||||
- Support `templateUrl` and `styleUrls` in angular modules.
|
||||
|
||||
# 0.12.2
|
||||
|
||||
- Add `<target>:build:copy` task. It copies user-defined files.
|
||||
|
||||
# 0.12.1
|
||||
|
||||
- Fix `<target>:watch` task.
|
||||
|
||||
# 0.12.0
|
||||
|
||||
- **[Breaking]**: Change naming convention for tasks. The names primary part is
|
||||
the target, then the action (`lib:build` instead of `build:lib`) to group
|
||||
the tasks per target.
|
||||
- **[Breaking]**: Use `typeRoots` instead of `definitions` in configuration to
|
||||
specify Typescript definition files.
|
||||
- Generate `tsconfig.json` file (mainly for editors)
|
||||
- Implement the `test` target to run unit-tests with `mocha`.
|
||||
|
||||
# 0.11.2
|
||||
|
||||
- Target `angular`: Add `build:<target>:assets:sass` for `.scss` files (Sassy CSS)
|
||||
|
||||
# 0.11.1
|
||||
|
||||
- Rename project to `web-build-tools` (`demurgos-web-build-tools` on _npm_)
|
||||
- Target `angular`: Add `build:<target>:assets`, `build:<target>:pug` and `build:<target>:static`.
|
||||
- Update `gulp-typescript`: solve error message during compilation
|
||||
- Targets `node` and `angular`: `build:<target>:scripts` now include in-lined source maps
|
||||
- Target `node`: `watch:<target>` to support incremental builds
|
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2015-2017 Charles Samborski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,14 @@
|
||||
Copyright (c) 2017, Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice
|
||||
appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
|
||||
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
@ -0,0 +1,11 @@
|
||||
# V8 Coverage
|
||||
|
||||
[](https://www.npmjs.com/package/@c88/v8-coverage)
|
||||
[](https://github.com/demurgos/v8-coverage)
|
||||
[](https://travis-ci.org/demurgos/v8-coverage)
|
||||
[](https://ci.appveyor.com/project/demurgos/v8-coverage)
|
||||
[](https://codecov.io/gh/demurgos/v8-coverage)
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](./LICENSE.md)
|
@ -0,0 +1,250 @@
|
||||
## Next
|
||||
|
||||
- **[Breaking change]** Replace `OutModules` enum by custom compiler option `mjsModule`.
|
||||
- **[Breaking change]** Drop support for Pug, Sass, Angular & Webpack.
|
||||
- **[Feature]** Expose custom registries for each target.
|
||||
- **[Feature]** Add `dist.tscOptions` for `lib` target to override options for
|
||||
distribution builds.
|
||||
- **[Feature]** Native ESM tests with mocha.
|
||||
- **[Fix]** Disable deprecated TsLint rules from the default config
|
||||
- **[Fix]** Remove use of experimental `fs/promises` module.
|
||||
- **[Internal]** Fix continuous deployment script (stop confusing PRs to master
|
||||
with push to master)
|
||||
- **[Internal]** Update dependencies
|
||||
- **[Internal]** Fix deprecated Mocha types.
|
||||
|
||||
## 0.17.1 (2017-05-03)
|
||||
|
||||
- **[Fix]** Update dependencies, remove `std/esm` warning.
|
||||
|
||||
## 0.17.0 (2017-04-22)
|
||||
|
||||
- **[Breaking change]** Update dependencies. Use `esm` instead of `@std/esm`, update Typescript to `2.8.3`.
|
||||
- **[Fix]** Fix Node processes spawn on Windows (Mocha, Nyc)
|
||||
|
||||
## 0.16.2 (2017-02-07)
|
||||
|
||||
- **[Fix]** Fix Typedoc generation: use `tsconfig.json` generated for the lib.
|
||||
- **[Fix]** Write source map for `.mjs` files
|
||||
- **[Fix]** Copy sources to `_src` when publishing a lib (#87).
|
||||
- **[Internal]** Restore continuous deployment of documentation.
|
||||
|
||||
## 0.16.1 (2017-01-20)
|
||||
|
||||
- **[Feature]** Support `mocha` tests on `.mjs` files (using `@std/esm`). Enabled by default
|
||||
if `outModules` is configured to emit `.mjs`. **You currently need to add
|
||||
`"@std/esm": {"esm": "cjs"}` to your `package.json`.**
|
||||
|
||||
## 0.16.0 (2017-01-09)
|
||||
|
||||
- **[Breaking change]** Enable `allowSyntheticDefaultImports` and `esModuleInterop` by default
|
||||
- **[Fix]** Allow deep module imports in default Tslint rules
|
||||
- **[Fix]** Drop dependency on deprecated `gulp-util`
|
||||
- **[Internal]** Replace most custom typings by types from `@types`
|
||||
|
||||
## 0.15.8 (2017-12-05)
|
||||
|
||||
- **[Fix]** Exit with non-zero code if command tested with coverage fails
|
||||
- **[Fix]** Solve duplicated error message when using the `run` mocha task.
|
||||
- **[Fix]** Exit with non-zero code when building scripts fails.
|
||||
|
||||
## 0.15.7 (2017-11-29)
|
||||
|
||||
- **[Feature]** Add `coverage` task to `mocha` target, use it for the default task
|
||||
|
||||
## 0.15.6 (2017-11-29)
|
||||
|
||||
- **[Fix]** Fix path to source in source maps.
|
||||
- **[Fix]** Disable `number-literal-format` in default Tslint rules. It enforced uppercase for hex.
|
||||
- **[Internal]** Enable integration with Greenkeeper.
|
||||
- **[Internal]** Enable integration with Codecov
|
||||
- **[Internal]** Enable code coverage
|
||||
|
||||
## 0.15.5 (2017-11-10)
|
||||
|
||||
- **[Feature]** Enable the following TsLint rules: `no-duplicate-switch-case`, `no-implicit-dependencies`,
|
||||
`no-return-await`
|
||||
- **[Internal]** Update self-dependency `0.15.4`, this restores the README on _npm_
|
||||
- **[Internal]** Add homepage and author fields to package.json
|
||||
|
||||
## 0.15.4 (2017-11-10)
|
||||
|
||||
- **[Fix]** Add support for custom additional copy for distribution builds. [#49](https://github.com/demurgos/turbo-gulp/issues/49)
|
||||
- **[Internal]** Update self-dependency to `turbo-gulp`
|
||||
- **[Internal]** Add link to license in `README.md`
|
||||
|
||||
## 0.15.3 (2017-11-09)
|
||||
|
||||
**Rename to `turbo-gulp`**. This package was previously named `demurgos-web-build-tools`.
|
||||
This version is fully compatible: you can just change the name of your dependency.
|
||||
|
||||
## 0.15.2 (2017-11-09)
|
||||
|
||||
**The package is prepared to be renamed `turbo-gulp`.**
|
||||
This is the last version released as `demurgos-web-build-tools`.
|
||||
|
||||
- **[Feature]** Add support for watch mode for library targets.
|
||||
- **[Fix]** Disable experimental support for `*.mjs` by default.
|
||||
- **[Fix]** Do not emit duplicate TS errors
|
||||
|
||||
## 0.15.1 (2017-10-19)
|
||||
|
||||
- **[Feature]** Add experimental support for `*.mjs` files
|
||||
- **[Fix]** Fix support of releases from Continuous Deployment using Travis.
|
||||
|
||||
## 0.15.0 (2017-10-18)
|
||||
|
||||
- **[Fix]** Add error handling for git deployment.
|
||||
- **[Internal]** Enable continuous deployment of the `master` branch.
|
||||
|
||||
## 0.15.0-beta.11 (2017-08-29)
|
||||
|
||||
- **[Feature]** Add `LibTarget.dist.copySrc` option to disable copy of source files to the dist directory.
|
||||
This allows to prevent issues with missing custom typings.
|
||||
- **[Fix]** Mark `deploy` property of `LibTarget.typedoc` as optional.
|
||||
- **[Internal]** Update self-dependency to `v0.15.0-beta.10`.
|
||||
|
||||
## 0.15.0-beta.10 (2017-08-28)
|
||||
|
||||
- **[Breaking]** Update Tslint rules to use `tslint@5.7.0`.
|
||||
- **[Fix]** Set `allowJs` to false in default TSC options.
|
||||
- **[Fix]** Do not pipe output of git commands to stdout.
|
||||
- **[Internal]** Update self-dependency to `v0.15.0-beta.9`.
|
||||
|
||||
## 0.15.0-beta.9 (2017-08-28)
|
||||
|
||||
- **[Breaking]** Drop old-style `test` target.
|
||||
- **[Breaking]** Drop old-style `node` target.
|
||||
- **[Feature]** Add `mocha` target to run tests in `spec.ts` files.
|
||||
- **[Feature]** Add `node` target to build and run top-level Node applications.
|
||||
- **[Feature]** Provide `generateNodeTasks`, `generateLibTasks` and `generateMochaTasks` functions.
|
||||
They create the tasks but do not register them.
|
||||
- **[Fix]** Run `clean` before `dist`, if defined.
|
||||
- **[Fix]** Run `dist` before `publish`.
|
||||
|
||||
## 0.15.0-beta.8 (2017-08-26)
|
||||
|
||||
- **[Fix]** Remove auth token and registry options for `<lib>:dist:publish`. It is better served
|
||||
by configuring the environment appropriately.
|
||||
|
||||
## 0.15.0-beta.7 (2017-08-26)
|
||||
|
||||
- **[Feature]** Add `clean` task to `lib` targets.
|
||||
- **[Fix]** Ensure that `gitHead` is defined when publishing a package to npm.
|
||||
|
||||
## 0.15.0-beta.6 (2017-08-22)
|
||||
|
||||
- **[Feature]** Add support for Typedoc deployment to a remote git branch (such as `gh-pages`)
|
||||
- **[Feature]** Add support for `copy` tasks in new library target.
|
||||
- **[Fix]** Resolve absolute paths when compiling scripts with custom typings.
|
||||
|
||||
## 0.15.0-beta.5 (2017-08-14)
|
||||
|
||||
- **[Fix]** Fix package entry for the main module.
|
||||
|
||||
## 0.15.0-beta.4 (2017-08-14)
|
||||
|
||||
- **[Breaking]** Drop ES5 build exposed to browsers with the `browser` field in `package.json`.
|
||||
- **[Feature]** Introduce first new-style target (`LibTarget`). it supports typedoc generation, dev builds and
|
||||
simple distribution.
|
||||
|
||||
## 0.15.0-beta.3 (2017-08-11)
|
||||
|
||||
- **[Breaking]** Update default lib target to use target-specific `srcDir`.
|
||||
- **[Feature]** Allow to complete `srcDir` in target.
|
||||
- **[Feature]** Add experimental library distribution supporting deep requires.
|
||||
|
||||
## 0.15.0-beta.2 (2017-08-10)
|
||||
|
||||
- **[Fix]** Default to CommonJS for project tsconfig.json
|
||||
- **[Fix]** Add Typescript configuration for default project.
|
||||
- **[Internal]** Update self-dependency to `0.15.0-beta.1`.
|
||||
|
||||
## 0.15.0-beta.1 (2017-08-09)
|
||||
|
||||
- **[Feature]** Support typed TSLint rules.
|
||||
- **[Internal]** Update gulpfile.ts to use build tools `0.15.0-beta.0`.
|
||||
- **[Fix]** Fix regressions caused by `0.15.0-beta.0` (missing type definition).
|
||||
|
||||
## 0.15.0-beta.0 (2017-08-09)
|
||||
|
||||
- **[Breaking]** Expose option interfaces directly in the main module instead of the `config` namespace.
|
||||
- **[Breaking]** Rename `DEFAULT_PROJECT_OPTIONS` to `DEFAULT_PROJECT`.
|
||||
- **[Feature]** Emit project-wide `tsconfig.json`.
|
||||
- **[Internal]** Convert gulpfile to Typescript, use `ts-node` to run it.
|
||||
- **[Internal]** Update dependencies
|
||||
|
||||
## 0.14.3 (2017-07-16)
|
||||
|
||||
- **[Feature]** Add `:lint:fix` project task to fix some lint errors.
|
||||
|
||||
## 0.14.2 (2017-07-10)
|
||||
|
||||
- **[Internal]** Update dependencies: add `package-lock.json` and update `tslint`.
|
||||
|
||||
## 0.14.1 (2017-06-17)
|
||||
|
||||
- **[Internal]** Update dependencies.
|
||||
- **[Internal]** Drop dependency on _Bluebird_.
|
||||
- **[Internal]** Drop dependency on _typings_.
|
||||
|
||||
## 0.14.0 (2017-05-10)
|
||||
|
||||
- **[Breaking]** Enforce trailing commas by default for multiline objects
|
||||
- **[Feature]** Allow bump from either `master` or a branch with the same name as the tag (exampel: `v1.2.3`)
|
||||
- **[Feature]** Support TSLint 8, allow to extend the default rules
|
||||
- **[Patch]** Allow mergeable namespaces
|
||||
|
||||
# 0.13.1
|
||||
|
||||
- **[Patch]** Allow namespaces in the default TS-Lint config
|
||||
|
||||
# 0.13.0
|
||||
|
||||
- **[Breaking]** Major overhaul of the angular target. The server build no longer depends on the client.
|
||||
- **[Breaking]** Update to `gulp@4` (from `gulp@3`)
|
||||
- **[Breaking]** Update to `tslint@7` (from `tslint@6`), add stricter default rules
|
||||
- **[Breaking]** Update signature of targetGenerators and project tasks: it only uses
|
||||
`ProjectOptions` and `Target` now, the additional options are embedded in those two objects.
|
||||
- **[Breaking]** Remove `:install`, `:instal:npm` and `:install:typings`. Use the `prepare` script in
|
||||
your `package.json` file instead.
|
||||
- Add `:tslint.json` project task to generate configuration for `tslint`
|
||||
- Add first class support for processing of `pug` and `sass` files, similar to `copy`
|
||||
- Implement end-to-end tests
|
||||
- Enable `emitDecoratorMetadata` in default typescript options.
|
||||
- Allow configuration of `:lint` with the `tslintOptions` property of the project configuration.
|
||||
- Add `<target>:watch` tasks for incremental builds.
|
||||
|
||||
# 0.12.3
|
||||
|
||||
- Support `templateUrl` and `styleUrls` in angular modules.
|
||||
|
||||
# 0.12.2
|
||||
|
||||
- Add `<target>:build:copy` task. It copies user-defined files.
|
||||
|
||||
# 0.12.1
|
||||
|
||||
- Fix `<target>:watch` task.
|
||||
|
||||
# 0.12.0
|
||||
|
||||
- **[Breaking]**: Change naming convention for tasks. The names primary part is
|
||||
the target, then the action (`lib:build` instead of `build:lib`) to group
|
||||
the tasks per target.
|
||||
- **[Breaking]**: Use `typeRoots` instead of `definitions` in configuration to
|
||||
specify Typescript definition files.
|
||||
- Generate `tsconfig.json` file (mainly for editors)
|
||||
- Implement the `test` target to run unit-tests with `mocha`.
|
||||
|
||||
# 0.11.2
|
||||
|
||||
- Target `angular`: Add `build:<target>:assets:sass` for `.scss` files (Sassy CSS)
|
||||
|
||||
# 0.11.1
|
||||
|
||||
- Rename project to `web-build-tools` (`demurgos-web-build-tools` on _npm_)
|
||||
- Target `angular`: Add `build:<target>:assets`, `build:<target>:pug` and `build:<target>:static`.
|
||||
- Update `gulp-typescript`: solve error message during compilation
|
||||
- Targets `node` and `angular`: `build:<target>:scripts` now include in-lined source maps
|
||||
- Target `node`: `watch:<target>` to support incremental builds
|
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2015-2017 Charles Samborski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,11 @@
|
||||
# V8 Coverage
|
||||
|
||||
[](https://www.npmjs.com/package/@c88/v8-coverage)
|
||||
[](https://github.com/demurgos/v8-coverage)
|
||||
[](https://travis-ci.org/demurgos/v8-coverage)
|
||||
[](https://ci.appveyor.com/project/demurgos/v8-coverage)
|
||||
[](https://codecov.io/gh/demurgos/v8-coverage)
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](./LICENSE.md)
|
@ -0,0 +1,146 @@
|
||||
import { compareRangeCovs } from "./compare";
|
||||
import { RangeCov } from "./types";
|
||||
|
||||
interface ReadonlyRangeTree {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
readonly count: number;
|
||||
readonly children: ReadonlyRangeTree[];
|
||||
}
|
||||
|
||||
export function emitForest(trees: ReadonlyArray<ReadonlyRangeTree>): string {
|
||||
return emitForestLines(trees).join("\n");
|
||||
}
|
||||
|
||||
export function emitForestLines(trees: ReadonlyArray<ReadonlyRangeTree>): string[] {
|
||||
const colMap: Map<number, number> = getColMap(trees);
|
||||
const header: string = emitOffsets(colMap);
|
||||
return [header, ...trees.map(tree => emitTree(tree, colMap).join("\n"))];
|
||||
}
|
||||
|
||||
function getColMap(trees: Iterable<ReadonlyRangeTree>): Map<number, number> {
|
||||
const eventSet: Set<number> = new Set();
|
||||
for (const tree of trees) {
|
||||
const stack: ReadonlyRangeTree[] = [tree];
|
||||
while (stack.length > 0) {
|
||||
const cur: ReadonlyRangeTree = stack.pop()!;
|
||||
eventSet.add(cur.start);
|
||||
eventSet.add(cur.end);
|
||||
for (const child of cur.children) {
|
||||
stack.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
const events: number[] = [...eventSet];
|
||||
events.sort((a, b) => a - b);
|
||||
let maxDigits: number = 1;
|
||||
for (const event of events) {
|
||||
maxDigits = Math.max(maxDigits, event.toString(10).length);
|
||||
}
|
||||
const colWidth: number = maxDigits + 3;
|
||||
const colMap: Map<number, number> = new Map();
|
||||
for (const [i, event] of events.entries()) {
|
||||
colMap.set(event, i * colWidth);
|
||||
}
|
||||
return colMap;
|
||||
}
|
||||
|
||||
function emitTree(tree: ReadonlyRangeTree, colMap: Map<number, number>): string[] {
|
||||
const layers: ReadonlyRangeTree[][] = [];
|
||||
let nextLayer: ReadonlyRangeTree[] = [tree];
|
||||
while (nextLayer.length > 0) {
|
||||
const layer: ReadonlyRangeTree[] = nextLayer;
|
||||
layers.push(layer);
|
||||
nextLayer = [];
|
||||
for (const node of layer) {
|
||||
for (const child of node.children) {
|
||||
nextLayer.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return layers.map(layer => emitTreeLayer(layer, colMap));
|
||||
}
|
||||
|
||||
export function parseFunctionRanges(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
||||
const result: RangeCov[] = [];
|
||||
for (const line of text.split("\n")) {
|
||||
for (const range of parseTreeLayer(line, offsetMap)) {
|
||||
result.push(range);
|
||||
}
|
||||
}
|
||||
result.sort(compareRangeCovs);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param layer Sorted list of disjoint trees.
|
||||
* @param colMap
|
||||
*/
|
||||
function emitTreeLayer(layer: ReadonlyRangeTree[], colMap: Map<number, number>): string {
|
||||
const line: string[] = [];
|
||||
let curIdx: number = 0;
|
||||
for (const {start, end, count} of layer) {
|
||||
const startIdx: number = colMap.get(start)!;
|
||||
const endIdx: number = colMap.get(end)!;
|
||||
if (startIdx > curIdx) {
|
||||
line.push(" ".repeat(startIdx - curIdx));
|
||||
}
|
||||
line.push(emitRange(count, endIdx - startIdx));
|
||||
curIdx = endIdx;
|
||||
}
|
||||
return line.join("");
|
||||
}
|
||||
|
||||
function parseTreeLayer(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
||||
const result: RangeCov[] = [];
|
||||
const regex: RegExp = /\[(\d+)-*\)/gs;
|
||||
while (true) {
|
||||
const match: RegExpMatchArray | null = regex.exec(text);
|
||||
if (match === null) {
|
||||
break;
|
||||
}
|
||||
const startIdx: number = match.index!;
|
||||
const endIdx: number = startIdx + match[0].length;
|
||||
const count: number = parseInt(match[1], 10);
|
||||
const startOffset: number | undefined = offsetMap.get(startIdx);
|
||||
const endOffset: number | undefined = offsetMap.get(endIdx);
|
||||
if (startOffset === undefined || endOffset === undefined) {
|
||||
throw new Error(`Invalid offsets for: ${JSON.stringify(text)}`);
|
||||
}
|
||||
result.push({startOffset, endOffset, count});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function emitRange(count: number, len: number): string {
|
||||
const rangeStart: string = `[${count.toString(10)}`;
|
||||
const rangeEnd: string = ")";
|
||||
const hyphensLen: number = len - (rangeStart.length + rangeEnd.length);
|
||||
const hyphens: string = "-".repeat(Math.max(0, hyphensLen));
|
||||
return `${rangeStart}${hyphens}${rangeEnd}`;
|
||||
}
|
||||
|
||||
function emitOffsets(colMap: Map<number, number>): string {
|
||||
let line: string = "";
|
||||
for (const [event, col] of colMap) {
|
||||
if (line.length < col) {
|
||||
line += " ".repeat(col - line.length);
|
||||
}
|
||||
line += event.toString(10);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
export function parseOffsets(text: string): Map<number, number> {
|
||||
const result: Map<number, number> = new Map();
|
||||
const regex: RegExp = /\d+/gs;
|
||||
while (true) {
|
||||
const match: RegExpExecArray | null = regex.exec(text);
|
||||
if (match === null) {
|
||||
break;
|
||||
}
|
||||
result.set(match.index, parseInt(match[0], 10));
|
||||
}
|
||||
return result;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import { FunctionCov, ProcessCov, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a process coverage.
|
||||
*
|
||||
* @param processCov Process coverage to clone.
|
||||
* @return Cloned process coverage.
|
||||
*/
|
||||
export function cloneProcessCov(processCov: Readonly<ProcessCov>): ProcessCov {
|
||||
const result: ScriptCov[] = [];
|
||||
for (const scriptCov of processCov.result) {
|
||||
result.push(cloneScriptCov(scriptCov));
|
||||
}
|
||||
|
||||
return {
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a script coverage.
|
||||
*
|
||||
* @param scriptCov Script coverage to clone.
|
||||
* @return Cloned script coverage.
|
||||
*/
|
||||
export function cloneScriptCov(scriptCov: Readonly<ScriptCov>): ScriptCov {
|
||||
const functions: FunctionCov[] = [];
|
||||
for (const functionCov of scriptCov.functions) {
|
||||
functions.push(cloneFunctionCov(functionCov));
|
||||
}
|
||||
|
||||
return {
|
||||
scriptId: scriptCov.scriptId,
|
||||
url: scriptCov.url,
|
||||
functions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param functionCov Function coverage to clone.
|
||||
* @return Cloned function coverage.
|
||||
*/
|
||||
export function cloneFunctionCov(functionCov: Readonly<FunctionCov>): FunctionCov {
|
||||
const ranges: RangeCov[] = [];
|
||||
for (const rangeCov of functionCov.ranges) {
|
||||
ranges.push(cloneRangeCov(rangeCov));
|
||||
}
|
||||
|
||||
return {
|
||||
functionName: functionCov.functionName,
|
||||
ranges,
|
||||
isBlockCoverage: functionCov.isBlockCoverage,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param rangeCov Range coverage to clone.
|
||||
* @return Cloned range coverage.
|
||||
*/
|
||||
export function cloneRangeCov(rangeCov: Readonly<RangeCov>): RangeCov {
|
||||
return {
|
||||
startOffset: rangeCov.startOffset,
|
||||
endOffset: rangeCov.endOffset,
|
||||
count: rangeCov.count,
|
||||
};
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import { FunctionCov, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Compares two script coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of their `url` value (alphabetical sort).
|
||||
*/
|
||||
export function compareScriptCovs(a: Readonly<ScriptCov>, b: Readonly<ScriptCov>): number {
|
||||
if (a.url === b.url) {
|
||||
return 0;
|
||||
} else if (a.url < b.url) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two function coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of the root ranges.
|
||||
*/
|
||||
export function compareFunctionCovs(a: Readonly<FunctionCov>, b: Readonly<FunctionCov>): number {
|
||||
return compareRangeCovs(a.ranges[0], b.ranges[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two range coverages.
|
||||
*
|
||||
* The ranges are first ordered by ascending `startOffset` and then by
|
||||
* descending `endOffset`.
|
||||
* This corresponds to a pre-order tree traversal.
|
||||
*/
|
||||
export function compareRangeCovs(a: Readonly<RangeCov>, b: Readonly<RangeCov>): number {
|
||||
if (a.startOffset !== b.startOffset) {
|
||||
return a.startOffset - b.startOffset;
|
||||
} else {
|
||||
return b.endOffset - a.endOffset;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export { emitForest, emitForestLines, parseFunctionRanges, parseOffsets } from "./ascii";
|
||||
export { cloneFunctionCov, cloneProcessCov, cloneScriptCov, cloneRangeCov } from "./clone";
|
||||
export { compareScriptCovs, compareFunctionCovs, compareRangeCovs } from "./compare";
|
||||
export { mergeFunctionCovs, mergeProcessCovs, mergeScriptCovs } from "./merge";
|
||||
export { RangeTree } from "./range-tree";
|
||||
export { ProcessCov, ScriptCov, FunctionCov, RangeCov } from "./types";
|
@ -0,0 +1,343 @@
|
||||
import {
|
||||
deepNormalizeScriptCov,
|
||||
normalizeFunctionCov,
|
||||
normalizeProcessCov,
|
||||
normalizeRangeTree,
|
||||
normalizeScriptCov,
|
||||
} from "./normalize";
|
||||
import { RangeTree } from "./range-tree";
|
||||
import { FunctionCov, ProcessCov, Range, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Merges a list of process coverages.
|
||||
*
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param processCovs Process coverages to merge.
|
||||
* @return Merged process coverage.
|
||||
*/
|
||||
export function mergeProcessCovs(processCovs: ReadonlyArray<ProcessCov>): ProcessCov {
|
||||
if (processCovs.length === 0) {
|
||||
return {result: []};
|
||||
}
|
||||
|
||||
const urlToScripts: Map<string, ScriptCov[]> = new Map();
|
||||
for (const processCov of processCovs) {
|
||||
for (const scriptCov of processCov.result) {
|
||||
let scriptCovs: ScriptCov[] | undefined = urlToScripts.get(scriptCov.url);
|
||||
if (scriptCovs === undefined) {
|
||||
scriptCovs = [];
|
||||
urlToScripts.set(scriptCov.url, scriptCovs);
|
||||
}
|
||||
scriptCovs.push(scriptCov);
|
||||
}
|
||||
}
|
||||
|
||||
const result: ScriptCov[] = [];
|
||||
for (const scripts of urlToScripts.values()) {
|
||||
// assert: `scripts.length > 0`
|
||||
result.push(mergeScriptCovs(scripts)!);
|
||||
}
|
||||
const merged: ProcessCov = {result};
|
||||
|
||||
normalizeProcessCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a list of matching script coverages.
|
||||
*
|
||||
* Scripts are matching if they have the same `url`.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param scriptCovs Process coverages to merge.
|
||||
* @return Merged script coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export function mergeScriptCovs(scriptCovs: ReadonlyArray<ScriptCov>): ScriptCov | undefined {
|
||||
if (scriptCovs.length === 0) {
|
||||
return undefined;
|
||||
} else if (scriptCovs.length === 1) {
|
||||
const merged: ScriptCov = scriptCovs[0];
|
||||
deepNormalizeScriptCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
const first: ScriptCov = scriptCovs[0];
|
||||
const scriptId: string = first.scriptId;
|
||||
const url: string = first.url;
|
||||
|
||||
const rangeToFuncs: Map<string, FunctionCov[]> = new Map();
|
||||
for (const scriptCov of scriptCovs) {
|
||||
for (const funcCov of scriptCov.functions) {
|
||||
const rootRange: string = stringifyFunctionRootRange(funcCov);
|
||||
let funcCovs: FunctionCov[] | undefined = rangeToFuncs.get(rootRange);
|
||||
|
||||
if (funcCovs === undefined ||
|
||||
// if the entry in rangeToFuncs is function-level granularity and
|
||||
// the new coverage is block-level, prefer block-level.
|
||||
(!funcCovs[0].isBlockCoverage && funcCov.isBlockCoverage)) {
|
||||
funcCovs = [];
|
||||
rangeToFuncs.set(rootRange, funcCovs);
|
||||
} else if (funcCovs[0].isBlockCoverage && !funcCov.isBlockCoverage) {
|
||||
// if the entry in rangeToFuncs is block-level granularity, we should
|
||||
// not append function level granularity.
|
||||
continue;
|
||||
}
|
||||
funcCovs.push(funcCov);
|
||||
}
|
||||
}
|
||||
|
||||
const functions: FunctionCov[] = [];
|
||||
for (const funcCovs of rangeToFuncs.values()) {
|
||||
// assert: `funcCovs.length > 0`
|
||||
functions.push(mergeFunctionCovs(funcCovs)!);
|
||||
}
|
||||
|
||||
const merged: ScriptCov = {scriptId, url, functions};
|
||||
normalizeScriptCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the root range of the function.
|
||||
*
|
||||
* This string can be used to match function with same root range.
|
||||
* The string is derived from the start and end offsets of the root range of
|
||||
* the function.
|
||||
* This assumes that `ranges` is non-empty (true for valid function coverages).
|
||||
*
|
||||
* @param funcCov Function coverage with the range to stringify
|
||||
* @internal
|
||||
*/
|
||||
function stringifyFunctionRootRange(funcCov: Readonly<FunctionCov>): string {
|
||||
const rootRange: RangeCov = funcCov.ranges[0];
|
||||
return `${rootRange.startOffset.toString(10)};${rootRange.endOffset.toString(10)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a list of matching function coverages.
|
||||
*
|
||||
* Functions are matching if their root ranges have the same span.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param funcCovs Function coverages to merge.
|
||||
* @return Merged function coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export function mergeFunctionCovs(funcCovs: ReadonlyArray<FunctionCov>): FunctionCov | undefined {
|
||||
if (funcCovs.length === 0) {
|
||||
return undefined;
|
||||
} else if (funcCovs.length === 1) {
|
||||
const merged: FunctionCov = funcCovs[0];
|
||||
normalizeFunctionCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
const functionName: string = funcCovs[0].functionName;
|
||||
|
||||
const trees: RangeTree[] = [];
|
||||
for (const funcCov of funcCovs) {
|
||||
// assert: `fn.ranges.length > 0`
|
||||
// assert: `fn.ranges` is sorted
|
||||
trees.push(RangeTree.fromSortedRanges(funcCov.ranges)!);
|
||||
}
|
||||
|
||||
// assert: `trees.length > 0`
|
||||
const mergedTree: RangeTree = mergeRangeTrees(trees)!;
|
||||
normalizeRangeTree(mergedTree);
|
||||
const ranges: RangeCov[] = mergedTree.toRanges();
|
||||
const isBlockCoverage: boolean = !(ranges.length === 1 && ranges[0].count === 0);
|
||||
|
||||
const merged: FunctionCov = {functionName, ranges, isBlockCoverage};
|
||||
// assert: `merged` is normalized
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @precondition Same `start` and `end` for all the trees
|
||||
*/
|
||||
function mergeRangeTrees(trees: ReadonlyArray<RangeTree>): RangeTree | undefined {
|
||||
if (trees.length <= 1) {
|
||||
return trees[0];
|
||||
}
|
||||
const first: RangeTree = trees[0];
|
||||
let delta: number = 0;
|
||||
for (const tree of trees) {
|
||||
delta += tree.delta;
|
||||
}
|
||||
const children: RangeTree[] = mergeRangeTreeChildren(trees);
|
||||
return new RangeTree(first.start, first.end, delta, children);
|
||||
}
|
||||
|
||||
class RangeTreeWithParent {
|
||||
readonly parentIndex: number;
|
||||
readonly tree: RangeTree;
|
||||
|
||||
constructor(parentIndex: number, tree: RangeTree) {
|
||||
this.parentIndex = parentIndex;
|
||||
this.tree = tree;
|
||||
}
|
||||
}
|
||||
|
||||
class StartEvent {
|
||||
readonly offset: number;
|
||||
readonly trees: RangeTreeWithParent[];
|
||||
|
||||
constructor(offset: number, trees: RangeTreeWithParent[]) {
|
||||
this.offset = offset;
|
||||
this.trees = trees;
|
||||
}
|
||||
|
||||
static compare(a: StartEvent, b: StartEvent): number {
|
||||
return a.offset - b.offset;
|
||||
}
|
||||
}
|
||||
|
||||
class StartEventQueue {
|
||||
private readonly queue: StartEvent[];
|
||||
private nextIndex: number;
|
||||
private pendingOffset: number;
|
||||
private pendingTrees: RangeTreeWithParent[] | undefined;
|
||||
|
||||
private constructor(queue: StartEvent[]) {
|
||||
this.queue = queue;
|
||||
this.nextIndex = 0;
|
||||
this.pendingOffset = 0;
|
||||
this.pendingTrees = undefined;
|
||||
}
|
||||
|
||||
static fromParentTrees(parentTrees: ReadonlyArray<RangeTree>): StartEventQueue {
|
||||
const startToTrees: Map<number, RangeTreeWithParent[]> = new Map();
|
||||
for (const [parentIndex, parentTree] of parentTrees.entries()) {
|
||||
for (const child of parentTree.children) {
|
||||
let trees: RangeTreeWithParent[] | undefined = startToTrees.get(child.start);
|
||||
if (trees === undefined) {
|
||||
trees = [];
|
||||
startToTrees.set(child.start, trees);
|
||||
}
|
||||
trees.push(new RangeTreeWithParent(parentIndex, child));
|
||||
}
|
||||
}
|
||||
const queue: StartEvent[] = [];
|
||||
for (const [startOffset, trees] of startToTrees) {
|
||||
queue.push(new StartEvent(startOffset, trees));
|
||||
}
|
||||
queue.sort(StartEvent.compare);
|
||||
return new StartEventQueue(queue);
|
||||
}
|
||||
|
||||
setPendingOffset(offset: number): void {
|
||||
this.pendingOffset = offset;
|
||||
}
|
||||
|
||||
pushPendingTree(tree: RangeTreeWithParent): void {
|
||||
if (this.pendingTrees === undefined) {
|
||||
this.pendingTrees = [];
|
||||
}
|
||||
this.pendingTrees.push(tree);
|
||||
}
|
||||
|
||||
next(): StartEvent | undefined {
|
||||
const pendingTrees: RangeTreeWithParent[] | undefined = this.pendingTrees;
|
||||
const nextEvent: StartEvent | undefined = this.queue[this.nextIndex];
|
||||
if (pendingTrees === undefined) {
|
||||
this.nextIndex++;
|
||||
return nextEvent;
|
||||
} else if (nextEvent === undefined) {
|
||||
this.pendingTrees = undefined;
|
||||
return new StartEvent(this.pendingOffset, pendingTrees);
|
||||
} else {
|
||||
if (this.pendingOffset < nextEvent.offset) {
|
||||
this.pendingTrees = undefined;
|
||||
return new StartEvent(this.pendingOffset, pendingTrees);
|
||||
} else {
|
||||
if (this.pendingOffset === nextEvent.offset) {
|
||||
this.pendingTrees = undefined;
|
||||
for (const tree of pendingTrees) {
|
||||
nextEvent.trees.push(tree);
|
||||
}
|
||||
}
|
||||
this.nextIndex++;
|
||||
return nextEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mergeRangeTreeChildren(parentTrees: ReadonlyArray<RangeTree>): RangeTree[] {
|
||||
const result: RangeTree[] = [];
|
||||
const startEventQueue: StartEventQueue = StartEventQueue.fromParentTrees(parentTrees);
|
||||
const parentToNested: Map<number, RangeTree[]> = new Map();
|
||||
let openRange: Range | undefined;
|
||||
|
||||
while (true) {
|
||||
const event: StartEvent | undefined = startEventQueue.next();
|
||||
if (event === undefined) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (openRange !== undefined && openRange.end <= event.offset) {
|
||||
result.push(nextChild(openRange, parentToNested));
|
||||
openRange = undefined;
|
||||
}
|
||||
|
||||
if (openRange === undefined) {
|
||||
let openRangeEnd: number = event.offset + 1;
|
||||
for (const {parentIndex, tree} of event.trees) {
|
||||
openRangeEnd = Math.max(openRangeEnd, tree.end);
|
||||
insertChild(parentToNested, parentIndex, tree);
|
||||
}
|
||||
startEventQueue.setPendingOffset(openRangeEnd);
|
||||
openRange = {start: event.offset, end: openRangeEnd};
|
||||
} else {
|
||||
for (const {parentIndex, tree} of event.trees) {
|
||||
if (tree.end > openRange.end) {
|
||||
const right: RangeTree = tree.split(openRange.end);
|
||||
startEventQueue.pushPendingTree(new RangeTreeWithParent(parentIndex, right));
|
||||
}
|
||||
insertChild(parentToNested, parentIndex, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (openRange !== undefined) {
|
||||
result.push(nextChild(openRange, parentToNested));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function insertChild(parentToNested: Map<number, RangeTree[]>, parentIndex: number, tree: RangeTree): void {
|
||||
let nested: RangeTree[] | undefined = parentToNested.get(parentIndex);
|
||||
if (nested === undefined) {
|
||||
nested = [];
|
||||
parentToNested.set(parentIndex, nested);
|
||||
}
|
||||
nested.push(tree);
|
||||
}
|
||||
|
||||
function nextChild(openRange: Range, parentToNested: Map<number, RangeTree[]>): RangeTree {
|
||||
const matchingTrees: RangeTree[] = [];
|
||||
|
||||
for (const nested of parentToNested.values()) {
|
||||
if (nested.length === 1 && nested[0].start === openRange.start && nested[0].end === openRange.end) {
|
||||
matchingTrees.push(nested[0]);
|
||||
} else {
|
||||
matchingTrees.push(new RangeTree(
|
||||
openRange.start,
|
||||
openRange.end,
|
||||
0,
|
||||
nested,
|
||||
));
|
||||
}
|
||||
}
|
||||
parentToNested.clear();
|
||||
return mergeRangeTrees(matchingTrees)!;
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
import { compareFunctionCovs, compareRangeCovs, compareScriptCovs } from "./compare";
|
||||
import { RangeTree } from "./range-tree";
|
||||
import { FunctionCov, ProcessCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Normalizes a process coverage.
|
||||
*
|
||||
* Sorts the scripts alphabetically by `url`.
|
||||
* Reassigns script ids: the script at index `0` receives `"0"`, the script at
|
||||
* index `1` receives `"1"` etc.
|
||||
* This does not normalize the script coverages.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export function normalizeProcessCov(processCov: ProcessCov): void {
|
||||
processCov.result.sort(compareScriptCovs);
|
||||
for (const [scriptId, scriptCov] of processCov.result.entries()) {
|
||||
scriptCov.scriptId = scriptId.toString(10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a process coverage deeply.
|
||||
*
|
||||
* Normalizes the script coverages deeply, then normalizes the process coverage
|
||||
* itself.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export function deepNormalizeProcessCov(processCov: ProcessCov): void {
|
||||
for (const scriptCov of processCov.result) {
|
||||
deepNormalizeScriptCov(scriptCov);
|
||||
}
|
||||
normalizeProcessCov(processCov);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a script coverage.
|
||||
*
|
||||
* Sorts the function by root range (pre-order sort).
|
||||
* This does not normalize the function coverages.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export function normalizeScriptCov(scriptCov: ScriptCov): void {
|
||||
scriptCov.functions.sort(compareFunctionCovs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a script coverage deeply.
|
||||
*
|
||||
* Normalizes the function coverages deeply, then normalizes the script coverage
|
||||
* itself.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export function deepNormalizeScriptCov(scriptCov: ScriptCov): void {
|
||||
for (const funcCov of scriptCov.functions) {
|
||||
normalizeFunctionCov(funcCov);
|
||||
}
|
||||
normalizeScriptCov(scriptCov);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a function coverage.
|
||||
*
|
||||
* Sorts the ranges (pre-order sort).
|
||||
* TODO: Tree-based normalization of the ranges.
|
||||
*
|
||||
* @param funcCov Function coverage to normalize.
|
||||
*/
|
||||
export function normalizeFunctionCov(funcCov: FunctionCov): void {
|
||||
funcCov.ranges.sort(compareRangeCovs);
|
||||
const tree: RangeTree = RangeTree.fromSortedRanges(funcCov.ranges)!;
|
||||
normalizeRangeTree(tree);
|
||||
funcCov.ranges = tree.toRanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function normalizeRangeTree(tree: RangeTree): void {
|
||||
tree.normalize();
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
import { RangeCov } from "./types";
|
||||
|
||||
export class RangeTree {
|
||||
start: number;
|
||||
end: number;
|
||||
delta: number;
|
||||
children: RangeTree[];
|
||||
|
||||
constructor(
|
||||
start: number,
|
||||
end: number,
|
||||
delta: number,
|
||||
children: RangeTree[],
|
||||
) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.delta = delta;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @precodition `ranges` are well-formed and pre-order sorted
|
||||
*/
|
||||
static fromSortedRanges(ranges: ReadonlyArray<RangeCov>): RangeTree | undefined {
|
||||
let root: RangeTree | undefined;
|
||||
// Stack of parent trees and parent counts.
|
||||
const stack: [RangeTree, number][] = [];
|
||||
for (const range of ranges) {
|
||||
const node: RangeTree = new RangeTree(range.startOffset, range.endOffset, range.count, []);
|
||||
if (root === undefined) {
|
||||
root = node;
|
||||
stack.push([node, range.count]);
|
||||
continue;
|
||||
}
|
||||
let parent: RangeTree;
|
||||
let parentCount: number;
|
||||
while (true) {
|
||||
[parent, parentCount] = stack[stack.length - 1];
|
||||
// assert: `top !== undefined` (the ranges are sorted)
|
||||
if (range.startOffset < parent.end) {
|
||||
break;
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
node.delta -= parentCount;
|
||||
parent.children.push(node);
|
||||
stack.push([node, range.count]);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
normalize(): void {
|
||||
const children: RangeTree[] = [];
|
||||
let curEnd: number;
|
||||
let head: RangeTree | undefined;
|
||||
const tail: RangeTree[] = [];
|
||||
for (const child of this.children) {
|
||||
if (head === undefined) {
|
||||
head = child;
|
||||
} else if (child.delta === head.delta && child.start === curEnd!) {
|
||||
tail.push(child);
|
||||
} else {
|
||||
endChain();
|
||||
head = child;
|
||||
}
|
||||
curEnd = child.end;
|
||||
}
|
||||
if (head !== undefined) {
|
||||
endChain();
|
||||
}
|
||||
|
||||
if (children.length === 1) {
|
||||
const child: RangeTree = children[0];
|
||||
if (child.start === this.start && child.end === this.end) {
|
||||
this.delta += child.delta;
|
||||
this.children = child.children;
|
||||
// `.lazyCount` is zero for both (both are after normalization)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.children = children;
|
||||
|
||||
function endChain(): void {
|
||||
if (tail.length !== 0) {
|
||||
head!.end = tail[tail.length - 1].end;
|
||||
for (const tailTree of tail) {
|
||||
for (const subChild of tailTree.children) {
|
||||
subChild.delta += tailTree.delta - head!.delta;
|
||||
head!.children.push(subChild);
|
||||
}
|
||||
}
|
||||
tail.length = 0;
|
||||
}
|
||||
head!.normalize();
|
||||
children.push(head!);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @precondition `tree.start < value && value < tree.end`
|
||||
* @return RangeTree Right part
|
||||
*/
|
||||
split(value: number): RangeTree {
|
||||
let leftChildLen: number = this.children.length;
|
||||
let mid: RangeTree | undefined;
|
||||
|
||||
// TODO(perf): Binary search (check overhead)
|
||||
for (let i: number = 0; i < this.children.length; i++) {
|
||||
const child: RangeTree = this.children[i];
|
||||
if (child.start < value && value < child.end) {
|
||||
mid = child.split(value);
|
||||
leftChildLen = i + 1;
|
||||
break;
|
||||
} else if (child.start >= value) {
|
||||
leftChildLen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const rightLen: number = this.children.length - leftChildLen;
|
||||
const rightChildren: RangeTree[] = this.children.splice(leftChildLen, rightLen);
|
||||
if (mid !== undefined) {
|
||||
rightChildren.unshift(mid);
|
||||
}
|
||||
const result: RangeTree = new RangeTree(
|
||||
value,
|
||||
this.end,
|
||||
this.delta,
|
||||
rightChildren,
|
||||
);
|
||||
this.end = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range coverages corresponding to the tree.
|
||||
*
|
||||
* The ranges are pre-order sorted.
|
||||
*/
|
||||
toRanges(): RangeCov[] {
|
||||
const ranges: RangeCov[] = [];
|
||||
// Stack of parent trees and counts.
|
||||
const stack: [RangeTree, number][] = [[this, 0]];
|
||||
while (stack.length > 0) {
|
||||
const [cur, parentCount]: [RangeTree, number] = stack.pop()!;
|
||||
const count: number = parentCount + cur.delta;
|
||||
ranges.push({startOffset: cur.start, endOffset: cur.end, count});
|
||||
for (let i: number = cur.children.length - 1; i >= 0; i--) {
|
||||
stack.push([cur.children[i], count]);
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
export interface ProcessCov {
|
||||
result: ScriptCov[];
|
||||
}
|
||||
|
||||
export interface ScriptCov {
|
||||
scriptId: string;
|
||||
url: string;
|
||||
functions: FunctionCov[];
|
||||
}
|
||||
|
||||
export interface FunctionCov {
|
||||
functionName: string;
|
||||
ranges: RangeCov[];
|
||||
isBlockCoverage: boolean;
|
||||
}
|
||||
|
||||
export interface Range {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
}
|
||||
|
||||
export interface RangeCov {
|
||||
startOffset: number;
|
||||
endOffset: number;
|
||||
count: number;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { RangeCov } from "./types";
|
||||
interface ReadonlyRangeTree {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
readonly count: number;
|
||||
readonly children: ReadonlyRangeTree[];
|
||||
}
|
||||
export declare function emitForest(trees: ReadonlyArray<ReadonlyRangeTree>): string;
|
||||
export declare function emitForestLines(trees: ReadonlyArray<ReadonlyRangeTree>): string[];
|
||||
export declare function parseFunctionRanges(text: string, offsetMap: Map<number, number>): RangeCov[];
|
||||
export declare function parseOffsets(text: string): Map<number, number>;
|
||||
export {};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,29 @@
|
||||
import { FunctionCov, ProcessCov, RangeCov, ScriptCov } from "./types";
|
||||
/**
|
||||
* Creates a deep copy of a process coverage.
|
||||
*
|
||||
* @param processCov Process coverage to clone.
|
||||
* @return Cloned process coverage.
|
||||
*/
|
||||
export declare function cloneProcessCov(processCov: Readonly<ProcessCov>): ProcessCov;
|
||||
/**
|
||||
* Creates a deep copy of a script coverage.
|
||||
*
|
||||
* @param scriptCov Script coverage to clone.
|
||||
* @return Cloned script coverage.
|
||||
*/
|
||||
export declare function cloneScriptCov(scriptCov: Readonly<ScriptCov>): ScriptCov;
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param functionCov Function coverage to clone.
|
||||
* @return Cloned function coverage.
|
||||
*/
|
||||
export declare function cloneFunctionCov(functionCov: Readonly<FunctionCov>): FunctionCov;
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param rangeCov Range coverage to clone.
|
||||
* @return Cloned range coverage.
|
||||
*/
|
||||
export declare function cloneRangeCov(rangeCov: Readonly<RangeCov>): RangeCov;
|
@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Creates a deep copy of a process coverage.
|
||||
*
|
||||
* @param processCov Process coverage to clone.
|
||||
* @return Cloned process coverage.
|
||||
*/
|
||||
function cloneProcessCov(processCov) {
|
||||
const result = [];
|
||||
for (const scriptCov of processCov.result) {
|
||||
result.push(cloneScriptCov(scriptCov));
|
||||
}
|
||||
return {
|
||||
result,
|
||||
};
|
||||
}
|
||||
exports.cloneProcessCov = cloneProcessCov;
|
||||
/**
|
||||
* Creates a deep copy of a script coverage.
|
||||
*
|
||||
* @param scriptCov Script coverage to clone.
|
||||
* @return Cloned script coverage.
|
||||
*/
|
||||
function cloneScriptCov(scriptCov) {
|
||||
const functions = [];
|
||||
for (const functionCov of scriptCov.functions) {
|
||||
functions.push(cloneFunctionCov(functionCov));
|
||||
}
|
||||
return {
|
||||
scriptId: scriptCov.scriptId,
|
||||
url: scriptCov.url,
|
||||
functions,
|
||||
};
|
||||
}
|
||||
exports.cloneScriptCov = cloneScriptCov;
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param functionCov Function coverage to clone.
|
||||
* @return Cloned function coverage.
|
||||
*/
|
||||
function cloneFunctionCov(functionCov) {
|
||||
const ranges = [];
|
||||
for (const rangeCov of functionCov.ranges) {
|
||||
ranges.push(cloneRangeCov(rangeCov));
|
||||
}
|
||||
return {
|
||||
functionName: functionCov.functionName,
|
||||
ranges,
|
||||
isBlockCoverage: functionCov.isBlockCoverage,
|
||||
};
|
||||
}
|
||||
exports.cloneFunctionCov = cloneFunctionCov;
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param rangeCov Range coverage to clone.
|
||||
* @return Cloned range coverage.
|
||||
*/
|
||||
function cloneRangeCov(rangeCov) {
|
||||
return {
|
||||
startOffset: rangeCov.startOffset,
|
||||
endOffset: rangeCov.endOffset,
|
||||
count: rangeCov.count,
|
||||
};
|
||||
}
|
||||
exports.cloneRangeCov = cloneRangeCov;
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvY2xvbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQTs7Ozs7R0FLRztBQUNILFNBQWdCLGVBQWUsQ0FBQyxVQUFnQztJQUM5RCxNQUFNLE1BQU0sR0FBZ0IsRUFBRSxDQUFDO0lBQy9CLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxDQUFDLE1BQU0sRUFBRTtRQUN6QyxNQUFNLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0tBQ3hDO0lBRUQsT0FBTztRQUNMLE1BQU07S0FDUCxDQUFDO0FBQ0osQ0FBQztBQVRELDBDQVNDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixjQUFjLENBQUMsU0FBOEI7SUFDM0QsTUFBTSxTQUFTLEdBQWtCLEVBQUUsQ0FBQztJQUNwQyxLQUFLLE1BQU0sV0FBVyxJQUFJLFNBQVMsQ0FBQyxTQUFTLEVBQUU7UUFDN0MsU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0tBQy9DO0lBRUQsT0FBTztRQUNMLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtRQUM1QixHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUc7UUFDbEIsU0FBUztLQUNWLENBQUM7QUFDSixDQUFDO0FBWEQsd0NBV0M7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLFdBQWtDO0lBQ2pFLE1BQU0sTUFBTSxHQUFlLEVBQUUsQ0FBQztJQUM5QixLQUFLLE1BQU0sUUFBUSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUU7UUFDekMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztLQUN0QztJQUVELE9BQU87UUFDTCxZQUFZLEVBQUUsV0FBVyxDQUFDLFlBQVk7UUFDdEMsTUFBTTtRQUNOLGVBQWUsRUFBRSxXQUFXLENBQUMsZUFBZTtLQUM3QyxDQUFDO0FBQ0osQ0FBQztBQVhELDRDQVdDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixhQUFhLENBQUMsUUFBNEI7SUFDeEQsT0FBTztRQUNMLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVztRQUNqQyxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVM7UUFDN0IsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO0tBQ3RCLENBQUM7QUFDSixDQUFDO0FBTkQsc0NBTUMiLCJmaWxlIjoiY2xvbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvbkNvdiwgUHJvY2Vzc0NvdiwgUmFuZ2VDb3YsIFNjcmlwdENvdiB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlZXAgY29weSBvZiBhIHByb2Nlc3MgY292ZXJhZ2UuXG4gKlxuICogQHBhcmFtIHByb2Nlc3NDb3YgUHJvY2VzcyBjb3ZlcmFnZSB0byBjbG9uZS5cbiAqIEByZXR1cm4gQ2xvbmVkIHByb2Nlc3MgY292ZXJhZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZVByb2Nlc3NDb3YocHJvY2Vzc0NvdjogUmVhZG9ubHk8UHJvY2Vzc0Nvdj4pOiBQcm9jZXNzQ292IHtcbiAgY29uc3QgcmVzdWx0OiBTY3JpcHRDb3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHNjcmlwdENvdiBvZiBwcm9jZXNzQ292LnJlc3VsdCkge1xuICAgIHJlc3VsdC5wdXNoKGNsb25lU2NyaXB0Q292KHNjcmlwdENvdikpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICByZXN1bHQsXG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlZXAgY29weSBvZiBhIHNjcmlwdCBjb3ZlcmFnZS5cbiAqXG4gKiBAcGFyYW0gc2NyaXB0Q292IFNjcmlwdCBjb3ZlcmFnZSB0byBjbG9uZS5cbiAqIEByZXR1cm4gQ2xvbmVkIHNjcmlwdCBjb3ZlcmFnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lU2NyaXB0Q292KHNjcmlwdENvdjogUmVhZG9ubHk8U2NyaXB0Q292Pik6IFNjcmlwdENvdiB7XG4gIGNvbnN0IGZ1bmN0aW9uczogRnVuY3Rpb25Db3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGZ1bmN0aW9uQ292IG9mIHNjcmlwdENvdi5mdW5jdGlvbnMpIHtcbiAgICBmdW5jdGlvbnMucHVzaChjbG9uZUZ1bmN0aW9uQ292KGZ1bmN0aW9uQ292KSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHNjcmlwdElkOiBzY3JpcHRDb3Yuc2NyaXB0SWQsXG4gICAgdXJsOiBzY3JpcHRDb3YudXJsLFxuICAgIGZ1bmN0aW9ucyxcbiAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVlcCBjb3B5IG9mIGEgZnVuY3Rpb24gY292ZXJhZ2UuXG4gKlxuICogQHBhcmFtIGZ1bmN0aW9uQ292IEZ1bmN0aW9uIGNvdmVyYWdlIHRvIGNsb25lLlxuICogQHJldHVybiBDbG9uZWQgZnVuY3Rpb24gY292ZXJhZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZUZ1bmN0aW9uQ292KGZ1bmN0aW9uQ292OiBSZWFkb25seTxGdW5jdGlvbkNvdj4pOiBGdW5jdGlvbkNvdiB7XG4gIGNvbnN0IHJhbmdlczogUmFuZ2VDb3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHJhbmdlQ292IG9mIGZ1bmN0aW9uQ292LnJhbmdlcykge1xuICAgIHJhbmdlcy5wdXNoKGNsb25lUmFuZ2VDb3YocmFuZ2VDb3YpKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZnVuY3Rpb25OYW1lOiBmdW5jdGlvbkNvdi5mdW5jdGlvbk5hbWUsXG4gICAgcmFuZ2VzLFxuICAgIGlzQmxvY2tDb3ZlcmFnZTogZnVuY3Rpb25Db3YuaXNCbG9ja0NvdmVyYWdlLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWVwIGNvcHkgb2YgYSBmdW5jdGlvbiBjb3ZlcmFnZS5cbiAqXG4gKiBAcGFyYW0gcmFuZ2VDb3YgUmFuZ2UgY292ZXJhZ2UgdG8gY2xvbmUuXG4gKiBAcmV0dXJuIENsb25lZCByYW5nZSBjb3ZlcmFnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lUmFuZ2VDb3YocmFuZ2VDb3Y6IFJlYWRvbmx5PFJhbmdlQ292Pik6IFJhbmdlQ292IHtcbiAgcmV0dXJuIHtcbiAgICBzdGFydE9mZnNldDogcmFuZ2VDb3Yuc3RhcnRPZmZzZXQsXG4gICAgZW5kT2Zmc2V0OiByYW5nZUNvdi5lbmRPZmZzZXQsXG4gICAgY291bnQ6IHJhbmdlQ292LmNvdW50LFxuICB9O1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Creates a deep copy of a process coverage.
|
||||
*
|
||||
* @param processCov Process coverage to clone.
|
||||
* @return Cloned process coverage.
|
||||
*/
|
||||
export function cloneProcessCov(processCov) {
|
||||
const result = [];
|
||||
for (const scriptCov of processCov.result) {
|
||||
result.push(cloneScriptCov(scriptCov));
|
||||
}
|
||||
return {
|
||||
result,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Creates a deep copy of a script coverage.
|
||||
*
|
||||
* @param scriptCov Script coverage to clone.
|
||||
* @return Cloned script coverage.
|
||||
*/
|
||||
export function cloneScriptCov(scriptCov) {
|
||||
const functions = [];
|
||||
for (const functionCov of scriptCov.functions) {
|
||||
functions.push(cloneFunctionCov(functionCov));
|
||||
}
|
||||
return {
|
||||
scriptId: scriptCov.scriptId,
|
||||
url: scriptCov.url,
|
||||
functions,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param functionCov Function coverage to clone.
|
||||
* @return Cloned function coverage.
|
||||
*/
|
||||
export function cloneFunctionCov(functionCov) {
|
||||
const ranges = [];
|
||||
for (const rangeCov of functionCov.ranges) {
|
||||
ranges.push(cloneRangeCov(rangeCov));
|
||||
}
|
||||
return {
|
||||
functionName: functionCov.functionName,
|
||||
ranges,
|
||||
isBlockCoverage: functionCov.isBlockCoverage,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param rangeCov Range coverage to clone.
|
||||
* @return Cloned range coverage.
|
||||
*/
|
||||
export function cloneRangeCov(rangeCov) {
|
||||
return {
|
||||
startOffset: rangeCov.startOffset,
|
||||
endOffset: rangeCov.endOffset,
|
||||
count: rangeCov.count,
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvY2xvbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLFVBQWdDO0lBQzlELE1BQU0sTUFBTSxHQUFnQixFQUFFLENBQUM7SUFDL0IsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLENBQUMsTUFBTSxFQUFFO1FBQ3pDLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7S0FDeEM7SUFFRCxPQUFPO1FBQ0wsTUFBTTtLQUNQLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLFNBQThCO0lBQzNELE1BQU0sU0FBUyxHQUFrQixFQUFFLENBQUM7SUFDcEMsS0FBSyxNQUFNLFdBQVcsSUFBSSxTQUFTLENBQUMsU0FBUyxFQUFFO1FBQzdDLFNBQVMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztLQUMvQztJQUVELE9BQU87UUFDTCxRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7UUFDNUIsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHO1FBQ2xCLFNBQVM7S0FDVixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLFdBQWtDO0lBQ2pFLE1BQU0sTUFBTSxHQUFlLEVBQUUsQ0FBQztJQUM5QixLQUFLLE1BQU0sUUFBUSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUU7UUFDekMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztLQUN0QztJQUVELE9BQU87UUFDTCxZQUFZLEVBQUUsV0FBVyxDQUFDLFlBQVk7UUFDdEMsTUFBTTtRQUNOLGVBQWUsRUFBRSxXQUFXLENBQUMsZUFBZTtLQUM3QyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxRQUE0QjtJQUN4RCxPQUFPO1FBQ0wsV0FBVyxFQUFFLFFBQVEsQ0FBQyxXQUFXO1FBQ2pDLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztRQUM3QixLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUs7S0FDdEIsQ0FBQztBQUNKLENBQUMiLCJmaWxlIjoiY2xvbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvbkNvdiwgUHJvY2Vzc0NvdiwgUmFuZ2VDb3YsIFNjcmlwdENvdiB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlZXAgY29weSBvZiBhIHByb2Nlc3MgY292ZXJhZ2UuXG4gKlxuICogQHBhcmFtIHByb2Nlc3NDb3YgUHJvY2VzcyBjb3ZlcmFnZSB0byBjbG9uZS5cbiAqIEByZXR1cm4gQ2xvbmVkIHByb2Nlc3MgY292ZXJhZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZVByb2Nlc3NDb3YocHJvY2Vzc0NvdjogUmVhZG9ubHk8UHJvY2Vzc0Nvdj4pOiBQcm9jZXNzQ292IHtcbiAgY29uc3QgcmVzdWx0OiBTY3JpcHRDb3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHNjcmlwdENvdiBvZiBwcm9jZXNzQ292LnJlc3VsdCkge1xuICAgIHJlc3VsdC5wdXNoKGNsb25lU2NyaXB0Q292KHNjcmlwdENvdikpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICByZXN1bHQsXG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlZXAgY29weSBvZiBhIHNjcmlwdCBjb3ZlcmFnZS5cbiAqXG4gKiBAcGFyYW0gc2NyaXB0Q292IFNjcmlwdCBjb3ZlcmFnZSB0byBjbG9uZS5cbiAqIEByZXR1cm4gQ2xvbmVkIHNjcmlwdCBjb3ZlcmFnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lU2NyaXB0Q292KHNjcmlwdENvdjogUmVhZG9ubHk8U2NyaXB0Q292Pik6IFNjcmlwdENvdiB7XG4gIGNvbnN0IGZ1bmN0aW9uczogRnVuY3Rpb25Db3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGZ1bmN0aW9uQ292IG9mIHNjcmlwdENvdi5mdW5jdGlvbnMpIHtcbiAgICBmdW5jdGlvbnMucHVzaChjbG9uZUZ1bmN0aW9uQ292KGZ1bmN0aW9uQ292KSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHNjcmlwdElkOiBzY3JpcHRDb3Yuc2NyaXB0SWQsXG4gICAgdXJsOiBzY3JpcHRDb3YudXJsLFxuICAgIGZ1bmN0aW9ucyxcbiAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVlcCBjb3B5IG9mIGEgZnVuY3Rpb24gY292ZXJhZ2UuXG4gKlxuICogQHBhcmFtIGZ1bmN0aW9uQ292IEZ1bmN0aW9uIGNvdmVyYWdlIHRvIGNsb25lLlxuICogQHJldHVybiBDbG9uZWQgZnVuY3Rpb24gY292ZXJhZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZUZ1bmN0aW9uQ292KGZ1bmN0aW9uQ292OiBSZWFkb25seTxGdW5jdGlvbkNvdj4pOiBGdW5jdGlvbkNvdiB7XG4gIGNvbnN0IHJhbmdlczogUmFuZ2VDb3ZbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHJhbmdlQ292IG9mIGZ1bmN0aW9uQ292LnJhbmdlcykge1xuICAgIHJhbmdlcy5wdXNoKGNsb25lUmFuZ2VDb3YocmFuZ2VDb3YpKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZnVuY3Rpb25OYW1lOiBmdW5jdGlvbkNvdi5mdW5jdGlvbk5hbWUsXG4gICAgcmFuZ2VzLFxuICAgIGlzQmxvY2tDb3ZlcmFnZTogZnVuY3Rpb25Db3YuaXNCbG9ja0NvdmVyYWdlLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWVwIGNvcHkgb2YgYSBmdW5jdGlvbiBjb3ZlcmFnZS5cbiAqXG4gKiBAcGFyYW0gcmFuZ2VDb3YgUmFuZ2UgY292ZXJhZ2UgdG8gY2xvbmUuXG4gKiBAcmV0dXJuIENsb25lZCByYW5nZSBjb3ZlcmFnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lUmFuZ2VDb3YocmFuZ2VDb3Y6IFJlYWRvbmx5PFJhbmdlQ292Pik6IFJhbmdlQ292IHtcbiAgcmV0dXJuIHtcbiAgICBzdGFydE9mZnNldDogcmFuZ2VDb3Yuc3RhcnRPZmZzZXQsXG4gICAgZW5kT2Zmc2V0OiByYW5nZUNvdi5lbmRPZmZzZXQsXG4gICAgY291bnQ6IHJhbmdlQ292LmNvdW50LFxuICB9O1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==
|
@ -0,0 +1,21 @@
|
||||
import { FunctionCov, RangeCov, ScriptCov } from "./types";
|
||||
/**
|
||||
* Compares two script coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of their `url` value (alphabetical sort).
|
||||
*/
|
||||
export declare function compareScriptCovs(a: Readonly<ScriptCov>, b: Readonly<ScriptCov>): number;
|
||||
/**
|
||||
* Compares two function coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of the root ranges.
|
||||
*/
|
||||
export declare function compareFunctionCovs(a: Readonly<FunctionCov>, b: Readonly<FunctionCov>): number;
|
||||
/**
|
||||
* Compares two range coverages.
|
||||
*
|
||||
* The ranges are first ordered by ascending `startOffset` and then by
|
||||
* descending `endOffset`.
|
||||
* This corresponds to a pre-order tree traversal.
|
||||
*/
|
||||
export declare function compareRangeCovs(a: Readonly<RangeCov>, b: Readonly<RangeCov>): number;
|
@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Compares two script coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of their `url` value (alphabetical sort).
|
||||
*/
|
||||
function compareScriptCovs(a, b) {
|
||||
if (a.url === b.url) {
|
||||
return 0;
|
||||
}
|
||||
else if (a.url < b.url) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
exports.compareScriptCovs = compareScriptCovs;
|
||||
/**
|
||||
* Compares two function coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of the root ranges.
|
||||
*/
|
||||
function compareFunctionCovs(a, b) {
|
||||
return compareRangeCovs(a.ranges[0], b.ranges[0]);
|
||||
}
|
||||
exports.compareFunctionCovs = compareFunctionCovs;
|
||||
/**
|
||||
* Compares two range coverages.
|
||||
*
|
||||
* The ranges are first ordered by ascending `startOffset` and then by
|
||||
* descending `endOffset`.
|
||||
* This corresponds to a pre-order tree traversal.
|
||||
*/
|
||||
function compareRangeCovs(a, b) {
|
||||
if (a.startOffset !== b.startOffset) {
|
||||
return a.startOffset - b.startOffset;
|
||||
}
|
||||
else {
|
||||
return b.endOffset - a.endOffset;
|
||||
}
|
||||
}
|
||||
exports.compareRangeCovs = compareRangeCovs;
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvY29tcGFyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBOzs7O0dBSUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxDQUFzQixFQUFFLENBQXNCO0lBQzlFLElBQUksQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFO1FBQ25CLE9BQU8sQ0FBQyxDQUFDO0tBQ1Y7U0FBTSxJQUFJLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRTtRQUN4QixPQUFPLENBQUMsQ0FBQyxDQUFDO0tBQ1g7U0FBTTtRQUNMLE9BQU8sQ0FBQyxDQUFDO0tBQ1Y7QUFDSCxDQUFDO0FBUkQsOENBUUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsQ0FBd0IsRUFBRSxDQUF3QjtJQUNwRixPQUFPLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BELENBQUM7QUFGRCxrREFFQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLENBQXFCLEVBQUUsQ0FBcUI7SUFDM0UsSUFBSSxDQUFDLENBQUMsV0FBVyxLQUFLLENBQUMsQ0FBQyxXQUFXLEVBQUU7UUFDbkMsT0FBTyxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLENBQUM7S0FDdEM7U0FBTTtRQUNMLE9BQU8sQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO0tBQ2xDO0FBQ0gsQ0FBQztBQU5ELDRDQU1DIiwiZmlsZSI6ImNvbXBhcmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvbkNvdiwgUmFuZ2VDb3YsIFNjcmlwdENvdiB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQ29tcGFyZXMgdHdvIHNjcmlwdCBjb3ZlcmFnZXMuXG4gKlxuICogVGhlIHJlc3VsdCBjb3JyZXNwb25kcyB0byB0aGUgY29tcGFyaXNvbiBvZiB0aGVpciBgdXJsYCB2YWx1ZSAoYWxwaGFiZXRpY2FsIHNvcnQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZVNjcmlwdENvdnMoYTogUmVhZG9ubHk8U2NyaXB0Q292PiwgYjogUmVhZG9ubHk8U2NyaXB0Q292Pik6IG51bWJlciB7XG4gIGlmIChhLnVybCA9PT0gYi51cmwpIHtcbiAgICByZXR1cm4gMDtcbiAgfSBlbHNlIGlmIChhLnVybCA8IGIudXJsKSB7XG4gICAgcmV0dXJuIC0xO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAxO1xuICB9XG59XG5cbi8qKlxuICogQ29tcGFyZXMgdHdvIGZ1bmN0aW9uIGNvdmVyYWdlcy5cbiAqXG4gKiBUaGUgcmVzdWx0IGNvcnJlc3BvbmRzIHRvIHRoZSBjb21wYXJpc29uIG9mIHRoZSByb290IHJhbmdlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmVGdW5jdGlvbkNvdnMoYTogUmVhZG9ubHk8RnVuY3Rpb25Db3Y+LCBiOiBSZWFkb25seTxGdW5jdGlvbkNvdj4pOiBudW1iZXIge1xuICByZXR1cm4gY29tcGFyZVJhbmdlQ292cyhhLnJhbmdlc1swXSwgYi5yYW5nZXNbMF0pO1xufVxuXG4vKipcbiAqIENvbXBhcmVzIHR3byByYW5nZSBjb3ZlcmFnZXMuXG4gKlxuICogVGhlIHJhbmdlcyBhcmUgZmlyc3Qgb3JkZXJlZCBieSBhc2NlbmRpbmcgYHN0YXJ0T2Zmc2V0YCBhbmQgdGhlbiBieVxuICogZGVzY2VuZGluZyBgZW5kT2Zmc2V0YC5cbiAqIFRoaXMgY29ycmVzcG9uZHMgdG8gYSBwcmUtb3JkZXIgdHJlZSB0cmF2ZXJzYWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlUmFuZ2VDb3ZzKGE6IFJlYWRvbmx5PFJhbmdlQ292PiwgYjogUmVhZG9ubHk8UmFuZ2VDb3Y+KTogbnVtYmVyIHtcbiAgaWYgKGEuc3RhcnRPZmZzZXQgIT09IGIuc3RhcnRPZmZzZXQpIHtcbiAgICByZXR1cm4gYS5zdGFydE9mZnNldCAtIGIuc3RhcnRPZmZzZXQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGIuZW5kT2Zmc2V0IC0gYS5lbmRPZmZzZXQ7XG4gIH1cbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Compares two script coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of their `url` value (alphabetical sort).
|
||||
*/
|
||||
export function compareScriptCovs(a, b) {
|
||||
if (a.url === b.url) {
|
||||
return 0;
|
||||
}
|
||||
else if (a.url < b.url) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Compares two function coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of the root ranges.
|
||||
*/
|
||||
export function compareFunctionCovs(a, b) {
|
||||
return compareRangeCovs(a.ranges[0], b.ranges[0]);
|
||||
}
|
||||
/**
|
||||
* Compares two range coverages.
|
||||
*
|
||||
* The ranges are first ordered by ascending `startOffset` and then by
|
||||
* descending `endOffset`.
|
||||
* This corresponds to a pre-order tree traversal.
|
||||
*/
|
||||
export function compareRangeCovs(a, b) {
|
||||
if (a.startOffset !== b.startOffset) {
|
||||
return a.startOffset - b.startOffset;
|
||||
}
|
||||
else {
|
||||
return b.endOffset - a.endOffset;
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvY29tcGFyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLENBQXNCLEVBQUUsQ0FBc0I7SUFDOUUsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUU7UUFDbkIsT0FBTyxDQUFDLENBQUM7S0FDVjtTQUFNLElBQUksQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLENBQUM7S0FDWDtTQUFNO1FBQ0wsT0FBTyxDQUFDLENBQUM7S0FDVjtBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLENBQXdCLEVBQUUsQ0FBd0I7SUFDcEYsT0FBTyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLENBQXFCLEVBQUUsQ0FBcUI7SUFDM0UsSUFBSSxDQUFDLENBQUMsV0FBVyxLQUFLLENBQUMsQ0FBQyxXQUFXLEVBQUU7UUFDbkMsT0FBTyxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLENBQUM7S0FDdEM7U0FBTTtRQUNMLE9BQU8sQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO0tBQ2xDO0FBQ0gsQ0FBQyIsImZpbGUiOiJjb21wYXJlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnVuY3Rpb25Db3YsIFJhbmdlQ292LCBTY3JpcHRDb3YgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIENvbXBhcmVzIHR3byBzY3JpcHQgY292ZXJhZ2VzLlxuICpcbiAqIFRoZSByZXN1bHQgY29ycmVzcG9uZHMgdG8gdGhlIGNvbXBhcmlzb24gb2YgdGhlaXIgYHVybGAgdmFsdWUgKGFscGhhYmV0aWNhbCBzb3J0KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmVTY3JpcHRDb3ZzKGE6IFJlYWRvbmx5PFNjcmlwdENvdj4sIGI6IFJlYWRvbmx5PFNjcmlwdENvdj4pOiBudW1iZXIge1xuICBpZiAoYS51cmwgPT09IGIudXJsKSB7XG4gICAgcmV0dXJuIDA7XG4gIH0gZWxzZSBpZiAoYS51cmwgPCBiLnVybCkge1xuICAgIHJldHVybiAtMTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gMTtcbiAgfVxufVxuXG4vKipcbiAqIENvbXBhcmVzIHR3byBmdW5jdGlvbiBjb3ZlcmFnZXMuXG4gKlxuICogVGhlIHJlc3VsdCBjb3JyZXNwb25kcyB0byB0aGUgY29tcGFyaXNvbiBvZiB0aGUgcm9vdCByYW5nZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlRnVuY3Rpb25Db3ZzKGE6IFJlYWRvbmx5PEZ1bmN0aW9uQ292PiwgYjogUmVhZG9ubHk8RnVuY3Rpb25Db3Y+KTogbnVtYmVyIHtcbiAgcmV0dXJuIGNvbXBhcmVSYW5nZUNvdnMoYS5yYW5nZXNbMF0sIGIucmFuZ2VzWzBdKTtcbn1cblxuLyoqXG4gKiBDb21wYXJlcyB0d28gcmFuZ2UgY292ZXJhZ2VzLlxuICpcbiAqIFRoZSByYW5nZXMgYXJlIGZpcnN0IG9yZGVyZWQgYnkgYXNjZW5kaW5nIGBzdGFydE9mZnNldGAgYW5kIHRoZW4gYnlcbiAqIGRlc2NlbmRpbmcgYGVuZE9mZnNldGAuXG4gKiBUaGlzIGNvcnJlc3BvbmRzIHRvIGEgcHJlLW9yZGVyIHRyZWUgdHJhdmVyc2FsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZVJhbmdlQ292cyhhOiBSZWFkb25seTxSYW5nZUNvdj4sIGI6IFJlYWRvbmx5PFJhbmdlQ292Pik6IG51bWJlciB7XG4gIGlmIChhLnN0YXJ0T2Zmc2V0ICE9PSBiLnN0YXJ0T2Zmc2V0KSB7XG4gICAgcmV0dXJuIGEuc3RhcnRPZmZzZXQgLSBiLnN0YXJ0T2Zmc2V0O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBiLmVuZE9mZnNldCAtIGEuZW5kT2Zmc2V0O1xuICB9XG59XG4iXSwic291cmNlUm9vdCI6IiJ9
|
@ -0,0 +1,6 @@
|
||||
export { emitForest, emitForestLines, parseFunctionRanges, parseOffsets } from "./ascii";
|
||||
export { cloneFunctionCov, cloneProcessCov, cloneScriptCov, cloneRangeCov } from "./clone";
|
||||
export { compareScriptCovs, compareFunctionCovs, compareRangeCovs } from "./compare";
|
||||
export { mergeFunctionCovs, mergeProcessCovs, mergeScriptCovs } from "./merge";
|
||||
export { RangeTree } from "./range-tree";
|
||||
export { ProcessCov, ScriptCov, FunctionCov, RangeCov } from "./types";
|
@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ascii_1 = require("./ascii");
|
||||
exports.emitForest = ascii_1.emitForest;
|
||||
exports.emitForestLines = ascii_1.emitForestLines;
|
||||
exports.parseFunctionRanges = ascii_1.parseFunctionRanges;
|
||||
exports.parseOffsets = ascii_1.parseOffsets;
|
||||
var clone_1 = require("./clone");
|
||||
exports.cloneFunctionCov = clone_1.cloneFunctionCov;
|
||||
exports.cloneProcessCov = clone_1.cloneProcessCov;
|
||||
exports.cloneScriptCov = clone_1.cloneScriptCov;
|
||||
exports.cloneRangeCov = clone_1.cloneRangeCov;
|
||||
var compare_1 = require("./compare");
|
||||
exports.compareScriptCovs = compare_1.compareScriptCovs;
|
||||
exports.compareFunctionCovs = compare_1.compareFunctionCovs;
|
||||
exports.compareRangeCovs = compare_1.compareRangeCovs;
|
||||
var merge_1 = require("./merge");
|
||||
exports.mergeFunctionCovs = merge_1.mergeFunctionCovs;
|
||||
exports.mergeProcessCovs = merge_1.mergeProcessCovs;
|
||||
exports.mergeScriptCovs = merge_1.mergeScriptCovs;
|
||||
var range_tree_1 = require("./range-tree");
|
||||
exports.RangeTree = range_tree_1.RangeTree;
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxpQ0FBeUY7QUFBaEYsNkJBQUEsVUFBVSxDQUFBO0FBQUUsa0NBQUEsZUFBZSxDQUFBO0FBQUUsc0NBQUEsbUJBQW1CLENBQUE7QUFBRSwrQkFBQSxZQUFZLENBQUE7QUFDdkUsaUNBQTJGO0FBQWxGLG1DQUFBLGdCQUFnQixDQUFBO0FBQUUsa0NBQUEsZUFBZSxDQUFBO0FBQUUsaUNBQUEsY0FBYyxDQUFBO0FBQUUsZ0NBQUEsYUFBYSxDQUFBO0FBQ3pFLHFDQUFxRjtBQUE1RSxzQ0FBQSxpQkFBaUIsQ0FBQTtBQUFFLHdDQUFBLG1CQUFtQixDQUFBO0FBQUUscUNBQUEsZ0JBQWdCLENBQUE7QUFDakUsaUNBQStFO0FBQXRFLG9DQUFBLGlCQUFpQixDQUFBO0FBQUUsbUNBQUEsZ0JBQWdCLENBQUE7QUFBRSxrQ0FBQSxlQUFlLENBQUE7QUFDN0QsMkNBQXlDO0FBQWhDLGlDQUFBLFNBQVMsQ0FBQSIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB7IGVtaXRGb3Jlc3QsIGVtaXRGb3Jlc3RMaW5lcywgcGFyc2VGdW5jdGlvblJhbmdlcywgcGFyc2VPZmZzZXRzIH0gZnJvbSBcIi4vYXNjaWlcIjtcbmV4cG9ydCB7IGNsb25lRnVuY3Rpb25Db3YsIGNsb25lUHJvY2Vzc0NvdiwgY2xvbmVTY3JpcHRDb3YsIGNsb25lUmFuZ2VDb3YgfSBmcm9tIFwiLi9jbG9uZVwiO1xuZXhwb3J0IHsgY29tcGFyZVNjcmlwdENvdnMsIGNvbXBhcmVGdW5jdGlvbkNvdnMsIGNvbXBhcmVSYW5nZUNvdnMgfSBmcm9tIFwiLi9jb21wYXJlXCI7XG5leHBvcnQgeyBtZXJnZUZ1bmN0aW9uQ292cywgbWVyZ2VQcm9jZXNzQ292cywgbWVyZ2VTY3JpcHRDb3ZzIH0gZnJvbSBcIi4vbWVyZ2VcIjtcbmV4cG9ydCB7IFJhbmdlVHJlZSB9IGZyb20gXCIuL3JhbmdlLXRyZWVcIjtcbmV4cG9ydCB7IFByb2Nlc3NDb3YsIFNjcmlwdENvdiwgRnVuY3Rpb25Db3YsIFJhbmdlQ292IH0gZnJvbSBcIi4vdHlwZXNcIjtcbiJdLCJzb3VyY2VSb290IjoiIn0=
|
@ -0,0 +1,7 @@
|
||||
export { emitForest, emitForestLines, parseFunctionRanges, parseOffsets } from "./ascii";
|
||||
export { cloneFunctionCov, cloneProcessCov, cloneScriptCov, cloneRangeCov } from "./clone";
|
||||
export { compareScriptCovs, compareFunctionCovs, compareRangeCovs } from "./compare";
|
||||
export { mergeFunctionCovs, mergeProcessCovs, mergeScriptCovs } from "./merge";
|
||||
export { RangeTree } from "./range-tree";
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMzRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMvRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZW1pdEZvcmVzdCwgZW1pdEZvcmVzdExpbmVzLCBwYXJzZUZ1bmN0aW9uUmFuZ2VzLCBwYXJzZU9mZnNldHMgfSBmcm9tIFwiLi9hc2NpaVwiO1xuZXhwb3J0IHsgY2xvbmVGdW5jdGlvbkNvdiwgY2xvbmVQcm9jZXNzQ292LCBjbG9uZVNjcmlwdENvdiwgY2xvbmVSYW5nZUNvdiB9IGZyb20gXCIuL2Nsb25lXCI7XG5leHBvcnQgeyBjb21wYXJlU2NyaXB0Q292cywgY29tcGFyZUZ1bmN0aW9uQ292cywgY29tcGFyZVJhbmdlQ292cyB9IGZyb20gXCIuL2NvbXBhcmVcIjtcbmV4cG9ydCB7IG1lcmdlRnVuY3Rpb25Db3ZzLCBtZXJnZVByb2Nlc3NDb3ZzLCBtZXJnZVNjcmlwdENvdnMgfSBmcm9tIFwiLi9tZXJnZVwiO1xuZXhwb3J0IHsgUmFuZ2VUcmVlIH0gZnJvbSBcIi4vcmFuZ2UtdHJlZVwiO1xuZXhwb3J0IHsgUHJvY2Vzc0NvdiwgU2NyaXB0Q292LCBGdW5jdGlvbkNvdiwgUmFuZ2VDb3YgfSBmcm9tIFwiLi90eXBlc1wiO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==
|
@ -0,0 +1,39 @@
|
||||
import { FunctionCov, ProcessCov, ScriptCov } from "./types";
|
||||
/**
|
||||
* Merges a list of process coverages.
|
||||
*
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param processCovs Process coverages to merge.
|
||||
* @return Merged process coverage.
|
||||
*/
|
||||
export declare function mergeProcessCovs(processCovs: ReadonlyArray<ProcessCov>): ProcessCov;
|
||||
/**
|
||||
* Merges a list of matching script coverages.
|
||||
*
|
||||
* Scripts are matching if they have the same `url`.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param scriptCovs Process coverages to merge.
|
||||
* @return Merged script coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export declare function mergeScriptCovs(scriptCovs: ReadonlyArray<ScriptCov>): ScriptCov | undefined;
|
||||
/**
|
||||
* Merges a list of matching function coverages.
|
||||
*
|
||||
* Functions are matching if their root ranges have the same span.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param funcCovs Function coverages to merge.
|
||||
* @return Merged function coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export declare function mergeFunctionCovs(funcCovs: ReadonlyArray<FunctionCov>): FunctionCov | undefined;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,53 @@
|
||||
import { RangeTree } from "./range-tree";
|
||||
import { FunctionCov, ProcessCov, ScriptCov } from "./types";
|
||||
/**
|
||||
* Normalizes a process coverage.
|
||||
*
|
||||
* Sorts the scripts alphabetically by `url`.
|
||||
* Reassigns script ids: the script at index `0` receives `"0"`, the script at
|
||||
* index `1` receives `"1"` etc.
|
||||
* This does not normalize the script coverages.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export declare function normalizeProcessCov(processCov: ProcessCov): void;
|
||||
/**
|
||||
* Normalizes a process coverage deeply.
|
||||
*
|
||||
* Normalizes the script coverages deeply, then normalizes the process coverage
|
||||
* itself.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export declare function deepNormalizeProcessCov(processCov: ProcessCov): void;
|
||||
/**
|
||||
* Normalizes a script coverage.
|
||||
*
|
||||
* Sorts the function by root range (pre-order sort).
|
||||
* This does not normalize the function coverages.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export declare function normalizeScriptCov(scriptCov: ScriptCov): void;
|
||||
/**
|
||||
* Normalizes a script coverage deeply.
|
||||
*
|
||||
* Normalizes the function coverages deeply, then normalizes the script coverage
|
||||
* itself.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export declare function deepNormalizeScriptCov(scriptCov: ScriptCov): void;
|
||||
/**
|
||||
* Normalizes a function coverage.
|
||||
*
|
||||
* Sorts the ranges (pre-order sort).
|
||||
* TODO: Tree-based normalization of the ranges.
|
||||
*
|
||||
* @param funcCov Function coverage to normalize.
|
||||
*/
|
||||
export declare function normalizeFunctionCov(funcCov: FunctionCov): void;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export declare function normalizeRangeTree(tree: RangeTree): void;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@bcoe/v8-coverage",
|
||||
"version": "0.2.3",
|
||||
"description": "Helper functions for V8 coverage files.",
|
||||
"author": "Charles Samborski <demurgos@demurgos.net> (https://demurgos.net)",
|
||||
"license": "MIT",
|
||||
"main": "index",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/demurgos/v8-coverage.git"
|
||||
},
|
||||
"homepage": "https://demurgos.github.io/v8-coverage",
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.4",
|
||||
"@types/gulp": "^4.0.5",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mocha": "^5.2.2",
|
||||
"@types/node": "^10.5.4",
|
||||
"chai": "^4.1.2",
|
||||
"codecov": "^3.0.2",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-cli": "^2.0.1",
|
||||
"minimist": "^1.2.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"turbo-gulp": "^0.20.1"
|
||||
},
|
||||
"nyc": {
|
||||
"include": [
|
||||
"build/test/lib/**/*.js",
|
||||
"build/test/lib/**/*.mjs"
|
||||
],
|
||||
"reporter": [
|
||||
"text",
|
||||
"html"
|
||||
],
|
||||
"extension": [
|
||||
".mjs"
|
||||
]
|
||||
},
|
||||
"gitHead": "529387e2bd3e0ba0b9336d80ec563aee593331e1",
|
||||
"private": false
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { RangeCov } from "./types";
|
||||
export declare class RangeTree {
|
||||
start: number;
|
||||
end: number;
|
||||
delta: number;
|
||||
children: RangeTree[];
|
||||
constructor(start: number, end: number, delta: number, children: RangeTree[]);
|
||||
/**
|
||||
* @precodition `ranges` are well-formed and pre-order sorted
|
||||
*/
|
||||
static fromSortedRanges(ranges: ReadonlyArray<RangeCov>): RangeTree | undefined;
|
||||
normalize(): void;
|
||||
/**
|
||||
* @precondition `tree.start < value && value < tree.end`
|
||||
* @return RangeTree Right part
|
||||
*/
|
||||
split(value: number): RangeTree;
|
||||
/**
|
||||
* Get the range coverages corresponding to the tree.
|
||||
*
|
||||
* The ranges are pre-order sorted.
|
||||
*/
|
||||
toRanges(): RangeCov[];
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,62 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"alwaysStrict": true,
|
||||
"charset": "utf8",
|
||||
"checkJs": false,
|
||||
"declaration": true,
|
||||
"disableSizeLimit": false,
|
||||
"downlevelIteration": false,
|
||||
"emitBOM": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": false,
|
||||
"inlineSourceMap": false,
|
||||
"inlineSources": false,
|
||||
"isolatedModules": false,
|
||||
"lib": [
|
||||
"es2017",
|
||||
"esnext.asynciterable"
|
||||
],
|
||||
"locale": "en-us",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"newLine": "lf",
|
||||
"noEmit": false,
|
||||
"noEmitHelpers": false,
|
||||
"noEmitOnError": true,
|
||||
"noErrorTruncation": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noStrictGenericChecks": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitUseStrict": false,
|
||||
"noLib": false,
|
||||
"noResolve": false,
|
||||
"preserveConstEnums": true,
|
||||
"removeComments": false,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"suppressExcessPropertyErrors": false,
|
||||
"suppressImplicitAnyIndexErrors": false,
|
||||
"target": "es2017",
|
||||
"traceResolution": false,
|
||||
"rootDir": "",
|
||||
"outDir": "../../build/lib",
|
||||
"typeRoots": []
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
export interface ProcessCov {
|
||||
result: ScriptCov[];
|
||||
}
|
||||
export interface ScriptCov {
|
||||
scriptId: string;
|
||||
url: string;
|
||||
functions: FunctionCov[];
|
||||
}
|
||||
export interface FunctionCov {
|
||||
functionName: string;
|
||||
ranges: RangeCov[];
|
||||
isBlockCoverage: boolean;
|
||||
}
|
||||
export interface Range {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
}
|
||||
export interface RangeCov {
|
||||
startOffset: number;
|
||||
endOffset: number;
|
||||
count: number;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJ0eXBlcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0NvdiB7XG4gIHJlc3VsdDogU2NyaXB0Q292W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NyaXB0Q292IHtcbiAgc2NyaXB0SWQ6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIGZ1bmN0aW9uczogRnVuY3Rpb25Db3ZbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvbkNvdiB7XG4gIGZ1bmN0aW9uTmFtZTogc3RyaW5nO1xuICByYW5nZXM6IFJhbmdlQ292W107XG4gIGlzQmxvY2tDb3ZlcmFnZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSYW5nZSB7XG4gIHJlYWRvbmx5IHN0YXJ0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGVuZDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJhbmdlQ292IHtcbiAgc3RhcnRPZmZzZXQ6IG51bWJlcjtcbiAgZW5kT2Zmc2V0OiBudW1iZXI7XG4gIGNvdW50OiBudW1iZXI7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9
|
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJ0eXBlcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0NvdiB7XG4gIHJlc3VsdDogU2NyaXB0Q292W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NyaXB0Q292IHtcbiAgc2NyaXB0SWQ6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIGZ1bmN0aW9uczogRnVuY3Rpb25Db3ZbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvbkNvdiB7XG4gIGZ1bmN0aW9uTmFtZTogc3RyaW5nO1xuICByYW5nZXM6IFJhbmdlQ292W107XG4gIGlzQmxvY2tDb3ZlcmFnZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSYW5nZSB7XG4gIHJlYWRvbmx5IHN0YXJ0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGVuZDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJhbmdlQ292IHtcbiAgc3RhcnRPZmZzZXQ6IG51bWJlcjtcbiAgZW5kT2Zmc2V0OiBudW1iZXI7XG4gIGNvdW50OiBudW1iZXI7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9
|
@ -0,0 +1,95 @@
|
||||
import * as buildTools from "turbo-gulp";
|
||||
import { LibTarget, registerLibTasks } from "turbo-gulp/targets/lib";
|
||||
import { MochaTarget, registerMochaTasks } from "turbo-gulp/targets/mocha";
|
||||
|
||||
import gulp from "gulp";
|
||||
import minimist from "minimist";
|
||||
|
||||
interface Options {
|
||||
devDist?: string;
|
||||
}
|
||||
|
||||
const options: Options & minimist.ParsedArgs = minimist(process.argv.slice(2), {
|
||||
string: ["devDist"],
|
||||
default: {devDist: undefined},
|
||||
alias: {devDist: "dev-dist"},
|
||||
});
|
||||
|
||||
const project: buildTools.Project = {
|
||||
root: __dirname,
|
||||
packageJson: "package.json",
|
||||
buildDir: "build",
|
||||
distDir: "dist",
|
||||
srcDir: "src",
|
||||
typescript: {}
|
||||
};
|
||||
|
||||
const lib: LibTarget = {
|
||||
project,
|
||||
name: "lib",
|
||||
srcDir: "src/lib",
|
||||
scripts: ["**/*.ts"],
|
||||
mainModule: "index",
|
||||
dist: {
|
||||
packageJsonMap: (old: buildTools.PackageJson): buildTools.PackageJson => {
|
||||
const version: string = options.devDist !== undefined ? `${old.version}-build.${options.devDist}` : old.version;
|
||||
return <any> {...old, version, scripts: undefined, private: false};
|
||||
},
|
||||
npmPublish: {
|
||||
tag: options.devDist !== undefined ? "next" : "latest",
|
||||
},
|
||||
},
|
||||
tscOptions: {
|
||||
declaration: true,
|
||||
skipLibCheck: true,
|
||||
},
|
||||
typedoc: {
|
||||
dir: "typedoc",
|
||||
name: "Helpers for V8 coverage files",
|
||||
deploy: {
|
||||
repository: "git@github.com:demurgos/v8-coverage.git",
|
||||
branch: "gh-pages",
|
||||
},
|
||||
},
|
||||
copy: [
|
||||
{
|
||||
files: ["**/*.json"],
|
||||
},
|
||||
],
|
||||
clean: {
|
||||
dirs: ["build/lib", "dist/lib"],
|
||||
},
|
||||
};
|
||||
|
||||
const test: MochaTarget = {
|
||||
project,
|
||||
name: "test",
|
||||
srcDir: "src",
|
||||
scripts: ["test/**/*.ts", "lib/**/*.ts", "e2e/*/*.ts"],
|
||||
customTypingsDir: "src/custom-typings",
|
||||
tscOptions: {
|
||||
allowSyntheticDefaultImports: true,
|
||||
esModuleInterop: true,
|
||||
skipLibCheck: true,
|
||||
},
|
||||
// generateTestMain: true,
|
||||
copy: [
|
||||
{
|
||||
src: "e2e",
|
||||
// <project-name>/(project|test-resources)/<any>
|
||||
files: ["*/project/**/*", "*/test-resources/**/*"],
|
||||
dest: "e2e",
|
||||
},
|
||||
],
|
||||
clean: {
|
||||
dirs: ["build/test"],
|
||||
},
|
||||
};
|
||||
|
||||
const libTasks: any = registerLibTasks(gulp, lib);
|
||||
registerMochaTasks(gulp, test);
|
||||
buildTools.projectTasks.registerAll(gulp, project);
|
||||
|
||||
gulp.task("all:tsconfig.json", gulp.parallel("lib:tsconfig.json", "test:tsconfig.json"));
|
||||
gulp.task("dist", libTasks.dist);
|
||||
gulp.task("default", libTasks.dist);
|
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@bcoe/v8-coverage",
|
||||
"version": "0.2.3",
|
||||
"description": "Helper functions for V8 coverage files.",
|
||||
"author": "Charles Samborski <demurgos@demurgos.net> (https://demurgos.net)",
|
||||
"license": "MIT",
|
||||
"main": "dist/lib/index",
|
||||
"types": "dist/lib/index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/demurgos/v8-coverage.git"
|
||||
},
|
||||
"homepage": "https://demurgos.github.io/v8-coverage",
|
||||
"scripts": {
|
||||
"prepare": "gulp all:tsconfig.json && gulp dist",
|
||||
"pretest": "gulp lib:build",
|
||||
"test": "gulp test",
|
||||
"lint": "gulp :lint:fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.4",
|
||||
"@types/gulp": "^4.0.5",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mocha": "^5.2.2",
|
||||
"@types/node": "^10.5.4",
|
||||
"chai": "^4.1.2",
|
||||
"codecov": "^3.0.2",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-cli": "^2.0.1",
|
||||
"minimist": "^1.2.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"turbo-gulp": "^0.20.1"
|
||||
},
|
||||
"nyc": {
|
||||
"include": [
|
||||
"build/test/lib/**/*.js",
|
||||
"build/test/lib/**/*.mjs"
|
||||
],
|
||||
"reporter": [
|
||||
"text",
|
||||
"html"
|
||||
],
|
||||
"extension": [
|
||||
".mjs"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
import { compareRangeCovs } from "./compare";
|
||||
import { RangeCov } from "./types";
|
||||
|
||||
interface ReadonlyRangeTree {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
readonly count: number;
|
||||
readonly children: ReadonlyRangeTree[];
|
||||
}
|
||||
|
||||
export function emitForest(trees: ReadonlyArray<ReadonlyRangeTree>): string {
|
||||
return emitForestLines(trees).join("\n");
|
||||
}
|
||||
|
||||
export function emitForestLines(trees: ReadonlyArray<ReadonlyRangeTree>): string[] {
|
||||
const colMap: Map<number, number> = getColMap(trees);
|
||||
const header: string = emitOffsets(colMap);
|
||||
return [header, ...trees.map(tree => emitTree(tree, colMap).join("\n"))];
|
||||
}
|
||||
|
||||
function getColMap(trees: Iterable<ReadonlyRangeTree>): Map<number, number> {
|
||||
const eventSet: Set<number> = new Set();
|
||||
for (const tree of trees) {
|
||||
const stack: ReadonlyRangeTree[] = [tree];
|
||||
while (stack.length > 0) {
|
||||
const cur: ReadonlyRangeTree = stack.pop()!;
|
||||
eventSet.add(cur.start);
|
||||
eventSet.add(cur.end);
|
||||
for (const child of cur.children) {
|
||||
stack.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
const events: number[] = [...eventSet];
|
||||
events.sort((a, b) => a - b);
|
||||
let maxDigits: number = 1;
|
||||
for (const event of events) {
|
||||
maxDigits = Math.max(maxDigits, event.toString(10).length);
|
||||
}
|
||||
const colWidth: number = maxDigits + 3;
|
||||
const colMap: Map<number, number> = new Map();
|
||||
for (const [i, event] of events.entries()) {
|
||||
colMap.set(event, i * colWidth);
|
||||
}
|
||||
return colMap;
|
||||
}
|
||||
|
||||
function emitTree(tree: ReadonlyRangeTree, colMap: Map<number, number>): string[] {
|
||||
const layers: ReadonlyRangeTree[][] = [];
|
||||
let nextLayer: ReadonlyRangeTree[] = [tree];
|
||||
while (nextLayer.length > 0) {
|
||||
const layer: ReadonlyRangeTree[] = nextLayer;
|
||||
layers.push(layer);
|
||||
nextLayer = [];
|
||||
for (const node of layer) {
|
||||
for (const child of node.children) {
|
||||
nextLayer.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return layers.map(layer => emitTreeLayer(layer, colMap));
|
||||
}
|
||||
|
||||
export function parseFunctionRanges(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
||||
const result: RangeCov[] = [];
|
||||
for (const line of text.split("\n")) {
|
||||
for (const range of parseTreeLayer(line, offsetMap)) {
|
||||
result.push(range);
|
||||
}
|
||||
}
|
||||
result.sort(compareRangeCovs);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param layer Sorted list of disjoint trees.
|
||||
* @param colMap
|
||||
*/
|
||||
function emitTreeLayer(layer: ReadonlyRangeTree[], colMap: Map<number, number>): string {
|
||||
const line: string[] = [];
|
||||
let curIdx: number = 0;
|
||||
for (const {start, end, count} of layer) {
|
||||
const startIdx: number = colMap.get(start)!;
|
||||
const endIdx: number = colMap.get(end)!;
|
||||
if (startIdx > curIdx) {
|
||||
line.push(" ".repeat(startIdx - curIdx));
|
||||
}
|
||||
line.push(emitRange(count, endIdx - startIdx));
|
||||
curIdx = endIdx;
|
||||
}
|
||||
return line.join("");
|
||||
}
|
||||
|
||||
function parseTreeLayer(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
||||
const result: RangeCov[] = [];
|
||||
const regex: RegExp = /\[(\d+)-*\)/gs;
|
||||
while (true) {
|
||||
const match: RegExpMatchArray | null = regex.exec(text);
|
||||
if (match === null) {
|
||||
break;
|
||||
}
|
||||
const startIdx: number = match.index!;
|
||||
const endIdx: number = startIdx + match[0].length;
|
||||
const count: number = parseInt(match[1], 10);
|
||||
const startOffset: number | undefined = offsetMap.get(startIdx);
|
||||
const endOffset: number | undefined = offsetMap.get(endIdx);
|
||||
if (startOffset === undefined || endOffset === undefined) {
|
||||
throw new Error(`Invalid offsets for: ${JSON.stringify(text)}`);
|
||||
}
|
||||
result.push({startOffset, endOffset, count});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function emitRange(count: number, len: number): string {
|
||||
const rangeStart: string = `[${count.toString(10)}`;
|
||||
const rangeEnd: string = ")";
|
||||
const hyphensLen: number = len - (rangeStart.length + rangeEnd.length);
|
||||
const hyphens: string = "-".repeat(Math.max(0, hyphensLen));
|
||||
return `${rangeStart}${hyphens}${rangeEnd}`;
|
||||
}
|
||||
|
||||
function emitOffsets(colMap: Map<number, number>): string {
|
||||
let line: string = "";
|
||||
for (const [event, col] of colMap) {
|
||||
if (line.length < col) {
|
||||
line += " ".repeat(col - line.length);
|
||||
}
|
||||
line += event.toString(10);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
export function parseOffsets(text: string): Map<number, number> {
|
||||
const result: Map<number, number> = new Map();
|
||||
const regex: RegExp = /\d+/gs;
|
||||
while (true) {
|
||||
const match: RegExpExecArray | null = regex.exec(text);
|
||||
if (match === null) {
|
||||
break;
|
||||
}
|
||||
result.set(match.index, parseInt(match[0], 10));
|
||||
}
|
||||
return result;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import { FunctionCov, ProcessCov, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a process coverage.
|
||||
*
|
||||
* @param processCov Process coverage to clone.
|
||||
* @return Cloned process coverage.
|
||||
*/
|
||||
export function cloneProcessCov(processCov: Readonly<ProcessCov>): ProcessCov {
|
||||
const result: ScriptCov[] = [];
|
||||
for (const scriptCov of processCov.result) {
|
||||
result.push(cloneScriptCov(scriptCov));
|
||||
}
|
||||
|
||||
return {
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a script coverage.
|
||||
*
|
||||
* @param scriptCov Script coverage to clone.
|
||||
* @return Cloned script coverage.
|
||||
*/
|
||||
export function cloneScriptCov(scriptCov: Readonly<ScriptCov>): ScriptCov {
|
||||
const functions: FunctionCov[] = [];
|
||||
for (const functionCov of scriptCov.functions) {
|
||||
functions.push(cloneFunctionCov(functionCov));
|
||||
}
|
||||
|
||||
return {
|
||||
scriptId: scriptCov.scriptId,
|
||||
url: scriptCov.url,
|
||||
functions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param functionCov Function coverage to clone.
|
||||
* @return Cloned function coverage.
|
||||
*/
|
||||
export function cloneFunctionCov(functionCov: Readonly<FunctionCov>): FunctionCov {
|
||||
const ranges: RangeCov[] = [];
|
||||
for (const rangeCov of functionCov.ranges) {
|
||||
ranges.push(cloneRangeCov(rangeCov));
|
||||
}
|
||||
|
||||
return {
|
||||
functionName: functionCov.functionName,
|
||||
ranges,
|
||||
isBlockCoverage: functionCov.isBlockCoverage,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of a function coverage.
|
||||
*
|
||||
* @param rangeCov Range coverage to clone.
|
||||
* @return Cloned range coverage.
|
||||
*/
|
||||
export function cloneRangeCov(rangeCov: Readonly<RangeCov>): RangeCov {
|
||||
return {
|
||||
startOffset: rangeCov.startOffset,
|
||||
endOffset: rangeCov.endOffset,
|
||||
count: rangeCov.count,
|
||||
};
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import { FunctionCov, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Compares two script coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of their `url` value (alphabetical sort).
|
||||
*/
|
||||
export function compareScriptCovs(a: Readonly<ScriptCov>, b: Readonly<ScriptCov>): number {
|
||||
if (a.url === b.url) {
|
||||
return 0;
|
||||
} else if (a.url < b.url) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two function coverages.
|
||||
*
|
||||
* The result corresponds to the comparison of the root ranges.
|
||||
*/
|
||||
export function compareFunctionCovs(a: Readonly<FunctionCov>, b: Readonly<FunctionCov>): number {
|
||||
return compareRangeCovs(a.ranges[0], b.ranges[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two range coverages.
|
||||
*
|
||||
* The ranges are first ordered by ascending `startOffset` and then by
|
||||
* descending `endOffset`.
|
||||
* This corresponds to a pre-order tree traversal.
|
||||
*/
|
||||
export function compareRangeCovs(a: Readonly<RangeCov>, b: Readonly<RangeCov>): number {
|
||||
if (a.startOffset !== b.startOffset) {
|
||||
return a.startOffset - b.startOffset;
|
||||
} else {
|
||||
return b.endOffset - a.endOffset;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export { emitForest, emitForestLines, parseFunctionRanges, parseOffsets } from "./ascii";
|
||||
export { cloneFunctionCov, cloneProcessCov, cloneScriptCov, cloneRangeCov } from "./clone";
|
||||
export { compareScriptCovs, compareFunctionCovs, compareRangeCovs } from "./compare";
|
||||
export { mergeFunctionCovs, mergeProcessCovs, mergeScriptCovs } from "./merge";
|
||||
export { RangeTree } from "./range-tree";
|
||||
export { ProcessCov, ScriptCov, FunctionCov, RangeCov } from "./types";
|
@ -0,0 +1,343 @@
|
||||
import {
|
||||
deepNormalizeScriptCov,
|
||||
normalizeFunctionCov,
|
||||
normalizeProcessCov,
|
||||
normalizeRangeTree,
|
||||
normalizeScriptCov,
|
||||
} from "./normalize";
|
||||
import { RangeTree } from "./range-tree";
|
||||
import { FunctionCov, ProcessCov, Range, RangeCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Merges a list of process coverages.
|
||||
*
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param processCovs Process coverages to merge.
|
||||
* @return Merged process coverage.
|
||||
*/
|
||||
export function mergeProcessCovs(processCovs: ReadonlyArray<ProcessCov>): ProcessCov {
|
||||
if (processCovs.length === 0) {
|
||||
return {result: []};
|
||||
}
|
||||
|
||||
const urlToScripts: Map<string, ScriptCov[]> = new Map();
|
||||
for (const processCov of processCovs) {
|
||||
for (const scriptCov of processCov.result) {
|
||||
let scriptCovs: ScriptCov[] | undefined = urlToScripts.get(scriptCov.url);
|
||||
if (scriptCovs === undefined) {
|
||||
scriptCovs = [];
|
||||
urlToScripts.set(scriptCov.url, scriptCovs);
|
||||
}
|
||||
scriptCovs.push(scriptCov);
|
||||
}
|
||||
}
|
||||
|
||||
const result: ScriptCov[] = [];
|
||||
for (const scripts of urlToScripts.values()) {
|
||||
// assert: `scripts.length > 0`
|
||||
result.push(mergeScriptCovs(scripts)!);
|
||||
}
|
||||
const merged: ProcessCov = {result};
|
||||
|
||||
normalizeProcessCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a list of matching script coverages.
|
||||
*
|
||||
* Scripts are matching if they have the same `url`.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param scriptCovs Process coverages to merge.
|
||||
* @return Merged script coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export function mergeScriptCovs(scriptCovs: ReadonlyArray<ScriptCov>): ScriptCov | undefined {
|
||||
if (scriptCovs.length === 0) {
|
||||
return undefined;
|
||||
} else if (scriptCovs.length === 1) {
|
||||
const merged: ScriptCov = scriptCovs[0];
|
||||
deepNormalizeScriptCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
const first: ScriptCov = scriptCovs[0];
|
||||
const scriptId: string = first.scriptId;
|
||||
const url: string = first.url;
|
||||
|
||||
const rangeToFuncs: Map<string, FunctionCov[]> = new Map();
|
||||
for (const scriptCov of scriptCovs) {
|
||||
for (const funcCov of scriptCov.functions) {
|
||||
const rootRange: string = stringifyFunctionRootRange(funcCov);
|
||||
let funcCovs: FunctionCov[] | undefined = rangeToFuncs.get(rootRange);
|
||||
|
||||
if (funcCovs === undefined ||
|
||||
// if the entry in rangeToFuncs is function-level granularity and
|
||||
// the new coverage is block-level, prefer block-level.
|
||||
(!funcCovs[0].isBlockCoverage && funcCov.isBlockCoverage)) {
|
||||
funcCovs = [];
|
||||
rangeToFuncs.set(rootRange, funcCovs);
|
||||
} else if (funcCovs[0].isBlockCoverage && !funcCov.isBlockCoverage) {
|
||||
// if the entry in rangeToFuncs is block-level granularity, we should
|
||||
// not append function level granularity.
|
||||
continue;
|
||||
}
|
||||
funcCovs.push(funcCov);
|
||||
}
|
||||
}
|
||||
|
||||
const functions: FunctionCov[] = [];
|
||||
for (const funcCovs of rangeToFuncs.values()) {
|
||||
// assert: `funcCovs.length > 0`
|
||||
functions.push(mergeFunctionCovs(funcCovs)!);
|
||||
}
|
||||
|
||||
const merged: ScriptCov = {scriptId, url, functions};
|
||||
normalizeScriptCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the root range of the function.
|
||||
*
|
||||
* This string can be used to match function with same root range.
|
||||
* The string is derived from the start and end offsets of the root range of
|
||||
* the function.
|
||||
* This assumes that `ranges` is non-empty (true for valid function coverages).
|
||||
*
|
||||
* @param funcCov Function coverage with the range to stringify
|
||||
* @internal
|
||||
*/
|
||||
function stringifyFunctionRootRange(funcCov: Readonly<FunctionCov>): string {
|
||||
const rootRange: RangeCov = funcCov.ranges[0];
|
||||
return `${rootRange.startOffset.toString(10)};${rootRange.endOffset.toString(10)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a list of matching function coverages.
|
||||
*
|
||||
* Functions are matching if their root ranges have the same span.
|
||||
* The result is normalized.
|
||||
* The input values may be mutated, it is not safe to use them after passing
|
||||
* them to this function.
|
||||
* The computation is synchronous.
|
||||
*
|
||||
* @param funcCovs Function coverages to merge.
|
||||
* @return Merged function coverage, or `undefined` if the input list was empty.
|
||||
*/
|
||||
export function mergeFunctionCovs(funcCovs: ReadonlyArray<FunctionCov>): FunctionCov | undefined {
|
||||
if (funcCovs.length === 0) {
|
||||
return undefined;
|
||||
} else if (funcCovs.length === 1) {
|
||||
const merged: FunctionCov = funcCovs[0];
|
||||
normalizeFunctionCov(merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
const functionName: string = funcCovs[0].functionName;
|
||||
|
||||
const trees: RangeTree[] = [];
|
||||
for (const funcCov of funcCovs) {
|
||||
// assert: `fn.ranges.length > 0`
|
||||
// assert: `fn.ranges` is sorted
|
||||
trees.push(RangeTree.fromSortedRanges(funcCov.ranges)!);
|
||||
}
|
||||
|
||||
// assert: `trees.length > 0`
|
||||
const mergedTree: RangeTree = mergeRangeTrees(trees)!;
|
||||
normalizeRangeTree(mergedTree);
|
||||
const ranges: RangeCov[] = mergedTree.toRanges();
|
||||
const isBlockCoverage: boolean = !(ranges.length === 1 && ranges[0].count === 0);
|
||||
|
||||
const merged: FunctionCov = {functionName, ranges, isBlockCoverage};
|
||||
// assert: `merged` is normalized
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @precondition Same `start` and `end` for all the trees
|
||||
*/
|
||||
function mergeRangeTrees(trees: ReadonlyArray<RangeTree>): RangeTree | undefined {
|
||||
if (trees.length <= 1) {
|
||||
return trees[0];
|
||||
}
|
||||
const first: RangeTree = trees[0];
|
||||
let delta: number = 0;
|
||||
for (const tree of trees) {
|
||||
delta += tree.delta;
|
||||
}
|
||||
const children: RangeTree[] = mergeRangeTreeChildren(trees);
|
||||
return new RangeTree(first.start, first.end, delta, children);
|
||||
}
|
||||
|
||||
class RangeTreeWithParent {
|
||||
readonly parentIndex: number;
|
||||
readonly tree: RangeTree;
|
||||
|
||||
constructor(parentIndex: number, tree: RangeTree) {
|
||||
this.parentIndex = parentIndex;
|
||||
this.tree = tree;
|
||||
}
|
||||
}
|
||||
|
||||
class StartEvent {
|
||||
readonly offset: number;
|
||||
readonly trees: RangeTreeWithParent[];
|
||||
|
||||
constructor(offset: number, trees: RangeTreeWithParent[]) {
|
||||
this.offset = offset;
|
||||
this.trees = trees;
|
||||
}
|
||||
|
||||
static compare(a: StartEvent, b: StartEvent): number {
|
||||
return a.offset - b.offset;
|
||||
}
|
||||
}
|
||||
|
||||
class StartEventQueue {
|
||||
private readonly queue: StartEvent[];
|
||||
private nextIndex: number;
|
||||
private pendingOffset: number;
|
||||
private pendingTrees: RangeTreeWithParent[] | undefined;
|
||||
|
||||
private constructor(queue: StartEvent[]) {
|
||||
this.queue = queue;
|
||||
this.nextIndex = 0;
|
||||
this.pendingOffset = 0;
|
||||
this.pendingTrees = undefined;
|
||||
}
|
||||
|
||||
static fromParentTrees(parentTrees: ReadonlyArray<RangeTree>): StartEventQueue {
|
||||
const startToTrees: Map<number, RangeTreeWithParent[]> = new Map();
|
||||
for (const [parentIndex, parentTree] of parentTrees.entries()) {
|
||||
for (const child of parentTree.children) {
|
||||
let trees: RangeTreeWithParent[] | undefined = startToTrees.get(child.start);
|
||||
if (trees === undefined) {
|
||||
trees = [];
|
||||
startToTrees.set(child.start, trees);
|
||||
}
|
||||
trees.push(new RangeTreeWithParent(parentIndex, child));
|
||||
}
|
||||
}
|
||||
const queue: StartEvent[] = [];
|
||||
for (const [startOffset, trees] of startToTrees) {
|
||||
queue.push(new StartEvent(startOffset, trees));
|
||||
}
|
||||
queue.sort(StartEvent.compare);
|
||||
return new StartEventQueue(queue);
|
||||
}
|
||||
|
||||
setPendingOffset(offset: number): void {
|
||||
this.pendingOffset = offset;
|
||||
}
|
||||
|
||||
pushPendingTree(tree: RangeTreeWithParent): void {
|
||||
if (this.pendingTrees === undefined) {
|
||||
this.pendingTrees = [];
|
||||
}
|
||||
this.pendingTrees.push(tree);
|
||||
}
|
||||
|
||||
next(): StartEvent | undefined {
|
||||
const pendingTrees: RangeTreeWithParent[] | undefined = this.pendingTrees;
|
||||
const nextEvent: StartEvent | undefined = this.queue[this.nextIndex];
|
||||
if (pendingTrees === undefined) {
|
||||
this.nextIndex++;
|
||||
return nextEvent;
|
||||
} else if (nextEvent === undefined) {
|
||||
this.pendingTrees = undefined;
|
||||
return new StartEvent(this.pendingOffset, pendingTrees);
|
||||
} else {
|
||||
if (this.pendingOffset < nextEvent.offset) {
|
||||
this.pendingTrees = undefined;
|
||||
return new StartEvent(this.pendingOffset, pendingTrees);
|
||||
} else {
|
||||
if (this.pendingOffset === nextEvent.offset) {
|
||||
this.pendingTrees = undefined;
|
||||
for (const tree of pendingTrees) {
|
||||
nextEvent.trees.push(tree);
|
||||
}
|
||||
}
|
||||
this.nextIndex++;
|
||||
return nextEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mergeRangeTreeChildren(parentTrees: ReadonlyArray<RangeTree>): RangeTree[] {
|
||||
const result: RangeTree[] = [];
|
||||
const startEventQueue: StartEventQueue = StartEventQueue.fromParentTrees(parentTrees);
|
||||
const parentToNested: Map<number, RangeTree[]> = new Map();
|
||||
let openRange: Range | undefined;
|
||||
|
||||
while (true) {
|
||||
const event: StartEvent | undefined = startEventQueue.next();
|
||||
if (event === undefined) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (openRange !== undefined && openRange.end <= event.offset) {
|
||||
result.push(nextChild(openRange, parentToNested));
|
||||
openRange = undefined;
|
||||
}
|
||||
|
||||
if (openRange === undefined) {
|
||||
let openRangeEnd: number = event.offset + 1;
|
||||
for (const {parentIndex, tree} of event.trees) {
|
||||
openRangeEnd = Math.max(openRangeEnd, tree.end);
|
||||
insertChild(parentToNested, parentIndex, tree);
|
||||
}
|
||||
startEventQueue.setPendingOffset(openRangeEnd);
|
||||
openRange = {start: event.offset, end: openRangeEnd};
|
||||
} else {
|
||||
for (const {parentIndex, tree} of event.trees) {
|
||||
if (tree.end > openRange.end) {
|
||||
const right: RangeTree = tree.split(openRange.end);
|
||||
startEventQueue.pushPendingTree(new RangeTreeWithParent(parentIndex, right));
|
||||
}
|
||||
insertChild(parentToNested, parentIndex, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (openRange !== undefined) {
|
||||
result.push(nextChild(openRange, parentToNested));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function insertChild(parentToNested: Map<number, RangeTree[]>, parentIndex: number, tree: RangeTree): void {
|
||||
let nested: RangeTree[] | undefined = parentToNested.get(parentIndex);
|
||||
if (nested === undefined) {
|
||||
nested = [];
|
||||
parentToNested.set(parentIndex, nested);
|
||||
}
|
||||
nested.push(tree);
|
||||
}
|
||||
|
||||
function nextChild(openRange: Range, parentToNested: Map<number, RangeTree[]>): RangeTree {
|
||||
const matchingTrees: RangeTree[] = [];
|
||||
|
||||
for (const nested of parentToNested.values()) {
|
||||
if (nested.length === 1 && nested[0].start === openRange.start && nested[0].end === openRange.end) {
|
||||
matchingTrees.push(nested[0]);
|
||||
} else {
|
||||
matchingTrees.push(new RangeTree(
|
||||
openRange.start,
|
||||
openRange.end,
|
||||
0,
|
||||
nested,
|
||||
));
|
||||
}
|
||||
}
|
||||
parentToNested.clear();
|
||||
return mergeRangeTrees(matchingTrees)!;
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
import { compareFunctionCovs, compareRangeCovs, compareScriptCovs } from "./compare";
|
||||
import { RangeTree } from "./range-tree";
|
||||
import { FunctionCov, ProcessCov, ScriptCov } from "./types";
|
||||
|
||||
/**
|
||||
* Normalizes a process coverage.
|
||||
*
|
||||
* Sorts the scripts alphabetically by `url`.
|
||||
* Reassigns script ids: the script at index `0` receives `"0"`, the script at
|
||||
* index `1` receives `"1"` etc.
|
||||
* This does not normalize the script coverages.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export function normalizeProcessCov(processCov: ProcessCov): void {
|
||||
processCov.result.sort(compareScriptCovs);
|
||||
for (const [scriptId, scriptCov] of processCov.result.entries()) {
|
||||
scriptCov.scriptId = scriptId.toString(10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a process coverage deeply.
|
||||
*
|
||||
* Normalizes the script coverages deeply, then normalizes the process coverage
|
||||
* itself.
|
||||
*
|
||||
* @param processCov Process coverage to normalize.
|
||||
*/
|
||||
export function deepNormalizeProcessCov(processCov: ProcessCov): void {
|
||||
for (const scriptCov of processCov.result) {
|
||||
deepNormalizeScriptCov(scriptCov);
|
||||
}
|
||||
normalizeProcessCov(processCov);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a script coverage.
|
||||
*
|
||||
* Sorts the function by root range (pre-order sort).
|
||||
* This does not normalize the function coverages.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export function normalizeScriptCov(scriptCov: ScriptCov): void {
|
||||
scriptCov.functions.sort(compareFunctionCovs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a script coverage deeply.
|
||||
*
|
||||
* Normalizes the function coverages deeply, then normalizes the script coverage
|
||||
* itself.
|
||||
*
|
||||
* @param scriptCov Script coverage to normalize.
|
||||
*/
|
||||
export function deepNormalizeScriptCov(scriptCov: ScriptCov): void {
|
||||
for (const funcCov of scriptCov.functions) {
|
||||
normalizeFunctionCov(funcCov);
|
||||
}
|
||||
normalizeScriptCov(scriptCov);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a function coverage.
|
||||
*
|
||||
* Sorts the ranges (pre-order sort).
|
||||
* TODO: Tree-based normalization of the ranges.
|
||||
*
|
||||
* @param funcCov Function coverage to normalize.
|
||||
*/
|
||||
export function normalizeFunctionCov(funcCov: FunctionCov): void {
|
||||
funcCov.ranges.sort(compareRangeCovs);
|
||||
const tree: RangeTree = RangeTree.fromSortedRanges(funcCov.ranges)!;
|
||||
normalizeRangeTree(tree);
|
||||
funcCov.ranges = tree.toRanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function normalizeRangeTree(tree: RangeTree): void {
|
||||
tree.normalize();
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
import { RangeCov } from "./types";
|
||||
|
||||
export class RangeTree {
|
||||
start: number;
|
||||
end: number;
|
||||
delta: number;
|
||||
children: RangeTree[];
|
||||
|
||||
constructor(
|
||||
start: number,
|
||||
end: number,
|
||||
delta: number,
|
||||
children: RangeTree[],
|
||||
) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.delta = delta;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @precodition `ranges` are well-formed and pre-order sorted
|
||||
*/
|
||||
static fromSortedRanges(ranges: ReadonlyArray<RangeCov>): RangeTree | undefined {
|
||||
let root: RangeTree | undefined;
|
||||
// Stack of parent trees and parent counts.
|
||||
const stack: [RangeTree, number][] = [];
|
||||
for (const range of ranges) {
|
||||
const node: RangeTree = new RangeTree(range.startOffset, range.endOffset, range.count, []);
|
||||
if (root === undefined) {
|
||||
root = node;
|
||||
stack.push([node, range.count]);
|
||||
continue;
|
||||
}
|
||||
let parent: RangeTree;
|
||||
let parentCount: number;
|
||||
while (true) {
|
||||
[parent, parentCount] = stack[stack.length - 1];
|
||||
// assert: `top !== undefined` (the ranges are sorted)
|
||||
if (range.startOffset < parent.end) {
|
||||
break;
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
node.delta -= parentCount;
|
||||
parent.children.push(node);
|
||||
stack.push([node, range.count]);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
normalize(): void {
|
||||
const children: RangeTree[] = [];
|
||||
let curEnd: number;
|
||||
let head: RangeTree | undefined;
|
||||
const tail: RangeTree[] = [];
|
||||
for (const child of this.children) {
|
||||
if (head === undefined) {
|
||||
head = child;
|
||||
} else if (child.delta === head.delta && child.start === curEnd!) {
|
||||
tail.push(child);
|
||||
} else {
|
||||
endChain();
|
||||
head = child;
|
||||
}
|
||||
curEnd = child.end;
|
||||
}
|
||||
if (head !== undefined) {
|
||||
endChain();
|
||||
}
|
||||
|
||||
if (children.length === 1) {
|
||||
const child: RangeTree = children[0];
|
||||
if (child.start === this.start && child.end === this.end) {
|
||||
this.delta += child.delta;
|
||||
this.children = child.children;
|
||||
// `.lazyCount` is zero for both (both are after normalization)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.children = children;
|
||||
|
||||
function endChain(): void {
|
||||
if (tail.length !== 0) {
|
||||
head!.end = tail[tail.length - 1].end;
|
||||
for (const tailTree of tail) {
|
||||
for (const subChild of tailTree.children) {
|
||||
subChild.delta += tailTree.delta - head!.delta;
|
||||
head!.children.push(subChild);
|
||||
}
|
||||
}
|
||||
tail.length = 0;
|
||||
}
|
||||
head!.normalize();
|
||||
children.push(head!);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @precondition `tree.start < value && value < tree.end`
|
||||
* @return RangeTree Right part
|
||||
*/
|
||||
split(value: number): RangeTree {
|
||||
let leftChildLen: number = this.children.length;
|
||||
let mid: RangeTree | undefined;
|
||||
|
||||
// TODO(perf): Binary search (check overhead)
|
||||
for (let i: number = 0; i < this.children.length; i++) {
|
||||
const child: RangeTree = this.children[i];
|
||||
if (child.start < value && value < child.end) {
|
||||
mid = child.split(value);
|
||||
leftChildLen = i + 1;
|
||||
break;
|
||||
} else if (child.start >= value) {
|
||||
leftChildLen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const rightLen: number = this.children.length - leftChildLen;
|
||||
const rightChildren: RangeTree[] = this.children.splice(leftChildLen, rightLen);
|
||||
if (mid !== undefined) {
|
||||
rightChildren.unshift(mid);
|
||||
}
|
||||
const result: RangeTree = new RangeTree(
|
||||
value,
|
||||
this.end,
|
||||
this.delta,
|
||||
rightChildren,
|
||||
);
|
||||
this.end = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range coverages corresponding to the tree.
|
||||
*
|
||||
* The ranges are pre-order sorted.
|
||||
*/
|
||||
toRanges(): RangeCov[] {
|
||||
const ranges: RangeCov[] = [];
|
||||
// Stack of parent trees and counts.
|
||||
const stack: [RangeTree, number][] = [[this, 0]];
|
||||
while (stack.length > 0) {
|
||||
const [cur, parentCount]: [RangeTree, number] = stack.pop()!;
|
||||
const count: number = parentCount + cur.delta;
|
||||
ranges.push({startOffset: cur.start, endOffset: cur.end, count});
|
||||
for (let i: number = cur.children.length - 1; i >= 0; i--) {
|
||||
stack.push([cur.children[i], count]);
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
export interface ProcessCov {
|
||||
result: ScriptCov[];
|
||||
}
|
||||
|
||||
export interface ScriptCov {
|
||||
scriptId: string;
|
||||
url: string;
|
||||
functions: FunctionCov[];
|
||||
}
|
||||
|
||||
export interface FunctionCov {
|
||||
functionName: string;
|
||||
ranges: RangeCov[];
|
||||
isBlockCoverage: boolean;
|
||||
}
|
||||
|
||||
export interface Range {
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
}
|
||||
|
||||
export interface RangeCov {
|
||||
startOffset: number;
|
||||
endOffset: number;
|
||||
count: number;
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
import chai from "chai";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { FunctionCov, mergeFunctionCovs, mergeProcessCovs, mergeScriptCovs, ProcessCov, ScriptCov } from "../lib";
|
||||
|
||||
const REPO_ROOT: string = path.join(__dirname, "..", "..", "..", "..");
|
||||
const BENCHES_INPUT_DIR: string = path.join(REPO_ROOT, "benches");
|
||||
const BENCHES_DIR: string = path.join(REPO_ROOT, "test-data", "merge", "benches");
|
||||
const RANGES_DIR: string = path.join(REPO_ROOT, "test-data", "merge", "ranges");
|
||||
const BENCHES_TIMEOUT: number = 20000; // 20sec
|
||||
|
||||
interface MergeRangeItem {
|
||||
name: string;
|
||||
status: "run" | "skip" | "only";
|
||||
inputs: ProcessCov[];
|
||||
expected: ProcessCov;
|
||||
}
|
||||
|
||||
const FIXTURES_DIR: string = path.join(REPO_ROOT, "test-data", "bugs");
|
||||
function loadFixture(name: string) {
|
||||
const content: string = fs.readFileSync(
|
||||
path.resolve(FIXTURES_DIR, `${name}.json`),
|
||||
{encoding: "UTF-8"},
|
||||
);
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
describe("merge", () => {
|
||||
describe("Various", () => {
|
||||
it("accepts empty arrays for `mergeProcessCovs`", () => {
|
||||
const inputs: ProcessCov[] = [];
|
||||
const expected: ProcessCov = {result: []};
|
||||
const actual: ProcessCov = mergeProcessCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it("accepts empty arrays for `mergeScriptCovs`", () => {
|
||||
const inputs: ScriptCov[] = [];
|
||||
const expected: ScriptCov | undefined = undefined;
|
||||
const actual: ScriptCov | undefined = mergeScriptCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it("accepts empty arrays for `mergeFunctionCovs`", () => {
|
||||
const inputs: FunctionCov[] = [];
|
||||
const expected: FunctionCov | undefined = undefined;
|
||||
const actual: FunctionCov | undefined = mergeFunctionCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it("accepts arrays with a single item for `mergeProcessCovs`", () => {
|
||||
const inputs: ProcessCov[] = [
|
||||
{
|
||||
result: [
|
||||
{
|
||||
scriptId: "123",
|
||||
url: "/lib.js",
|
||||
functions: [
|
||||
{
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 2, count: 1},
|
||||
{startOffset: 2, endOffset: 3, count: 1},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const expected: ProcessCov = {
|
||||
result: [
|
||||
{
|
||||
scriptId: "0",
|
||||
url: "/lib.js",
|
||||
functions: [
|
||||
{
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 3, count: 1},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const actual: ProcessCov = mergeProcessCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
describe("mergeProcessCovs", () => {
|
||||
// see: https://github.com/demurgos/v8-coverage/issues/2
|
||||
it("handles function coverage merged into block coverage", () => {
|
||||
const blockCoverage: ProcessCov = loadFixture("issue-2-block-coverage");
|
||||
const functionCoverage: ProcessCov = loadFixture("issue-2-func-coverage");
|
||||
const inputs: ProcessCov[] = [
|
||||
functionCoverage,
|
||||
blockCoverage,
|
||||
];
|
||||
const expected: ProcessCov = loadFixture("issue-2-expected");
|
||||
const actual: ProcessCov = mergeProcessCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
// see: https://github.com/demurgos/v8-coverage/issues/2
|
||||
it("handles block coverage merged into function coverage", () => {
|
||||
const blockCoverage: ProcessCov = loadFixture("issue-2-block-coverage");
|
||||
const functionCoverage: ProcessCov = loadFixture("issue-2-func-coverage");
|
||||
const inputs: ProcessCov[] = [
|
||||
blockCoverage,
|
||||
functionCoverage,
|
||||
];
|
||||
const expected: ProcessCov = loadFixture("issue-2-expected");
|
||||
const actual: ProcessCov = mergeProcessCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts arrays with a single item for `mergeScriptCovs`", () => {
|
||||
const inputs: ScriptCov[] = [
|
||||
{
|
||||
scriptId: "123",
|
||||
url: "/lib.js",
|
||||
functions: [
|
||||
{
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 2, count: 1},
|
||||
{startOffset: 2, endOffset: 3, count: 1},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const expected: ScriptCov | undefined = {
|
||||
scriptId: "123",
|
||||
url: "/lib.js",
|
||||
functions: [
|
||||
{
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 3, count: 1},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const actual: ScriptCov | undefined = mergeScriptCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it("accepts arrays with a single item for `mergeFunctionCovs`", () => {
|
||||
const inputs: FunctionCov[] = [
|
||||
{
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 2, count: 1},
|
||||
{startOffset: 2, endOffset: 3, count: 1},
|
||||
],
|
||||
},
|
||||
];
|
||||
const expected: FunctionCov = {
|
||||
functionName: "test",
|
||||
isBlockCoverage: true,
|
||||
ranges: [
|
||||
{startOffset: 0, endOffset: 4, count: 2},
|
||||
{startOffset: 1, endOffset: 3, count: 1},
|
||||
],
|
||||
};
|
||||
const actual: FunctionCov | undefined = mergeFunctionCovs(inputs);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ranges", () => {
|
||||
for (const sourceFile of getSourceFiles()) {
|
||||
const relPath: string = path.relative(RANGES_DIR, sourceFile);
|
||||
describe(relPath, () => {
|
||||
const content: string = fs.readFileSync(sourceFile, {encoding: "UTF-8"});
|
||||
const items: MergeRangeItem[] = JSON.parse(content);
|
||||
for (const item of items) {
|
||||
const test: () => void = () => {
|
||||
const actual: ProcessCov | undefined = mergeProcessCovs(item.inputs);
|
||||
chai.assert.deepEqual(actual, item.expected);
|
||||
};
|
||||
switch (item.status) {
|
||||
case "run":
|
||||
it(item.name, test);
|
||||
break;
|
||||
case "only":
|
||||
it.only(item.name, test);
|
||||
break;
|
||||
case "skip":
|
||||
it.skip(item.name, test);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected status: ${item.status}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("benches", () => {
|
||||
for (const bench of getBenches()) {
|
||||
const BENCHES_TO_SKIP: Set<string> = new Set();
|
||||
if (process.env.CI === "true") {
|
||||
// Skip very large benchmarks when running continuous integration
|
||||
BENCHES_TO_SKIP.add("node@10.11.0");
|
||||
BENCHES_TO_SKIP.add("npm@6.4.1");
|
||||
}
|
||||
|
||||
const name: string = path.basename(bench);
|
||||
|
||||
if (BENCHES_TO_SKIP.has(name)) {
|
||||
it.skip(`${name} (skipped: too large for CI)`, testBench);
|
||||
} else {
|
||||
it(name, testBench);
|
||||
}
|
||||
|
||||
async function testBench(this: Mocha.Context) {
|
||||
this.timeout(BENCHES_TIMEOUT);
|
||||
|
||||
const inputFileNames: string[] = await fs.promises.readdir(bench);
|
||||
const inputPromises: Promise<ProcessCov>[] = [];
|
||||
for (const inputFileName of inputFileNames) {
|
||||
const resolved: string = path.join(bench, inputFileName);
|
||||
inputPromises.push(fs.promises.readFile(resolved).then(buffer => JSON.parse(buffer.toString("UTF-8"))));
|
||||
}
|
||||
const inputs: ProcessCov[] = await Promise.all(inputPromises);
|
||||
const expectedPath: string = path.join(BENCHES_DIR, `${name}.json`);
|
||||
const expectedContent: string = await fs.promises.readFile(expectedPath, {encoding: "UTF-8"}) as string;
|
||||
const expected: ProcessCov = JSON.parse(expectedContent);
|
||||
const startTime: number = Date.now();
|
||||
const actual: ProcessCov | undefined = mergeProcessCovs(inputs);
|
||||
const endTime: number = Date.now();
|
||||
console.error(`Time (${name}): ${(endTime - startTime) / 1000}`);
|
||||
chai.assert.deepEqual(actual, expected);
|
||||
console.error(`OK: ${name}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getSourceFiles() {
|
||||
return getSourcesFrom(RANGES_DIR);
|
||||
|
||||
function* getSourcesFrom(dir: string): Iterable<string> {
|
||||
const names: string[] = fs.readdirSync(dir);
|
||||
for (const name of names) {
|
||||
const resolved: string = path.join(dir, name);
|
||||
const stat: fs.Stats = fs.statSync(resolved);
|
||||
if (stat.isDirectory()) {
|
||||
yield* getSourcesFrom(dir);
|
||||
} else {
|
||||
yield resolved;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* getBenches(): Iterable<string> {
|
||||
const names: string[] = fs.readdirSync(BENCHES_INPUT_DIR);
|
||||
for (const name of names) {
|
||||
const resolved: string = path.join(BENCHES_INPUT_DIR, name);
|
||||
const stat: fs.Stats = fs.statSync(resolved);
|
||||
if (stat.isDirectory()) {
|
||||
yield resolved;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"alwaysStrict": true,
|
||||
"charset": "utf8",
|
||||
"checkJs": false,
|
||||
"declaration": false,
|
||||
"disableSizeLimit": false,
|
||||
"downlevelIteration": false,
|
||||
"emitBOM": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": false,
|
||||
"inlineSourceMap": false,
|
||||
"inlineSources": false,
|
||||
"isolatedModules": false,
|
||||
"lib": [
|
||||
"es2017",
|
||||
"esnext.asynciterable"
|
||||
],
|
||||
"locale": "en-us",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"newLine": "lf",
|
||||
"noEmit": false,
|
||||
"noEmitHelpers": false,
|
||||
"noEmitOnError": true,
|
||||
"noErrorTruncation": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noStrictGenericChecks": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": false,
|
||||
"noImplicitUseStrict": false,
|
||||
"noLib": false,
|
||||
"noResolve": false,
|
||||
"preserveConstEnums": false,
|
||||
"removeComments": false,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"suppressExcessPropertyErrors": false,
|
||||
"suppressImplicitAnyIndexErrors": false,
|
||||
"target": "es2017",
|
||||
"traceResolution": false,
|
||||
"typeRoots": [
|
||||
"src/lib/custom-typings",
|
||||
"node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
../which/bin/node-which
|
@ -0,0 +1 @@
|
||||
../rimraf/bin.js
|
@ -0,0 +1 @@
|
||||
../json5/lib/cli.js
|
@ -0,0 +1 @@
|
||||
../json5/lib/cli.js
|
@ -0,0 +1,23 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2018 Aseem Kishore, and [others].
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
[others]: https://github.com/json5/json5/contributors
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';var _fs=require('fs');var _fs2=_interopRequireDefault(_fs);var _path=require('path');var _path2=_interopRequireDefault(_path);var _minimist=require('minimist');var _minimist2=_interopRequireDefault(_minimist);var _package=require('../package.json');var _package2=_interopRequireDefault(_package);var _=require('./');var _2=_interopRequireDefault(_);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var argv=(0,_minimist2.default)(process.argv.slice(2),{alias:{'convert':'c','space':'s','validate':'v','out-file':'o','version':'V','help':'h'},boolean:['convert','validate','version','help'],string:['space','out-file']});if(argv.version){version()}else if(argv.help){usage()}else{var inFilename=argv._[0];var readStream=void 0;if(inFilename){readStream=_fs2.default.createReadStream(inFilename)}else{readStream=process.stdin}var json5='';readStream.on('data',function(data){json5+=data});readStream.on('end',function(){var space=void 0;if(argv.space==='t'||argv.space==='tab'){space='\t'}else{space=Number(argv.space)}var value=void 0;try{value=_2.default.parse(json5);if(!argv.validate){var json=JSON.stringify(value,null,space);var writeStream=void 0;if(argv.convert&&inFilename&&!argv.o){var parsedFilename=_path2.default.parse(inFilename);var outFilename=_path2.default.format(Object.assign(parsedFilename,{base:_path2.default.basename(parsedFilename.base,parsedFilename.ext)+'.json'}));writeStream=_fs2.default.createWriteStream(outFilename)}else if(argv.o){writeStream=_fs2.default.createWriteStream(argv.o)}else{writeStream=process.stdout}writeStream.write(json)}}catch(err){console.error(err.message);process.exit(1)}})}function version(){console.log(_package2.default.version)}function usage(){console.log('\n Usage: json5 [options] <file>\n\n If <file> is not provided, then STDIN is used.\n\n Options:\n\n -s, --space The number of spaces to indent or \'t\' for tabs\n -o, --out-file [file] Output to the specified file, otherwise STDOUT\n -v, --validate Validate JSON5 but do not output JSON\n -V, --version Output the version number\n -h, --help Output usage information')}
|
@ -0,0 +1 @@
|
||||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var _parse=require('./parse');var _parse2=_interopRequireDefault(_parse);var _stringify=require('./stringify');var _stringify2=_interopRequireDefault(_stringify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}exports.default={parse:_parse2.default,stringify:_stringify2.default};module.exports=exports['default'];
|
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
'use strict';var _fs=require('fs');var _fs2=_interopRequireDefault(_fs);var _=require('./');var _2=_interopRequireDefault(_);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}require.extensions['.json5']=function(module,filename){var content=_fs2.default.readFileSync(filename,'utf8');try{module.exports=_2.default.parse(content)}catch(err){err.message=filename+': '+err.message;throw err}};
|
@ -0,0 +1 @@
|
||||
"use strict";require("./register");console.warn("'json5/require' is deprecated. Please use 'json5/register' instead.");
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});exports.isSpaceSeparator=isSpaceSeparator;exports.isIdStartChar=isIdStartChar;exports.isIdContinueChar=isIdContinueChar;exports.isDigit=isDigit;exports.isHexDigit=isHexDigit;var _unicode=require('../lib/unicode');var unicode=_interopRequireWildcard(_unicode);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key]}}newObj.default=obj;return newObj}}function isSpaceSeparator(c){return unicode.Space_Separator.test(c)}function isIdStartChar(c){return c>='a'&&c<='z'||c>='A'&&c<='Z'||c==='$'||c==='_'||unicode.ID_Start.test(c)}function isIdContinueChar(c){return c>='a'&&c<='z'||c>='A'&&c<='Z'||c>='0'&&c<='9'||c==='$'||c==='_'||c==='\u200C'||c==='\u200D'||unicode.ID_Continue.test(c)}function isDigit(c){return /[0-9]/.test(c)}function isHexDigit(c){return /[0-9A-Fa-f]/.test(c)}
|
@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "json5",
|
||||
"version": "1.0.2",
|
||||
"description": "JSON for humans.",
|
||||
"main": "lib/index.js",
|
||||
"bin": "lib/cli.js",
|
||||
"browser": "dist/index.js",
|
||||
"files": [
|
||||
"lib/",
|
||||
"dist/"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "babel-node build/build.js && babel src -d lib && rollup -c",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"lint": "eslint --fix build src",
|
||||
"prepublishOnly": "npm run lint && npm test && npm run production",
|
||||
"pretest": "cross-env NODE_ENV=test npm run build",
|
||||
"preversion": "npm run lint && npm test && npm run production",
|
||||
"production": "cross-env NODE_ENV=production npm run build",
|
||||
"test": "nyc --reporter=html --reporter=text mocha"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/json5/json5.git"
|
||||
},
|
||||
"keywords": [
|
||||
"json",
|
||||
"json5",
|
||||
"es5",
|
||||
"es2015",
|
||||
"ecmascript"
|
||||
],
|
||||
"author": "Aseem Kishore <aseem.kishore@gmail.com>",
|
||||
"contributors": [
|
||||
"Max Nanasy <max.nanasy@gmail.com>",
|
||||
"Andrew Eisenberg <andrew@eisenberg.as>",
|
||||
"Jordan Tucker <jordanbtucker@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/json5/json5/issues"
|
||||
},
|
||||
"homepage": "http://json5.org/",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-add-module-exports": "^0.2.1",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-istanbul": "^4.1.5",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-register": "^6.26.0",
|
||||
"babelrc-rollup": "^3.0.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"cross-env": "^5.1.4",
|
||||
"del": "^3.0.0",
|
||||
"eslint": "^4.18.2",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
"eslint-plugin-import": "^2.9.0",
|
||||
"eslint-plugin-node": "^6.0.1",
|
||||
"eslint-plugin-promise": "^3.7.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"mocha": "^5.0.4",
|
||||
"nyc": "^11.4.1",
|
||||
"regenerate": "^1.3.3",
|
||||
"rollup": "^0.56.5",
|
||||
"rollup-plugin-babel": "^3.0.3",
|
||||
"rollup-plugin-commonjs": "^9.0.0",
|
||||
"rollup-plugin-node-resolve": "^3.2.0",
|
||||
"rollup-plugin-uglify": "^3.0.0",
|
||||
"sinon": "^4.4.2",
|
||||
"unicode-9.0.0": "^0.7.5"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
../json5/lib/cli.js
|
@ -0,0 +1,23 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2018 Aseem Kishore, and [others].
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
[others]: https://github.com/json5/json5/contributors
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';var _fs=require('fs');var _fs2=_interopRequireDefault(_fs);var _path=require('path');var _path2=_interopRequireDefault(_path);var _minimist=require('minimist');var _minimist2=_interopRequireDefault(_minimist);var _package=require('../package.json');var _package2=_interopRequireDefault(_package);var _=require('./');var _2=_interopRequireDefault(_);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var argv=(0,_minimist2.default)(process.argv.slice(2),{alias:{'convert':'c','space':'s','validate':'v','out-file':'o','version':'V','help':'h'},boolean:['convert','validate','version','help'],string:['space','out-file']});if(argv.version){version()}else if(argv.help){usage()}else{var inFilename=argv._[0];var readStream=void 0;if(inFilename){readStream=_fs2.default.createReadStream(inFilename)}else{readStream=process.stdin}var json5='';readStream.on('data',function(data){json5+=data});readStream.on('end',function(){var space=void 0;if(argv.space==='t'||argv.space==='tab'){space='\t'}else{space=Number(argv.space)}var value=void 0;try{value=_2.default.parse(json5);if(!argv.validate){var json=JSON.stringify(value,null,space);var writeStream=void 0;if(argv.convert&&inFilename&&!argv.o){var parsedFilename=_path2.default.parse(inFilename);var outFilename=_path2.default.format(Object.assign(parsedFilename,{base:_path2.default.basename(parsedFilename.base,parsedFilename.ext)+'.json'}));writeStream=_fs2.default.createWriteStream(outFilename)}else if(argv.o){writeStream=_fs2.default.createWriteStream(argv.o)}else{writeStream=process.stdout}writeStream.write(json)}}catch(err){console.error(err.message);process.exit(1)}})}function version(){console.log(_package2.default.version)}function usage(){console.log('\n Usage: json5 [options] <file>\n\n If <file> is not provided, then STDIN is used.\n\n Options:\n\n -s, --space The number of spaces to indent or \'t\' for tabs\n -o, --out-file [file] Output to the specified file, otherwise STDOUT\n -v, --validate Validate JSON5 but do not output JSON\n -V, --version Output the version number\n -h, --help Output usage information')}
|
@ -0,0 +1 @@
|
||||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var _parse=require('./parse');var _parse2=_interopRequireDefault(_parse);var _stringify=require('./stringify');var _stringify2=_interopRequireDefault(_stringify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}exports.default={parse:_parse2.default,stringify:_stringify2.default};module.exports=exports['default'];
|
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
'use strict';var _fs=require('fs');var _fs2=_interopRequireDefault(_fs);var _=require('./');var _2=_interopRequireDefault(_);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}require.extensions['.json5']=function(module,filename){var content=_fs2.default.readFileSync(filename,'utf8');try{module.exports=_2.default.parse(content)}catch(err){err.message=filename+': '+err.message;throw err}};
|
@ -0,0 +1 @@
|
||||
"use strict";require("./register");console.warn("'json5/require' is deprecated. Please use 'json5/register' instead.");
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});exports.isSpaceSeparator=isSpaceSeparator;exports.isIdStartChar=isIdStartChar;exports.isIdContinueChar=isIdContinueChar;exports.isDigit=isDigit;exports.isHexDigit=isHexDigit;var _unicode=require('../lib/unicode');var unicode=_interopRequireWildcard(_unicode);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key]}}newObj.default=obj;return newObj}}function isSpaceSeparator(c){return unicode.Space_Separator.test(c)}function isIdStartChar(c){return c>='a'&&c<='z'||c>='A'&&c<='Z'||c==='$'||c==='_'||unicode.ID_Start.test(c)}function isIdContinueChar(c){return c>='a'&&c<='z'||c>='A'&&c<='Z'||c>='0'&&c<='9'||c==='$'||c==='_'||c==='\u200C'||c==='\u200D'||unicode.ID_Continue.test(c)}function isDigit(c){return /[0-9]/.test(c)}function isHexDigit(c){return /[0-9A-Fa-f]/.test(c)}
|
@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "json5",
|
||||
"version": "1.0.2",
|
||||
"description": "JSON for humans.",
|
||||
"main": "lib/index.js",
|
||||
"bin": "lib/cli.js",
|
||||
"browser": "dist/index.js",
|
||||
"files": [
|
||||
"lib/",
|
||||
"dist/"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "babel-node build/build.js && babel src -d lib && rollup -c",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"lint": "eslint --fix build src",
|
||||
"prepublishOnly": "npm run lint && npm test && npm run production",
|
||||
"pretest": "cross-env NODE_ENV=test npm run build",
|
||||
"preversion": "npm run lint && npm test && npm run production",
|
||||
"production": "cross-env NODE_ENV=production npm run build",
|
||||
"test": "nyc --reporter=html --reporter=text mocha"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/json5/json5.git"
|
||||
},
|
||||
"keywords": [
|
||||
"json",
|
||||
"json5",
|
||||
"es5",
|
||||
"es2015",
|
||||
"ecmascript"
|
||||
],
|
||||
"author": "Aseem Kishore <aseem.kishore@gmail.com>",
|
||||
"contributors": [
|
||||
"Max Nanasy <max.nanasy@gmail.com>",
|
||||
"Andrew Eisenberg <andrew@eisenberg.as>",
|
||||
"Jordan Tucker <jordanbtucker@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/json5/json5/issues"
|
||||
},
|
||||
"homepage": "http://json5.org/",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-add-module-exports": "^0.2.1",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-istanbul": "^4.1.5",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-register": "^6.26.0",
|
||||
"babelrc-rollup": "^3.0.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"cross-env": "^5.1.4",
|
||||
"del": "^3.0.0",
|
||||
"eslint": "^4.18.2",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
"eslint-plugin-import": "^2.9.0",
|
||||
"eslint-plugin-node": "^6.0.1",
|
||||
"eslint-plugin-promise": "^3.7.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"mocha": "^5.0.4",
|
||||
"nyc": "^11.4.1",
|
||||
"regenerate": "^1.3.3",
|
||||
"rollup": "^0.56.5",
|
||||
"rollup-plugin-babel": "^3.0.3",
|
||||
"rollup-plugin-commonjs": "^9.0.0",
|
||||
"rollup-plugin-node-resolve": "^3.2.0",
|
||||
"rollup-plugin-uglify": "^3.0.0",
|
||||
"sinon": "^4.4.2",
|
||||
"unicode-9.0.0": "^0.7.5"
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue