Move more config into local typescript gulpfile

This commit is contained in:
Jason Reed
2020-07-14 12:52:06 -04:00
parent 2c5b672c81
commit 528cbc8d49
15 changed files with 10883 additions and 36 deletions

View File

@@ -3,7 +3,7 @@ module.exports = {
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
project: ["tsconfig.json", "./src/**/tsconfig.json"],
project: ["tsconfig.json", "./src/**/tsconfig.json", "./_gulpfile.ts/tsconfig.json"],
},
plugins: ["@typescript-eslint"],
env: {

View File

@@ -0,0 +1,201 @@
import * as fs from 'fs-extra';
import * as jsonc from 'jsonc-parser';
import { IPackageJson } from '@microsoft/node-core-library';
import * as path from 'path';
import { getRushContext, RushContext } from './rush';
import * as packlist from 'npm-packlist';
import * as glob from 'glob-promise';
import * as cpp from 'child-process-promise';
interface PackageInfo {
name: string;
version: string;
sourcePath: string;
files: string[];
dependencies: PackageInfo[];
isRoot?: boolean;
copied?: boolean;
}
async function copyPackage(packageFiles: PackageInfo, destPath: string): Promise<void> {
for (const file of packageFiles.files) {
const sourceFilePath = path.resolve(packageFiles.sourcePath, file);
const destFilePath = path.resolve(destPath, file);
if (packageFiles.isRoot && (file === 'package.json')) {
// For non-release builds, we tweak the version number of the extension to add a prerelease
// suffix. Rather than just copying `package.json`, we'll parse the original copy, update the
// `version` property, and write it out to the new location.
const packageJson = jsonc.parse((await fs.readFile(sourceFilePath)).toString());
packageJson.version = packageFiles.version;
await fs.writeFile(destFilePath, JSON.stringify(packageJson));
}
else {
await fs.copy(sourceFilePath, destFilePath);
}
}
}
export interface DeployedPackage {
distPath: string;
name: string;
version: string;
}
class PackageMap {
private map = new Map<string, Map<string, PackageInfo>>();
public getPackageInfo(name: string, version: string): PackageInfo | undefined {
const versionMap = this.map.get(name);
if (versionMap === undefined) {
return undefined;
}
return versionMap.get(version);
}
public addPackageInfo(pkg: PackageInfo): void {
if (this.getPackageInfo(pkg.name, pkg.version)) {
throw new Error(`Attempt to add duplicate package '${pkg.name}@${pkg.version}'.`);
}
let versionMap = this.map.get(pkg.name);
if (versionMap === undefined) {
versionMap = new Map<string, PackageInfo>();
this.map.set(pkg.name, versionMap);
}
versionMap.set(pkg.version, pkg);
}
public hasMultipleVersions(name: string): boolean {
return this.map.get(name)!.size > 1;
}
}
async function collectPackages(context: RushContext, name: string, version: string,
pkgs: PackageMap): Promise<PackageInfo> {
let pkg = pkgs.getPackageInfo(name, version);
if (!pkg) {
const info = await context.getPackageInfo(name, version);
let files: string[];
if (info.isLocal) {
// For local packages, use `packlist` to get the list of files that npm would have packed
// into the tarball.
files = packlist.sync({ path: info.path });
}
else {
// For non-local packages, just copy everything.
files = await glob('**/*', {
nodir: true,
cwd: info.path
});
}
pkg = {
name: name,
version: version,
sourcePath: info.path,
files: files,
dependencies: []
};
pkgs.addPackageInfo(pkg);
for (const dependencyName of info.dependencies.keys()) {
const dependencyVersion = info.dependencies.get(dependencyName)!;
const dependencyPackage = await collectPackages(context, dependencyName, dependencyVersion, pkgs);
pkg.dependencies.push(dependencyPackage);
}
}
return pkg;
}
async function copyPackageAndModules(pkg: PackageInfo, pkgs: PackageMap, destPath: string,
rootNodeModulesPath: string): Promise<void> {
let destPackagePath: string;
if (pkgs.hasMultipleVersions(pkg.name) || pkg.isRoot) {
// Copy as a nested package, and let `npm dedupe` fix it up later if possible.
destPackagePath = path.join(destPath, pkg.name);
}
else {
// Copy to the root `node_modules` directory.
if (pkg.copied) {
return;
}
pkg.copied = true;
destPackagePath = path.join(rootNodeModulesPath, pkg.name);
}
await copyPackage(pkg, destPackagePath);
const nodeModulesPath = path.join(destPackagePath, 'node_modules');
for (const dependencyPkg of pkg.dependencies) {
await copyPackageAndModules(dependencyPkg, pkgs, nodeModulesPath, rootNodeModulesPath);
}
}
export async function deployPackage(packageJsonPath: string): Promise<DeployedPackage> {
try {
const context = await getRushContext(path.dirname(packageJsonPath));
const rootPackage: IPackageJson = jsonc.parse(await fs.readFile(packageJsonPath, 'utf8'));
// Default to development build; use flag --release to indicate release build.
const isDevBuild = !process.argv.includes('--release');
const distDir = path.join(context.rushConfig.rushJsonFolder, 'dist');
await fs.mkdirs(distDir);
if (isDevBuild) {
// NOTE: rootPackage.name had better not have any regex metacharacters
const oldDevBuildPattern = new RegExp('^' + rootPackage.name + '[^/]+-dev[0-9.]+\\.vsix$');
// Dev package filenames are of the form
// vscode-codeql-0.0.1-dev.2019.9.27.19.55.20.vsix
(await fs.readdir(distDir)).filter(name => name.match(oldDevBuildPattern)).map(build => {
console.log(`Deleting old dev build ${build}...`);
fs.unlinkSync(path.join(distDir, build));
});
const now = new Date();
rootPackage.version = rootPackage.version +
`-dev.${now.getUTCFullYear()}.${now.getUTCMonth() + 1}.${now.getUTCDate()}` +
`.${now.getUTCHours()}.${now.getUTCMinutes()}.${now.getUTCSeconds()}`;
}
const distPath = path.join(distDir, rootPackage.name);
await fs.remove(distPath);
await fs.mkdirs(distPath);
console.log(`Gathering transitive dependencies of package '${rootPackage.name}'...`);
const pkgs = new PackageMap();
const rootPkg = await collectPackages(context, rootPackage.name, rootPackage.version, pkgs);
rootPkg.isRoot = true;
console.log(`Copying package '${rootPackage.name}' and its dependencies to '${distPath}'...`);
await copyPackageAndModules(rootPkg, pkgs, path.dirname(distPath), path.join(distPath, 'node_modules'));
await fs.copy(path.resolve(rootPkg.sourcePath, '.vscodeignore'), path.resolve(distPath, '.vscodeignore'));
console.log(`Deduplicating dependencies of package '${rootPackage.name}'...`);
// We create a temporary `package-lock.json` file just to prevent `npm ls` from printing out the
// message that it created a package-lock.json.
const packageLockPath = path.join(distPath, 'package-lock.json');
await fs.writeFile(packageLockPath, '{}');
await cpp.spawn('npm', ['dedupe'], {
cwd: distPath,
stdio: 'inherit'
});
await fs.unlink(packageLockPath);
return {
distPath: distPath,
name: rootPackage.name,
version: rootPackage.version
};
}
catch (e) {
console.error(e);
throw e;
}
}

View File

@@ -1,7 +1,9 @@
const task = (done: any) => {
console.log('Hello world!');
done();
};
import * as gulp from 'gulp';
import { compileTypeScript, watchTypeScript, copyViewCss } from './typescript';
import { compileTextMateGrammar } from './textmate';
import { copyTestData } from './tests';
import { compileView } from './webpack';
export default task;
export const buildWithoutPackage = gulp.parallel(compileTypeScript, compileTextMateGrammar, compileView, copyTestData, copyViewCss);
export { compileTextMateGrammar, watchTypeScript, compileTypeScript };
// exports.default = gulp.series(exports.buildWithoutPackage, packageExtension);

View File

@@ -0,0 +1,23 @@
import * as path from 'path';
import { deployPackage } from './deploy';
import * as childProcess from 'child-process-promise';
export async function packageExtension(): Promise<void> {
const deployedPackage = await deployPackage(path.resolve('package.json'));
console.log(`Packaging extension '${deployedPackage.name}@${deployedPackage.version}'...`);
const args = [
'package',
'--out', path.resolve(deployedPackage.distPath, '..', `${deployedPackage.name}-${deployedPackage.version}.vsix`)
];
const proc = childProcess.spawn('vsce', args, {
cwd: deployedPackage.distPath
});
proc.childProcess.stdout!.on('data', (data) => {
console.log(data.toString());
});
proc.childProcess.stderr!.on('data', (data) => {
console.error(data.toString());
});
await proc;
}

View File

@@ -0,0 +1,17 @@
export interface PackageDependencies {
[key: string]: string;
}
export interface ShrinkwrapPackage {
dependencies?: PackageDependencies;
dev?: boolean;
name?: string;
version?: string;
}
export interface Shrinkwrap {
dependencies: PackageDependencies;
packages: {
[key: string]: ShrinkwrapPackage;
};
}

View File

@@ -0,0 +1,166 @@
import * as fs from 'fs-extra';
import * as glob from 'glob-promise';
import * as jsonc from 'jsonc-parser';
import { Shrinkwrap, ShrinkwrapPackage } from './pnpm';
import * as path from 'path';
import { IPackageJson } from '@microsoft/node-core-library';
import { RushConfiguration } from '@microsoft/rush-lib';
import * as yaml from 'js-yaml';
export interface PackageJsonWithFiles extends IPackageJson {
files?: string[];
}
interface PackageInfo {
path: string;
dependencies: Map<string, string>;
config: PackageJsonWithFiles;
isLocal: boolean;
}
const peerDependencyVersionPattern = /^\/((?:@(?:[^\/]+)\/)?[^\/]+)\/([^\/]+)\//;
export class RushContext {
private shrinkwrap?: Shrinkwrap;
private shrinkwrapPackages?: Map<string, ShrinkwrapPackage>;
private readonly packageStore: string;
constructor(public readonly rushConfig: RushConfiguration) {
this.packageStore = path.join(rushConfig.pnpmStoreFolder, '2');
}
private async findPackageInRepository(name: string, version: string): Promise<string> {
// Packages may be pulled from multiple registries, each of which has its own directory in the
// pnpm store. Search for the package name in any of these directories. We use `*.*` to match
// the directory name to avoid searching the `local` directory, which does not represent a
// package registry.
const results = await glob(`*.*/${name}/${version}/package`, {
absolute: true,
cwd: this.packageStore
});
if (results.length === 0) {
throw new Error(`Package '${name}:${version}' not found in package repository.`);
}
else if (results.length > 1) {
throw new Error(`Multiple copies of package '${name}:${version}' found in package repository.`);
}
else {
return results[0];
}
}
private getRushProjectPath(name: string): string | undefined {
const project = this.rushConfig.getProjectByName(name);
if (project) {
return project.projectFolder;
}
else {
return undefined;
}
}
private async getShrinkwrap(): Promise<Shrinkwrap> {
if (!this.shrinkwrap) {
this.shrinkwrap = yaml.safeLoad(await fs.readFile(this.rushConfig.getCommittedShrinkwrapFilename(), 'utf8'));
}
return this.shrinkwrap!;
}
private async getShrinkwrapPackage(name: string, version: string): Promise<ShrinkwrapPackage> {
const shrinkwrap = await this.getShrinkwrap();
if (!this.shrinkwrapPackages) {
this.shrinkwrapPackages = new Map<string, ShrinkwrapPackage>();
for (const name in shrinkwrap.packages) {
const pkg = shrinkwrap.packages[name];
let packageKey: string;
if (pkg.name) {
packageKey = makePackageKey(pkg.name, pkg.version!);
}
else {
packageKey = name;
}
this.shrinkwrapPackages.set(packageKey, pkg);
}
}
const packageKey = makePackageKey(name, version);
const shrinkwrapPackage = this.shrinkwrapPackages.get(packageKey);
if (!shrinkwrapPackage) {
throw new Error(`Package '${packageKey}' not found in shrinkwrap file.`);
}
return shrinkwrapPackage;
}
public async getPackageInfo(name: string, version: string): Promise<PackageInfo> {
let pkg: ShrinkwrapPackage;
const rushProject = this.rushConfig.getProjectByName(name);
let packagePath: string;
let config: PackageJsonWithFiles;
if (rushProject) {
packagePath = rushProject.projectFolder;
pkg = await this.getShrinkwrapPackage(rushProject.tempProjectName, '0.0.0');
config = rushProject.packageJson;
}
else {
pkg = await this.getShrinkwrapPackage(name, version);
// Ensure a proper version number. pnpm uses syntax like 3.4.0_glob@7.1.6 for peer dependencies
version = version.split('_')[0];
packagePath = await this.findPackageInRepository(name, version);
packagePath = await fs.realpath(packagePath);
config = jsonc.parse(await fs.readFile(path.join(packagePath, 'package.json'), 'utf8'));
}
const dependencies = new Map<string, string>();
if (config.dependencies) {
for (const dependencyName in config.dependencies) {
let dependencyVersion: string;
if (await this.getRushProjectPath(dependencyName)) {
dependencyVersion = '0.0.0';
}
else {
dependencyVersion = pkg.dependencies![dependencyName];
if (!dependencyVersion) {
throw new Error(`Package '${name}' depends on unresolved package '${dependencyName}'.`);
}
if (dependencyVersion.startsWith('/')) {
// This is a package with a peer dependency. We need to extract the actual package
// version.
const match = dependencyVersion.match(peerDependencyVersionPattern);
if (match) {
if (match[1] !== dependencyName) {
throw new Error(`Mismatch between package name '${dependencyName}' and peer dependency specifier '${dependencyVersion}'.`);
}
dependencyVersion = match[2];
}
else {
throw new Error(`Invalid peer dependency specifier '${dependencyVersion}'.`);
}
}
}
dependencies.set(dependencyName, dependencyVersion);
}
}
return {
path: packagePath,
dependencies: dependencies,
config: config,
isLocal: rushProject !== undefined
};
}
}
function makePackageKey(name: string, version: string): string {
return `/${name}/${version}`;
}
export async function getRushContext(startingFolder?: string): Promise<RushContext> {
const rushConfig = RushConfiguration.loadFromDefaultLocation({
startingFolder: startingFolder
});
return new RushContext(rushConfig);
}

View File

@@ -0,0 +1,6 @@
import * as gulp from 'gulp';
export function copyTestData() {
return gulp.src('src/vscode-tests/no-workspace/data/**/*')
.pipe(gulp.dest('out/vscode-tests/no-workspace/data'));
}

View File

@@ -0,0 +1,246 @@
import * as gulp from 'gulp';
import * as jsYaml from 'js-yaml';
import * as through from 'through2';
import * as PluginError from 'plugin-error';
import * as Vinyl from 'vinyl';
/**
* Replaces all rule references with the match pattern of the referenced rule.
*
* @param value Original regex containing rule references.
* @param replacements Map from rule name to match text.
* @returns The new regex after replacement.
*/
function replaceReferencesWithStrings(value: string, replacements: Map<string, string>): string {
let result = value;
// eslint-disable-next-line no-constant-condition
while (true) {
const original = result;
for (const key of Array.from(replacements.keys())) {
result = result.replace(`(?#${key})`, `(?:${replacements.get(key)})`);
}
if (result === original) {
return result;
}
}
}
/**
* Gather all macro definitions from the document.
*
* @param yaml The root of the YAML document.
* @returns A map from macro name to replacement text.
*/
function gatherMacros(yaml: any): Map<string, string> {
const macros = new Map<string, string>();
for (const key in yaml.macros) {
macros.set(key, yaml.macros[key]);
}
return macros;
}
/**
* Return the match text to be substituted wherever the specified rule is referenced in a regular
* expression.
*
* @param rule The rule whose match text is to be retrieved.
* @returns The match text for the rule. This is either the value of the rule's `match` property,
* or the disjunction of the match text of all of the other rules `include`d by this rule.
*/
function getNodeMatchText(rule: any): string {
if (rule.match !== undefined) {
// For a match string, just use that string as the replacement.
return rule.match;
}
else if (rule.patterns !== undefined) {
const patterns: string[] = [];
// For a list of patterns, use the disjunction of those patterns.
for (const patternIndex in rule.patterns) {
const pattern = rule.patterns[patternIndex];
if (pattern.include !== null) {
patterns.push('(?' + pattern.include + ')');
}
}
return '(?:' + patterns.join('|') + ')';
}
else {
return '';
}
}
/**
* Generates a map from rule name to match text.
*
* @param yaml The root of the YAML document.
* @returns A map whose keys are the names of rules, and whose values are the corresponding match
* text of each rule.
*/
function gatherMatchTextForRules(yaml: any): Map<string, string> {
const replacements = new Map<string, string>();
for (const key in yaml.repository) {
const node = yaml.repository[key];
replacements.set(key, getNodeMatchText(node));
}
return replacements;
}
/**
* Invoke the specified callback function on each rule definition in the file.
*
* @param yaml The root of the YAML document.
* @param action Callback to invoke on each rule.
*/
function visitAllRulesInFile(yaml: any, action: (rule: any) => void) {
visitAllRulesInRuleMap(yaml.patterns, action);
visitAllRulesInRuleMap(yaml.repository, action);
}
/**
* Invoke the specified callback function on each rule definition in a map or array of rules.
* For rules that have a `patterns` element defined child rules, the children are included in the
* visitation.
*
* @param ruleMap The map or array of rules to visit.
* @param action Callback to invoke on each rule.
*/
function visitAllRulesInRuleMap(ruleMap: any, action: (rule: any) => void) {
for (const key in ruleMap) {
const rule = ruleMap[key];
if ((typeof rule) === 'object') {
action(rule);
if (rule.patterns !== undefined) {
visitAllRulesInRuleMap(rule.patterns, action);
}
}
}
}
/**
* Invoke the specified transformation on all match patterns in the specified rule.
*
* @param rule The rule whose matches are to be transformed.
* @param action The transformation to make on each match pattern.
*/
function visitAllMatchesInRule(rule: any, action: (match: any) => any) {
for (const key in rule) {
switch (key) {
case 'begin':
case 'end':
case 'match':
case 'while':
rule[key] = action(rule[key]);
break;
default:
break;
}
}
}
/**
* Replace any usage of the specified `beginPattern` or `endPattern` property with the equivalent
* `begin`/`beginCaptures` or `end`/`endCaptures` properties.
*
* @param rule Rule to be transformed.
* @param key Base key of the property to be transformed.
*/
function expandPatternMatchProperties(rule: any, key: 'begin' | 'end') {
const patternKey = key + 'Pattern';
const capturesKey = key + 'Captures';
const pattern = rule[patternKey];
if (pattern !== undefined) {
const patterns: string[] = Array.isArray(pattern) ? pattern : [pattern];
rule[key] = patterns.map(p => `((?${p}))`).join('|');
const captures: { [index: string]: any } = {};
for (const patternIndex in patterns) {
captures[(Number(patternIndex) + 1).toString()] = {
patterns: [
{
include: patterns[patternIndex]
}
]
};
}
rule[capturesKey] = captures;
rule[patternKey] = undefined;
}
}
/**
* Transform the specified document to produce a TextMate grammar.
*
* @param yaml The root of the YAML document.
*/
function transformFile(yaml: any) {
const macros = gatherMacros(yaml);
visitAllRulesInFile(yaml, (rule) => {
expandPatternMatchProperties(rule, 'begin');
expandPatternMatchProperties(rule, 'end');
});
// Expand macros in matches.
visitAllRulesInFile(yaml, (rule) => {
visitAllMatchesInRule(rule, (match) => {
if ((typeof match) === 'object') {
for (const key in match) {
return macros.get(key)!.replace('(?#)', `(?:${match[key]})`);
}
throw new Error('No key in macro map.');
}
else {
return match;
}
});
});
yaml.macros = undefined;
const replacements = gatherMatchTextForRules(yaml);
// Expand references in matches.
visitAllRulesInFile(yaml, (rule) => {
visitAllMatchesInRule(rule, (match) => {
return replaceReferencesWithStrings(match, replacements);
});
});
if (yaml.regexOptions !== undefined) {
const regexOptions = '(?' + yaml.regexOptions + ')';
visitAllRulesInFile(yaml, (rule) => {
visitAllMatchesInRule(rule, (match) => {
return regexOptions + match;
});
});
yaml.regexOptions = undefined;
}
}
export function transpileTextMateGrammar() {
return through.obj((file: Vinyl, _encoding: string, callback: Function): void => {
if (file.isNull()) {
callback(null, file);
}
else if (file.isBuffer()) {
const buf: Buffer = file.contents;
const yamlText: string = buf.toString('utf8');
const jsonData: any = jsYaml.safeLoad(yamlText);
transformFile(jsonData);
file.contents = Buffer.from(JSON.stringify(jsonData, null, 2), 'utf8');
file.extname = '.json';
callback(null, file);
}
else {
callback('error', new PluginError('transpileTextMateGrammar', 'Format not supported.'));
}
});
}
export function compileTextMateGrammar() {
return gulp.src('syntaxes/*.tmLanguage.yml')
.pipe(transpileTextMateGrammar())
.pipe(gulp.dest('out/syntaxes'));
}

View File

@@ -0,0 +1,22 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"compilerOptions": {
"declaration": true,
"strict": true,
"module": "commonjs",
"target": "es2017",
"lib": ["es6"],
"moduleResolution": "node",
"sourceMap": true,
"rootDir": "src",
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
"preserveWatchOutput": true,
"newLine": "lf",
"noImplicitReturns": true,
"experimentalDecorators": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"include": ["*.ts"]
}

View File

@@ -0,0 +1,50 @@
import * as colors from 'ansi-colors';
import * as gulp from 'gulp';
import * as path from 'path';
import * as sourcemaps from 'gulp-sourcemaps';
import * as ts from 'gulp-typescript';
function goodReporter(): ts.reporter.Reporter {
return {
error: (error, typescript) => {
if (error.tsFile) {
console.log('[' + colors.gray('gulp-typescript') + '] ' + colors.red(error.fullFilename
+ '(' + (error.startPosition!.line + 1) + ',' + error.startPosition!.character + '): ')
+ 'error TS' + error.diagnostic.code + ': ' + typescript.flattenDiagnosticMessageText(error.diagnostic.messageText, '\n'));
}
else {
console.log(error.message);
}
},
};
}
const tsProject = ts.createProject('tsconfig.json');
export function compileTypeScript() {
return tsProject.src()
.pipe(sourcemaps.init())
.pipe(tsProject(goodReporter()))
.pipe((sourcemaps as any).mapSources((sourcePath: string, _file: string) => {
// The source path is kind of odd, because it's relative to the `tsconfig.json` file in the
// `typescript-config` package, which lives in the `node_modules` directory of the package
// that is being built. It starts out as something like '../../../src/foo.ts', and we need to
// strip out the leading '../../../'.
return path.join('a/b/c', sourcePath);
}))
.pipe(sourcemaps.write('.', {
includeContent: false,
sourceRoot: '.', // XXX this is probably wrong
}))
.pipe(gulp.dest('out'));
}
export function watchTypeScript() {
gulp.watch('src/**/*.ts', compileTypeScript);
}
/** Copy CSS files for the results view into the output directory. */
export function copyViewCss() {
return gulp.src('src/view/*.css')
.pipe(gulp.dest('out'));
}

View File

@@ -0,0 +1,65 @@
import * as path from 'path';
import * as webpack from 'webpack';
export const config: webpack.Configuration = {
mode: 'development',
entry: {
resultsView: './src/view/results.tsx',
compareView: './src/compare/view/Compare.tsx',
},
output: {
path: path.resolve(__dirname, '..', 'out'),
filename: '[name].js'
},
devtool: 'inline-source-map',
resolve: {
extensions: ['.js', '.ts', '.tsx', '.json']
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'ts-loader',
options: {
configFile: 'src/view/tsconfig.json',
}
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
sourceMap: true
}
},
{
loader: 'less-loader',
options: {
javascriptEnabled: true,
sourceMap: true
}
}
]
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
}
]
}
]
},
performance: {
hints: false
}
};

View File

@@ -0,0 +1,28 @@
import * as webpack from 'webpack';
import { config } from './webpack.config';
export function compileView(cb: (err?: Error) => void) {
webpack(config).run((error, stats) => {
if (error) {
cb(error);
}
console.log(stats.toString({
errorDetails: true,
colors: true,
assets: false,
builtAt: false,
version: false,
hash: false,
entrypoints: false,
timings: false,
modules: false,
errors: true
}));
if (stats.hasErrors()) {
cb(new Error('Compilation errors detected.'));
return;
}
cb();
});
}

10023
extensions/ql-vscode/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -586,90 +586,91 @@
"preintegration": "rm -rf ./out/vscode-tests && gulp",
"integration": "node ./out/vscode-tests/run-integration-tests.js",
"update-vscode": "node ./node_modules/vscode/bin/install",
"postinstall": "npm rebuild && node ./node_modules/vscode/bin/install",
"format": "tsfmt -r && eslint src test --ext .ts,.tsx --fix",
"lint": "eslint src test --ext .ts,.tsx --max-warnings=0",
"format-staged": "lint-staged"
},
"dependencies": {
"@types/semver": "~7.2.0",
"child-process-promise": "^2.2.1",
"classnames": "~2.2.6",
"fs-extra": "^8.1.0",
"glob-promise": "^3.4.0",
"js-yaml": "^3.12.0",
"js-yaml": "^3.14.0",
"minimist": "~1.2.5",
"node-fetch": "~2.6.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"semver": "~7.3.2",
"tmp": "^0.1.0",
"tmp-promise": "~3.0.2",
"tree-kill": "~1.2.2",
"unzipper": "~0.10.5",
"vscode-jsonrpc": "^5.0.1",
"vscode-languageclient": "^6.1.3",
"vscode-test-adapter-api": "~1.7.0",
"vscode-test-adapter-util": "~0.7.0",
"minimist": "~1.2.5",
"semver": "~7.3.2",
"@types/semver": "~7.2.0",
"tmp-promise": "~3.0.2",
"zip-a-folder": "~0.0.12"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/chai-as-promised": "~7.1.2",
"@types/child-process-promise": "^2.2.1",
"@types/classnames": "~2.2.9",
"@types/fs-extra": "^8.0.0",
"@types/glob": "^7.1.1",
"@types/google-protobuf": "^3.2.7",
"@types/gulp": "^4.0.6",
"@types/js-yaml": "~3.12.1",
"@types/gulp-sourcemaps": "0.0.32",
"@types/js-yaml": "=3.12.2",
"@types/jszip": "~3.1.6",
"@types/mocha": "~5.2.7",
"@types/node": "^12.0.8",
"@types/node-fetch": "~2.5.2",
"@types/proxyquire": "~1.3.28",
"@types/react": "^16.8.17",
"@types/react-dom": "^16.8.4",
"@types/sarif": "~2.1.2",
"@types/sinon": "~7.5.2",
"@types/sinon-chai": "~3.2.3",
"@types/through2": "^2.0.36",
"@types/tmp": "^0.1.0",
"@types/unzipper": "~0.10.1",
"@types/vscode": "^1.39.0",
"@types/vscode": "=1.43.0",
"@types/webpack": "^4.32.1",
"@types/xml2js": "~0.4.4",
"@github/codeql-gulp-tasks": "^0.0.4",
"@typescript-eslint/eslint-plugin": "~2.23.0",
"@typescript-eslint/parser": "~2.23.0",
"ansi-colors": "^4.1.1",
"chai": "^4.2.0",
"chai-as-promised": "~7.1.1",
"css-loader": "~3.1.0",
"eslint": "~6.8.0",
"eslint-plugin-react": "~7.19.0",
"glob": "^7.1.4",
"gulp": "^4.0.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-typescript": "^5.0.1",
"husky": "~4.2.5",
"lint-staged": "~10.2.2",
"mocha": "~6.2.1",
"mocha-sinon": "~2.1.0",
"npm-run-all": "^4.1.5",
"prettier": "~2.0.5",
"proxyquire": "~2.1.3",
"sinon": "~9.0.0",
"sinon-chai": "~3.5.0",
"style-loader": "~0.23.1",
"through2": "^3.0.1",
"ts-loader": "^5.4.5",
"ts-node": "^8.3.0",
"ts-protoc-gen": "^0.9.0",
"typescript": "^3.7.2",
"typescript": "=3.8.3",
"typescript-formatter": "^7.2.2",
"vsce": "^1.65.0",
"vscode-test": "^1.4.0",
"webpack": "^4.38.0",
"webpack-cli": "^3.3.2",
"eslint": "~6.8.0",
"@typescript-eslint/eslint-plugin": "~2.23.0",
"@typescript-eslint/parser": "~2.23.0",
"chai-as-promised": "~7.1.1",
"@types/chai-as-promised": "~7.1.2",
"@types/sinon": "~7.5.2",
"sinon-chai": "~3.5.0",
"@types/sinon-chai": "~3.2.3",
"proxyquire": "~2.1.3",
"@types/proxyquire": "~1.3.28",
"eslint-plugin-react": "~7.19.0",
"husky": "~4.2.5",
"lint-staged": "~10.2.2",
"prettier": "~2.0.5"
"webpack-cli": "^3.3.2"
},
"husky": {
"hooks": {

View File

@@ -1,4 +1,4 @@
import { Disposable } from "vscode";
import { Disposable } from 'vscode';
/**
* Base class to make it easier to implement a `Disposable` that owns other disposable object.
@@ -7,9 +7,6 @@ export abstract class DisposableObject implements Disposable {
private disposables: Disposable[] = [];
private tracked?: Set<Disposable> = undefined;
constructor() {
}
/**
* Adds `obj` to a list of objects to dispose when `this` is disposed. Objects added by `push` are
* disposed in reverse order of being added.