move gulp-tsb into the build/lib remove as dependency

This commit is contained in:
Johannes
2022-05-05 11:35:33 +02:00
parent 63076cfe10
commit c13d581bce
14 changed files with 1622 additions and 49 deletions

View File

@@ -102,7 +102,7 @@ const tasks = compilations.map(function (tsconfigFile) {
function createPipeline(build, emitError) {
const nlsDev = require('vscode-nls-dev');
const tsb = require('gulp-tsb');
const tsb = require('./lib/tsb');
const sourcemaps = require('gulp-sourcemaps');
const reporter = createReporter('extensions');

View File

@@ -35,7 +35,7 @@ function getTypeScriptCompilerOptions(src) {
return options;
}
function createCompile(src, build, emitError) {
const tsb = require('gulp-tsb');
const tsb = require('./tsb');
const sourcemaps = require('gulp-sourcemaps');
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };

View File

@@ -40,7 +40,7 @@ function getTypeScriptCompilerOptions(src: string): ts.CompilerOptions {
}
function createCompile(src: string, build: boolean, emitError?: boolean) {
const tsb = require('gulp-tsb') as typeof import('gulp-tsb');
const tsb = require('./tsb') as typeof import('./tsb');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');

491
build/lib/tsb/builder.js Normal file
View File

@@ -0,0 +1,491 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTypeScriptBuilder = exports.CancellationToken = void 0;
const fs_1 = require("fs");
const path = require("path");
const crypto = require("crypto");
const utils = require("./utils");
const log = require("fancy-log");
const colors = require("ansi-colors");
const ts = require("typescript");
const Vinyl = require("vinyl");
var CancellationToken;
(function (CancellationToken) {
CancellationToken.None = {
isCancellationRequested() { return false; }
};
})(CancellationToken = exports.CancellationToken || (exports.CancellationToken = {}));
function normalize(path) {
return path.replace(/\\/g, '/');
}
function createTypeScriptBuilder(config, projectFile, cmd) {
function _log(topic, message) {
if (config.verbose) {
log(colors.cyan(topic), message);
}
}
let host = new LanguageServiceHost(cmd, projectFile, _log), service = ts.createLanguageService(host, ts.createDocumentRegistry()), lastBuildVersion = Object.create(null), lastDtsHash = Object.create(null), userWantsDeclarations = cmd.options.declaration, oldErrors = Object.create(null), headUsed = process.memoryUsage().heapUsed, emitSourceMapsInStream = true;
// always emit declaraction files
host.getCompilationSettings().declaration = true;
function file(file) {
// support gulp-sourcemaps
if (file.sourceMap) {
emitSourceMapsInStream = false;
}
if (!file.contents) {
host.removeScriptSnapshot(file.path);
}
else {
host.addScriptSnapshot(file.path, new VinylScriptSnapshot(file));
}
}
function baseFor(snapshot) {
if (snapshot instanceof VinylScriptSnapshot) {
return cmd.options.outDir || snapshot.getBase();
}
else {
return '';
}
}
function isExternalModule(sourceFile) {
return sourceFile.externalModuleIndicator
|| /declare\s+module\s+('|")(.+)\1/.test(sourceFile.getText());
}
function build(out, onError, token = CancellationToken.None) {
function checkSyntaxSoon(fileName) {
return new Promise(resolve => {
process.nextTick(function () {
if (!host.getScriptSnapshot(fileName, false)) {
resolve([]); // no script, no problems
}
else {
resolve(service.getSyntacticDiagnostics(fileName));
}
});
});
}
function checkSemanticsSoon(fileName) {
return new Promise(resolve => {
process.nextTick(function () {
if (!host.getScriptSnapshot(fileName, false)) {
resolve([]); // no script, no problems
}
else {
resolve(service.getSemanticDiagnostics(fileName));
}
});
});
}
function emitSoon(fileName) {
return new Promise(resolve => {
process.nextTick(function () {
if (/\.d\.ts$/.test(fileName)) {
// if it's already a d.ts file just emit it signature
let snapshot = host.getScriptSnapshot(fileName);
let signature = crypto.createHash('md5')
.update(snapshot.getText(0, snapshot.getLength()))
.digest('base64');
return resolve({
fileName,
signature,
files: []
});
}
let output = service.getEmitOutput(fileName);
let files = [];
let signature;
for (let file of output.outputFiles) {
if (!emitSourceMapsInStream && /\.js\.map$/.test(file.name)) {
continue;
}
if (/\.d\.ts$/.test(file.name)) {
signature = crypto.createHash('md5')
.update(file.text)
.digest('base64');
if (!userWantsDeclarations) {
// don't leak .d.ts files if users don't want them
continue;
}
}
let vinyl = new Vinyl({
path: file.name,
contents: Buffer.from(file.text),
base: !config._emitWithoutBasePath && baseFor(host.getScriptSnapshot(fileName)) || undefined
});
if (!emitSourceMapsInStream && /\.js$/.test(file.name)) {
let sourcemapFile = output.outputFiles.filter(f => /\.js\.map$/.test(f.name))[0];
if (sourcemapFile) {
let extname = path.extname(vinyl.relative);
let basename = path.basename(vinyl.relative, extname);
let dirname = path.dirname(vinyl.relative);
let tsname = (dirname === '.' ? '' : dirname + '/') + basename + '.ts';
let sourceMap = JSON.parse(sourcemapFile.text);
sourceMap.sources[0] = tsname.replace(/\\/g, '/');
vinyl.sourceMap = sourceMap;
}
}
files.push(vinyl);
}
resolve({
fileName,
signature,
files
});
});
});
}
let newErrors = Object.create(null);
let t1 = Date.now();
let toBeEmitted = [];
let toBeCheckedSyntactically = [];
let toBeCheckedSemantically = [];
let filesWithChangedSignature = [];
let dependentFiles = [];
let newLastBuildVersion = new Map();
for (let fileName of host.getScriptFileNames()) {
if (lastBuildVersion[fileName] !== host.getScriptVersion(fileName)) {
toBeEmitted.push(fileName);
toBeCheckedSyntactically.push(fileName);
toBeCheckedSemantically.push(fileName);
}
}
return new Promise(resolve => {
let semanticCheckInfo = new Map();
let seenAsDependentFile = new Set();
function workOnNext() {
let promise;
// let fileName: string;
// someone told us to stop this
if (token.isCancellationRequested()) {
_log('[CANCEL]', '>>This compile run was cancelled<<');
newLastBuildVersion.clear();
resolve();
return;
}
// (1st) emit code
else if (toBeEmitted.length) {
let fileName = toBeEmitted.pop();
promise = emitSoon(fileName).then(value => {
for (let file of value.files) {
_log('[emit code]', file.path);
out(file);
}
// remember when this was build
newLastBuildVersion.set(fileName, host.getScriptVersion(fileName));
// remeber the signature
if (value.signature && lastDtsHash[fileName] !== value.signature) {
lastDtsHash[fileName] = value.signature;
filesWithChangedSignature.push(fileName);
}
}).catch(e => {
// can't just skip this or make a result up..
host.error(`ERROR emitting ${fileName}`);
host.error(e);
});
}
// (2nd) check syntax
else if (toBeCheckedSyntactically.length) {
let fileName = toBeCheckedSyntactically.pop();
_log('[check syntax]', fileName);
promise = checkSyntaxSoon(fileName).then(diagnostics => {
delete oldErrors[fileName];
if (diagnostics.length > 0) {
diagnostics.forEach(d => onError(d));
newErrors[fileName] = diagnostics;
// stop the world when there are syntax errors
toBeCheckedSyntactically.length = 0;
toBeCheckedSemantically.length = 0;
filesWithChangedSignature.length = 0;
}
});
}
// (3rd) check semantics
else if (toBeCheckedSemantically.length) {
let fileName = toBeCheckedSemantically.pop();
while (fileName && semanticCheckInfo.has(fileName)) {
fileName = toBeCheckedSemantically.pop();
}
if (fileName) {
_log('[check semantics]', fileName);
promise = checkSemanticsSoon(fileName).then(diagnostics => {
delete oldErrors[fileName];
semanticCheckInfo.set(fileName, diagnostics.length);
if (diagnostics.length > 0) {
diagnostics.forEach(d => onError(d));
newErrors[fileName] = diagnostics;
}
});
}
}
// (4th) check dependents
else if (filesWithChangedSignature.length) {
while (filesWithChangedSignature.length) {
let fileName = filesWithChangedSignature.pop();
if (!isExternalModule(service.getProgram().getSourceFile(fileName))) {
_log('[check semantics*]', fileName + ' is an internal module and it has changed shape -> check whatever hasn\'t been checked yet');
toBeCheckedSemantically.push(...host.getScriptFileNames());
filesWithChangedSignature.length = 0;
dependentFiles.length = 0;
break;
}
host.collectDependents(fileName, dependentFiles);
}
}
// (5th) dependents contd
else if (dependentFiles.length) {
let fileName = dependentFiles.pop();
while (fileName && seenAsDependentFile.has(fileName)) {
fileName = dependentFiles.pop();
}
if (fileName) {
seenAsDependentFile.add(fileName);
let value = semanticCheckInfo.get(fileName);
if (value === 0) {
// already validated successfully -> look at dependents next
host.collectDependents(fileName, dependentFiles);
}
else if (typeof value === 'undefined') {
// first validate -> look at dependents next
dependentFiles.push(fileName);
toBeCheckedSemantically.push(fileName);
}
}
}
// (last) done
else {
resolve();
return;
}
if (!promise) {
promise = Promise.resolve();
}
promise.then(function () {
// change to change
process.nextTick(workOnNext);
}).catch(err => {
console.error(err);
});
}
workOnNext();
}).then(() => {
// store the build versions to not rebuilt the next time
newLastBuildVersion.forEach((value, key) => {
lastBuildVersion[key] = value;
});
// print old errors and keep them
utils.collections.forEach(oldErrors, entry => {
entry.value.forEach(diag => onError(diag));
newErrors[entry.key] = entry.value;
});
oldErrors = newErrors;
// print stats
if (config.verbose) {
const headNow = process.memoryUsage().heapUsed;
const MB = 1024 * 1024;
log('[tsb]', 'time:', colors.yellow((Date.now() - t1) + 'ms'), 'mem:', colors.cyan(Math.ceil(headNow / MB) + 'MB'), colors.bgcyan('delta: ' + Math.ceil((headNow - headUsed) / MB)));
headUsed = headNow;
}
});
}
return {
file,
build,
languageService: service
};
}
exports.createTypeScriptBuilder = createTypeScriptBuilder;
class ScriptSnapshot {
constructor(text, mtime) {
this._text = text;
this._mtime = mtime;
}
getVersion() {
return this._mtime.toUTCString();
}
getText(start, end) {
return this._text.substring(start, end);
}
getLength() {
return this._text.length;
}
getChangeRange(_oldSnapshot) {
return undefined;
}
}
class VinylScriptSnapshot extends ScriptSnapshot {
constructor(file) {
super(file.contents.toString(), file.stat.mtime);
this._base = file.base;
}
getBase() {
return this._base;
}
}
class LanguageServiceHost {
constructor(_cmdLine, _projectPath, _log) {
this._cmdLine = _cmdLine;
this._projectPath = _projectPath;
this._log = _log;
this.directoryExists = ts.sys.directoryExists;
this.getDirectories = ts.sys.getDirectories;
this.fileExists = ts.sys.fileExists;
this.readFile = ts.sys.readFile;
this.readDirectory = ts.sys.readDirectory;
this._snapshots = Object.create(null);
this._filesInProject = new Set(_cmdLine.fileNames);
this._filesAdded = new Set();
this._dependencies = new utils.graph.Graph(s => s);
this._dependenciesRecomputeList = [];
this._fileNameToDeclaredModule = Object.create(null);
this._projectVersion = 1;
}
log(_s) {
// console.log(s);
}
trace(_s) {
// console.log(s);
}
error(s) {
console.error(s);
}
getCompilationSettings() {
return this._cmdLine.options;
}
getProjectVersion() {
return String(this._projectVersion);
}
getScriptFileNames() {
const res = Object.keys(this._snapshots).filter(path => this._filesInProject.has(path) || this._filesAdded.has(path));
return res;
}
getScriptVersion(filename) {
filename = normalize(filename);
const result = this._snapshots[filename];
if (result) {
return result.getVersion();
}
return 'UNKNWON_FILE_' + Math.random().toString(16).slice(2);
}
getScriptSnapshot(filename, resolve = true) {
filename = normalize(filename);
let result = this._snapshots[filename];
if (!result && resolve) {
try {
result = new VinylScriptSnapshot(new Vinyl({
path: filename,
contents: (0, fs_1.readFileSync)(filename),
base: this.getCompilationSettings().outDir,
stat: (0, fs_1.statSync)(filename)
}));
this.addScriptSnapshot(filename, result);
}
catch (e) {
// ignore
}
}
return result;
}
addScriptSnapshot(filename, snapshot) {
this._projectVersion++;
filename = normalize(filename);
const old = this._snapshots[filename];
if (!old && !this._filesInProject.has(filename) && !filename.endsWith('.d.ts')) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
// not very proper!
this._filesAdded.add(filename);
}
if (!old || old.getVersion() !== snapshot.getVersion()) {
this._dependenciesRecomputeList.push(filename);
let node = this._dependencies.lookup(filename);
if (node) {
node.outgoing = Object.create(null);
}
// (cheap) check for declare module
LanguageServiceHost._declareModule.lastIndex = 0;
let match;
while ((match = LanguageServiceHost._declareModule.exec(snapshot.getText(0, snapshot.getLength())))) {
let declaredModules = this._fileNameToDeclaredModule[filename];
if (!declaredModules) {
this._fileNameToDeclaredModule[filename] = declaredModules = [];
}
declaredModules.push(match[2]);
}
}
this._snapshots[filename] = snapshot;
return old;
}
removeScriptSnapshot(filename) {
this._filesInProject.delete(filename);
this._filesAdded.delete(filename);
this._projectVersion++;
filename = normalize(filename);
delete this._fileNameToDeclaredModule[filename];
return delete this._snapshots[filename];
}
getCurrentDirectory() {
return path.dirname(this._projectPath);
}
getDefaultLibFileName(options) {
return ts.getDefaultLibFilePath(options);
}
// ---- dependency management
collectDependents(filename, target) {
while (this._dependenciesRecomputeList.length) {
this._processFile(this._dependenciesRecomputeList.pop());
}
filename = normalize(filename);
const node = this._dependencies.lookup(filename);
if (node) {
utils.collections.forEach(node.incoming, entry => target.push(entry.key));
}
}
_processFile(filename) {
if (filename.match(/.*\.d\.ts$/)) {
return;
}
filename = normalize(filename);
const snapshot = this.getScriptSnapshot(filename);
if (!snapshot) {
this._log('processFile', `Missing snapshot for: ${filename}`);
return;
}
const info = ts.preProcessFile(snapshot.getText(0, snapshot.getLength()), true);
// (1) ///-references
info.referencedFiles.forEach(ref => {
const resolvedPath = path.resolve(path.dirname(filename), ref.fileName);
const normalizedPath = normalize(resolvedPath);
this._dependencies.inertEdge(filename, normalizedPath);
});
// (2) import-require statements
info.importedFiles.forEach(ref => {
const stopDirname = normalize(this.getCurrentDirectory());
let dirname = filename;
let found = false;
while (!found && dirname.indexOf(stopDirname) === 0) {
dirname = path.dirname(dirname);
const resolvedPath = path.resolve(dirname, ref.fileName);
const normalizedPath = normalize(resolvedPath);
if (this.getScriptSnapshot(normalizedPath + '.ts')) {
this._dependencies.inertEdge(filename, normalizedPath + '.ts');
found = true;
}
else if (this.getScriptSnapshot(normalizedPath + '.d.ts')) {
this._dependencies.inertEdge(filename, normalizedPath + '.d.ts');
found = true;
}
}
if (!found) {
for (let key in this._fileNameToDeclaredModule) {
if (this._fileNameToDeclaredModule[key] && ~this._fileNameToDeclaredModule[key].indexOf(ref.fileName)) {
this._dependencies.inertEdge(filename, key);
}
}
}
});
}
}
LanguageServiceHost._declareModule = /declare\s+module\s+('|")(.+)\1/g;

616
build/lib/tsb/builder.ts Normal file
View File

@@ -0,0 +1,616 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { statSync, readFileSync } from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import * as utils from './utils';
import * as log from 'fancy-log';
import * as colors from 'ansi-colors';
import * as ts from 'typescript';
import * as Vinyl from 'vinyl';
export interface IConfiguration {
verbose: boolean;
_emitWithoutBasePath?: boolean;
}
export interface CancellationToken {
isCancellationRequested(): boolean;
}
export namespace CancellationToken {
export const None: CancellationToken = {
isCancellationRequested() { return false; }
};
}
export interface ITypeScriptBuilder {
build(out: (file: Vinyl) => void, onError: (err: ts.Diagnostic) => void, token?: CancellationToken): Promise<any>;
file(file: Vinyl): void;
languageService: ts.LanguageService;
}
function normalize(path: string): string {
return path.replace(/\\/g, '/');
}
export function createTypeScriptBuilder(config: IConfiguration, projectFile: string, cmd: ts.ParsedCommandLine): ITypeScriptBuilder {
function _log(topic: string, message: string): void {
if (config.verbose) {
log(colors.cyan(topic), message);
}
}
let host = new LanguageServiceHost(cmd, projectFile, _log),
service = ts.createLanguageService(host, ts.createDocumentRegistry()),
lastBuildVersion: { [path: string]: string } = Object.create(null),
lastDtsHash: { [path: string]: string } = Object.create(null),
userWantsDeclarations = cmd.options.declaration,
oldErrors: { [path: string]: ts.Diagnostic[] } = Object.create(null),
headUsed = process.memoryUsage().heapUsed,
emitSourceMapsInStream = true;
// always emit declaraction files
host.getCompilationSettings().declaration = true;
function file(file: Vinyl): void {
// support gulp-sourcemaps
if ((<any>file).sourceMap) {
emitSourceMapsInStream = false;
}
if (!file.contents) {
host.removeScriptSnapshot(file.path);
} else {
host.addScriptSnapshot(file.path, new VinylScriptSnapshot(file));
}
}
function baseFor(snapshot: ScriptSnapshot): string {
if (snapshot instanceof VinylScriptSnapshot) {
return cmd.options.outDir || snapshot.getBase();
} else {
return '';
}
}
function isExternalModule(sourceFile: ts.SourceFile): boolean {
return (<any>sourceFile).externalModuleIndicator
|| /declare\s+module\s+('|")(.+)\1/.test(sourceFile.getText());
}
function build(out: (file: Vinyl) => void, onError: (err: any) => void, token = CancellationToken.None): Promise<any> {
function checkSyntaxSoon(fileName: string): Promise<ts.Diagnostic[]> {
return new Promise<ts.Diagnostic[]>(resolve => {
process.nextTick(function () {
if (!host.getScriptSnapshot(fileName, false)) {
resolve([]); // no script, no problems
} else {
resolve(service.getSyntacticDiagnostics(fileName));
}
});
});
}
function checkSemanticsSoon(fileName: string): Promise<ts.Diagnostic[]> {
return new Promise<ts.Diagnostic[]>(resolve => {
process.nextTick(function () {
if (!host.getScriptSnapshot(fileName, false)) {
resolve([]); // no script, no problems
} else {
resolve(service.getSemanticDiagnostics(fileName));
}
});
});
}
function emitSoon(fileName: string): Promise<{ fileName: string; signature?: string; files: Vinyl[] }> {
return new Promise(resolve => {
process.nextTick(function () {
if (/\.d\.ts$/.test(fileName)) {
// if it's already a d.ts file just emit it signature
let snapshot = host.getScriptSnapshot(fileName);
let signature = crypto.createHash('md5')
.update(snapshot.getText(0, snapshot.getLength()))
.digest('base64');
return resolve({
fileName,
signature,
files: []
});
}
let output = service.getEmitOutput(fileName);
let files: Vinyl[] = [];
let signature: string | undefined;
for (let file of output.outputFiles) {
if (!emitSourceMapsInStream && /\.js\.map$/.test(file.name)) {
continue;
}
if (/\.d\.ts$/.test(file.name)) {
signature = crypto.createHash('md5')
.update(file.text)
.digest('base64');
if (!userWantsDeclarations) {
// don't leak .d.ts files if users don't want them
continue;
}
}
let vinyl = new Vinyl({
path: file.name,
contents: Buffer.from(file.text),
base: !config._emitWithoutBasePath && baseFor(host.getScriptSnapshot(fileName)) || undefined
});
if (!emitSourceMapsInStream && /\.js$/.test(file.name)) {
let sourcemapFile = output.outputFiles.filter(f => /\.js\.map$/.test(f.name))[0];
if (sourcemapFile) {
let extname = path.extname(vinyl.relative);
let basename = path.basename(vinyl.relative, extname);
let dirname = path.dirname(vinyl.relative);
let tsname = (dirname === '.' ? '' : dirname + '/') + basename + '.ts';
let sourceMap = JSON.parse(sourcemapFile.text);
sourceMap.sources[0] = tsname.replace(/\\/g, '/');
(<any>vinyl).sourceMap = sourceMap;
}
}
files.push(vinyl);
}
resolve({
fileName,
signature,
files
});
});
});
}
let newErrors: { [path: string]: ts.Diagnostic[] } = Object.create(null);
let t1 = Date.now();
let toBeEmitted: string[] = [];
let toBeCheckedSyntactically: string[] = [];
let toBeCheckedSemantically: string[] = [];
let filesWithChangedSignature: string[] = [];
let dependentFiles: string[] = [];
let newLastBuildVersion = new Map<string, string>();
for (let fileName of host.getScriptFileNames()) {
if (lastBuildVersion[fileName] !== host.getScriptVersion(fileName)) {
toBeEmitted.push(fileName);
toBeCheckedSyntactically.push(fileName);
toBeCheckedSemantically.push(fileName);
}
}
return new Promise<void>(resolve => {
let semanticCheckInfo = new Map<string, number>();
let seenAsDependentFile = new Set<string>();
function workOnNext() {
let promise: Promise<any> | undefined;
// let fileName: string;
// someone told us to stop this
if (token.isCancellationRequested()) {
_log('[CANCEL]', '>>This compile run was cancelled<<');
newLastBuildVersion.clear();
resolve();
return;
}
// (1st) emit code
else if (toBeEmitted.length) {
let fileName = toBeEmitted.pop()!;
promise = emitSoon(fileName).then(value => {
for (let file of value.files) {
_log('[emit code]', file.path);
out(file);
}
// remember when this was build
newLastBuildVersion.set(fileName, host.getScriptVersion(fileName));
// remeber the signature
if (value.signature && lastDtsHash[fileName] !== value.signature) {
lastDtsHash[fileName] = value.signature;
filesWithChangedSignature.push(fileName);
}
}).catch(e => {
// can't just skip this or make a result up..
host.error(`ERROR emitting ${fileName}`);
host.error(e);
});
}
// (2nd) check syntax
else if (toBeCheckedSyntactically.length) {
let fileName = toBeCheckedSyntactically.pop()!;
_log('[check syntax]', fileName);
promise = checkSyntaxSoon(fileName).then(diagnostics => {
delete oldErrors[fileName];
if (diagnostics.length > 0) {
diagnostics.forEach(d => onError(d));
newErrors[fileName] = diagnostics;
// stop the world when there are syntax errors
toBeCheckedSyntactically.length = 0;
toBeCheckedSemantically.length = 0;
filesWithChangedSignature.length = 0;
}
});
}
// (3rd) check semantics
else if (toBeCheckedSemantically.length) {
let fileName = toBeCheckedSemantically.pop();
while (fileName && semanticCheckInfo.has(fileName)) {
fileName = toBeCheckedSemantically.pop()!;
}
if (fileName) {
_log('[check semantics]', fileName);
promise = checkSemanticsSoon(fileName).then(diagnostics => {
delete oldErrors[fileName!];
semanticCheckInfo.set(fileName!, diagnostics.length);
if (diagnostics.length > 0) {
diagnostics.forEach(d => onError(d));
newErrors[fileName!] = diagnostics;
}
});
}
}
// (4th) check dependents
else if (filesWithChangedSignature.length) {
while (filesWithChangedSignature.length) {
let fileName = filesWithChangedSignature.pop()!;
if (!isExternalModule(service.getProgram()!.getSourceFile(fileName)!)) {
_log('[check semantics*]', fileName + ' is an internal module and it has changed shape -> check whatever hasn\'t been checked yet');
toBeCheckedSemantically.push(...host.getScriptFileNames());
filesWithChangedSignature.length = 0;
dependentFiles.length = 0;
break;
}
host.collectDependents(fileName, dependentFiles);
}
}
// (5th) dependents contd
else if (dependentFiles.length) {
let fileName = dependentFiles.pop();
while (fileName && seenAsDependentFile.has(fileName)) {
fileName = dependentFiles.pop();
}
if (fileName) {
seenAsDependentFile.add(fileName);
let value = semanticCheckInfo.get(fileName);
if (value === 0) {
// already validated successfully -> look at dependents next
host.collectDependents(fileName, dependentFiles);
} else if (typeof value === 'undefined') {
// first validate -> look at dependents next
dependentFiles.push(fileName);
toBeCheckedSemantically.push(fileName);
}
}
}
// (last) done
else {
resolve();
return;
}
if (!promise) {
promise = Promise.resolve();
}
promise.then(function () {
// change to change
process.nextTick(workOnNext);
}).catch(err => {
console.error(err);
});
}
workOnNext();
}).then(() => {
// store the build versions to not rebuilt the next time
newLastBuildVersion.forEach((value, key) => {
lastBuildVersion[key] = value;
});
// print old errors and keep them
utils.collections.forEach(oldErrors, entry => {
entry.value.forEach(diag => onError(diag));
newErrors[entry.key] = entry.value;
});
oldErrors = newErrors;
// print stats
if (config.verbose) {
const headNow = process.memoryUsage().heapUsed;
const MB = 1024 * 1024;
log('[tsb]',
'time:', colors.yellow((Date.now() - t1) + 'ms'),
'mem:', colors.cyan(Math.ceil(headNow / MB) + 'MB'), colors.bgcyan('delta: ' + Math.ceil((headNow - headUsed) / MB))
);
headUsed = headNow;
}
});
}
return {
file,
build,
languageService: service
};
}
class ScriptSnapshot implements ts.IScriptSnapshot {
private readonly _text: string;
private readonly _mtime: Date;
constructor(text: string, mtime: Date) {
this._text = text;
this._mtime = mtime;
}
getVersion(): string {
return this._mtime.toUTCString();
}
getText(start: number, end: number): string {
return this._text.substring(start, end);
}
getLength(): number {
return this._text.length;
}
getChangeRange(_oldSnapshot: ts.IScriptSnapshot): ts.TextChangeRange | undefined {
return undefined;
}
}
class VinylScriptSnapshot extends ScriptSnapshot {
private readonly _base: string;
constructor(file: Vinyl) {
super(file.contents!.toString(), file.stat!.mtime);
this._base = file.base;
}
getBase(): string {
return this._base;
}
}
class LanguageServiceHost implements ts.LanguageServiceHost {
private readonly _snapshots: { [path: string]: ScriptSnapshot };
private readonly _filesInProject: Set<string>;
private readonly _filesAdded: Set<string>;
private readonly _dependencies: utils.graph.Graph<string>;
private readonly _dependenciesRecomputeList: string[];
private readonly _fileNameToDeclaredModule: { [path: string]: string[] };
private _projectVersion: number;
constructor(
private readonly _cmdLine: ts.ParsedCommandLine,
private readonly _projectPath: string,
private readonly _log: (topic: string, message: string) => void
) {
this._snapshots = Object.create(null);
this._filesInProject = new Set(_cmdLine.fileNames);
this._filesAdded = new Set();
this._dependencies = new utils.graph.Graph<string>(s => s);
this._dependenciesRecomputeList = [];
this._fileNameToDeclaredModule = Object.create(null);
this._projectVersion = 1;
}
log(_s: string): void {
// console.log(s);
}
trace(_s: string): void {
// console.log(s);
}
error(s: string): void {
console.error(s);
}
getCompilationSettings(): ts.CompilerOptions {
return this._cmdLine.options;
}
getProjectVersion(): string {
return String(this._projectVersion);
}
getScriptFileNames(): string[] {
const res = Object.keys(this._snapshots).filter(path => this._filesInProject.has(path) || this._filesAdded.has(path));
return res;
}
getScriptVersion(filename: string): string {
filename = normalize(filename);
const result = this._snapshots[filename];
if (result) {
return result.getVersion();
}
return 'UNKNWON_FILE_' + Math.random().toString(16).slice(2);
}
getScriptSnapshot(filename: string, resolve: boolean = true): ScriptSnapshot {
filename = normalize(filename);
let result = this._snapshots[filename];
if (!result && resolve) {
try {
result = new VinylScriptSnapshot(new Vinyl(<any>{
path: filename,
contents: readFileSync(filename),
base: this.getCompilationSettings().outDir,
stat: statSync(filename)
}));
this.addScriptSnapshot(filename, result);
} catch (e) {
// ignore
}
}
return result;
}
private static _declareModule = /declare\s+module\s+('|")(.+)\1/g;
addScriptSnapshot(filename: string, snapshot: ScriptSnapshot): ScriptSnapshot {
this._projectVersion++;
filename = normalize(filename);
const old = this._snapshots[filename];
if (!old && !this._filesInProject.has(filename) && !filename.endsWith('.d.ts')) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
// not very proper!
this._filesAdded.add(filename);
}
if (!old || old.getVersion() !== snapshot.getVersion()) {
this._dependenciesRecomputeList.push(filename);
let node = this._dependencies.lookup(filename);
if (node) {
node.outgoing = Object.create(null);
}
// (cheap) check for declare module
LanguageServiceHost._declareModule.lastIndex = 0;
let match: RegExpExecArray | null | undefined;
while ((match = LanguageServiceHost._declareModule.exec(snapshot.getText(0, snapshot.getLength())))) {
let declaredModules = this._fileNameToDeclaredModule[filename];
if (!declaredModules) {
this._fileNameToDeclaredModule[filename] = declaredModules = [];
}
declaredModules.push(match[2]);
}
}
this._snapshots[filename] = snapshot;
return old;
}
removeScriptSnapshot(filename: string): boolean {
this._filesInProject.delete(filename);
this._filesAdded.delete(filename);
this._projectVersion++;
filename = normalize(filename);
delete this._fileNameToDeclaredModule[filename];
return delete this._snapshots[filename];
}
getCurrentDirectory(): string {
return path.dirname(this._projectPath);
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
return ts.getDefaultLibFilePath(options);
}
readonly directoryExists = ts.sys.directoryExists;
readonly getDirectories = ts.sys.getDirectories;
readonly fileExists = ts.sys.fileExists;
readonly readFile = ts.sys.readFile;
readonly readDirectory = ts.sys.readDirectory;
// ---- dependency management
collectDependents(filename: string, target: string[]): void {
while (this._dependenciesRecomputeList.length) {
this._processFile(this._dependenciesRecomputeList.pop()!);
}
filename = normalize(filename);
const node = this._dependencies.lookup(filename);
if (node) {
utils.collections.forEach(node.incoming, entry => target.push(entry.key));
}
}
_processFile(filename: string): void {
if (filename.match(/.*\.d\.ts$/)) {
return;
}
filename = normalize(filename);
const snapshot = this.getScriptSnapshot(filename);
if (!snapshot) {
this._log('processFile', `Missing snapshot for: ${filename}`);
return;
}
const info = ts.preProcessFile(snapshot.getText(0, snapshot.getLength()), true);
// (1) ///-references
info.referencedFiles.forEach(ref => {
const resolvedPath = path.resolve(path.dirname(filename), ref.fileName);
const normalizedPath = normalize(resolvedPath);
this._dependencies.inertEdge(filename, normalizedPath);
});
// (2) import-require statements
info.importedFiles.forEach(ref => {
const stopDirname = normalize(this.getCurrentDirectory());
let dirname = filename;
let found = false;
while (!found && dirname.indexOf(stopDirname) === 0) {
dirname = path.dirname(dirname);
const resolvedPath = path.resolve(dirname, ref.fileName);
const normalizedPath = normalize(resolvedPath);
if (this.getScriptSnapshot(normalizedPath + '.ts')) {
this._dependencies.inertEdge(filename, normalizedPath + '.ts');
found = true;
} else if (this.getScriptSnapshot(normalizedPath + '.d.ts')) {
this._dependencies.inertEdge(filename, normalizedPath + '.d.ts');
found = true;
}
}
if (!found) {
for (let key in this._fileNameToDeclaredModule) {
if (this._fileNameToDeclaredModule[key] && ~this._fileNameToDeclaredModule[key].indexOf(ref.fileName)) {
this._dependencies.inertEdge(filename, key);
}
}
}
});
}
}

89
build/lib/tsb/index.js Normal file
View File

@@ -0,0 +1,89 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const Vinyl = require("vinyl");
const through = require("through");
const builder = require("./builder");
const ts = require("typescript");
const stream_1 = require("stream");
const path_1 = require("path");
const utils_1 = require("./utils");
const fs_1 = require("fs");
class EmptyDuplex extends stream_1.Duplex {
_write(_chunk, _encoding, callback) { callback(); }
_read() { this.push(null); }
}
function createNullCompiler() {
const result = function () { return new EmptyDuplex(); };
result.src = () => new EmptyDuplex();
return result;
}
const _defaultOnError = (err) => console.log(JSON.stringify(err, null, 4));
function create(projectPath, existingOptions, verbose = false, onError = _defaultOnError) {
function printDiagnostic(diag) {
if (!diag.file || !diag.start) {
onError(ts.flattenDiagnosticMessageText(diag.messageText, '\n'));
}
else {
const lineAndCh = diag.file.getLineAndCharacterOfPosition(diag.start);
onError(utils_1.strings.format('{0}({1},{2}): {3}', diag.file.fileName, lineAndCh.line + 1, lineAndCh.character + 1, ts.flattenDiagnosticMessageText(diag.messageText, '\n')));
}
}
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
if (parsed.error) {
printDiagnostic(parsed.error);
return createNullCompiler();
}
const cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, (0, path_1.dirname)(projectPath), existingOptions);
if (cmdLine.errors.length > 0) {
cmdLine.errors.forEach(printDiagnostic);
return createNullCompiler();
}
const _builder = builder.createTypeScriptBuilder({ verbose }, projectPath, cmdLine);
function createStream(token) {
return through(function (file) {
// give the file to the compiler
if (file.isStream()) {
this.emit('error', 'no support for streams');
return;
}
_builder.file(file);
}, function () {
// start the compilation process
_builder.build(file => this.queue(file), printDiagnostic, token).catch(e => console.error(e)).then(() => this.queue(null));
});
}
const result = (token) => createStream(token);
result.src = (opts) => {
let _pos = 0;
let _fileNames = cmdLine.fileNames.slice(0);
return new class extends stream_1.Readable {
constructor() {
super({ objectMode: true });
}
_read() {
let more = true;
let path;
for (; more && _pos < _fileNames.length; _pos++) {
path = _fileNames[_pos];
more = this.push(new Vinyl({
path,
contents: (0, fs_1.readFileSync)(path),
stat: (0, fs_1.statSync)(path),
cwd: opts && opts.cwd,
base: opts && opts.base || (0, path_1.dirname)(projectPath)
}));
}
if (_pos >= _fileNames.length) {
this.push(null);
}
}
};
};
return result;
}
exports.create = create;

118
build/lib/tsb/index.ts Normal file
View File

@@ -0,0 +1,118 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as Vinyl from 'vinyl';
import * as through from 'through';
import * as builder from './builder';
import * as ts from 'typescript';
import { Readable, Writable, Duplex } from 'stream';
import { dirname } from 'path';
import { strings } from './utils';
import { readFileSync, statSync } from 'fs';
export interface IncrementalCompiler {
(token?: any): Readable & Writable;
src(opts?: { cwd?: string; base?: string }): Readable;
}
class EmptyDuplex extends Duplex {
_write(_chunk: any, _encoding: string, callback: (err?: Error) => void): void { callback(); }
_read() { this.push(null); }
}
function createNullCompiler(): IncrementalCompiler {
const result: IncrementalCompiler = function () { return new EmptyDuplex(); };
result.src = () => new EmptyDuplex();
return result;
}
const _defaultOnError = (err: string) => console.log(JSON.stringify(err, null, 4));
export function create(
projectPath: string,
existingOptions: Partial<ts.CompilerOptions>,
verbose: boolean = false,
onError: (message: string) => void = _defaultOnError
): IncrementalCompiler {
function printDiagnostic(diag: ts.Diagnostic): void {
if (!diag.file || !diag.start) {
onError(ts.flattenDiagnosticMessageText(diag.messageText, '\n'));
} else {
const lineAndCh = diag.file.getLineAndCharacterOfPosition(diag.start);
onError(strings.format('{0}({1},{2}): {3}',
diag.file.fileName,
lineAndCh.line + 1,
lineAndCh.character + 1,
ts.flattenDiagnosticMessageText(diag.messageText, '\n'))
);
}
}
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
if (parsed.error) {
printDiagnostic(parsed.error);
return createNullCompiler();
}
const cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, dirname(projectPath), existingOptions);
if (cmdLine.errors.length > 0) {
cmdLine.errors.forEach(printDiagnostic);
return createNullCompiler();
}
const _builder = builder.createTypeScriptBuilder({ verbose }, projectPath, cmdLine);
function createStream(token?: builder.CancellationToken): Readable & Writable {
return through(function (this: through.ThroughStream, file: Vinyl) {
// give the file to the compiler
if (file.isStream()) {
this.emit('error', 'no support for streams');
return;
}
_builder.file(file);
}, function (this: { queue(a: any): void }) {
// start the compilation process
_builder.build(
file => this.queue(file),
printDiagnostic,
token
).catch(e => console.error(e)).then(() => this.queue(null));
});
}
const result = (token: builder.CancellationToken) => createStream(token);
result.src = (opts?: { cwd?: string; base?: string }) => {
let _pos = 0;
let _fileNames = cmdLine.fileNames.slice(0);
return new class extends Readable {
constructor() {
super({ objectMode: true });
}
_read() {
let more: boolean = true;
let path: string;
for (; more && _pos < _fileNames.length; _pos++) {
path = _fileNames[_pos];
more = this.push(new Vinyl({
path,
contents: readFileSync(path),
stat: statSync(path),
cwd: opts && opts.cwd,
base: opts && opts.base || dirname(projectPath)
}));
}
if (_pos >= _fileNames.length) {
this.push(null);
}
}
};
};
return <IncrementalCompiler>result;
}

124
build/lib/tsb/utils.js Normal file
View File

@@ -0,0 +1,124 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.graph = exports.strings = exports.collections = void 0;
var collections;
(function (collections) {
const hasOwnProperty = Object.prototype.hasOwnProperty;
function lookup(collection, key) {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
}
return null;
}
collections.lookup = lookup;
function insert(collection, key, value) {
collection[key] = value;
}
collections.insert = insert;
function lookupOrInsert(collection, key, value) {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
}
else {
collection[key] = value;
return value;
}
}
collections.lookupOrInsert = lookupOrInsert;
function forEach(collection, callback) {
for (let key in collection) {
if (hasOwnProperty.call(collection, key)) {
callback({
key: key,
value: collection[key]
});
}
}
}
collections.forEach = forEach;
function contains(collection, key) {
return hasOwnProperty.call(collection, key);
}
collections.contains = contains;
})(collections = exports.collections || (exports.collections = {}));
var strings;
(function (strings) {
/**
* The empty string. The one and only.
*/
strings.empty = '';
strings.eolUnix = '\r\n';
function format(value, ...rest) {
return value.replace(/({\d+})/g, function (match) {
const index = Number(match.substring(1, match.length - 1));
return String(rest[index]) || match;
});
}
strings.format = format;
})(strings = exports.strings || (exports.strings = {}));
var graph;
(function (graph) {
function newNode(data) {
return {
data: data,
incoming: {},
outgoing: {}
};
}
graph.newNode = newNode;
class Graph {
constructor(_hashFn) {
this._hashFn = _hashFn;
this._nodes = {};
// empty
}
traverse(start, inwards, callback) {
const startNode = this.lookup(start);
if (!startNode) {
return;
}
this._traverse(startNode, inwards, {}, callback);
}
_traverse(node, inwards, seen, callback) {
const key = this._hashFn(node.data);
if (collections.contains(seen, key)) {
return;
}
seen[key] = true;
callback(node.data);
const nodes = inwards ? node.outgoing : node.incoming;
collections.forEach(nodes, (entry) => this._traverse(entry.value, inwards, seen, callback));
}
inertEdge(from, to) {
const fromNode = this.lookupOrInsertNode(from);
const toNode = this.lookupOrInsertNode(to);
fromNode.outgoing[this._hashFn(to)] = toNode;
toNode.incoming[this._hashFn(from)] = fromNode;
}
removeNode(data) {
const key = this._hashFn(data);
delete this._nodes[key];
collections.forEach(this._nodes, (entry) => {
delete entry.value.outgoing[key];
delete entry.value.incoming[key];
});
}
lookupOrInsertNode(data) {
const key = this._hashFn(data);
let node = collections.lookup(this._nodes, key);
if (!node) {
node = newNode(data);
this._nodes[key] = node;
}
return node;
}
lookup(data) {
return collections.lookup(this._nodes, this._hashFn(data));
}
}
graph.Graph = Graph;
})(graph = exports.graph || (exports.graph = {}));

140
build/lib/tsb/utils.ts Normal file
View File

@@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export module collections {
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function lookup<T>(collection: { [keys: string]: T }, key: string): T | null {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
}
return null;
}
export function insert<T>(collection: { [keys: string]: T }, key: string, value: T): void {
collection[key] = value;
}
export function lookupOrInsert<T>(collection: { [keys: string]: T }, key: string, value: T): T {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
} else {
collection[key] = value;
return value;
}
}
export function forEach<T>(collection: { [keys: string]: T }, callback: (entry: { key: string; value: T }) => void): void {
for (let key in collection) {
if (hasOwnProperty.call(collection, key)) {
callback({
key: key,
value: collection[key]
});
}
}
}
export function contains(collection: { [keys: string]: any }, key: string): boolean {
return hasOwnProperty.call(collection, key);
}
}
export module strings {
/**
* The empty string. The one and only.
*/
export const empty = '';
export const eolUnix = '\r\n';
export function format(value: string, ...rest: any[]): string {
return value.replace(/({\d+})/g, function (match) {
const index = Number(match.substring(1, match.length - 1));
return String(rest[index]) || match;
});
}
}
export module graph {
export interface Node<T> {
data: T;
incoming: { [key: string]: Node<T> };
outgoing: { [key: string]: Node<T> };
}
export function newNode<T>(data: T): Node<T> {
return {
data: data,
incoming: {},
outgoing: {}
};
}
export class Graph<T> {
private _nodes: { [key: string]: Node<T> } = {};
constructor(private _hashFn: (element: T) => string) {
// empty
}
traverse(start: T, inwards: boolean, callback: (data: T) => void): void {
const startNode = this.lookup(start);
if (!startNode) {
return;
}
this._traverse(startNode, inwards, {}, callback);
}
private _traverse(node: Node<T>, inwards: boolean, seen: { [key: string]: boolean }, callback: (data: T) => void): void {
const key = this._hashFn(node.data);
if (collections.contains(seen, key)) {
return;
}
seen[key] = true;
callback(node.data);
const nodes = inwards ? node.outgoing : node.incoming;
collections.forEach(nodes, (entry) => this._traverse(entry.value, inwards, seen, callback));
}
inertEdge(from: T, to: T): void {
const fromNode = this.lookupOrInsertNode(from);
const toNode = this.lookupOrInsertNode(to);
fromNode.outgoing[this._hashFn(to)] = toNode;
toNode.incoming[this._hashFn(from)] = fromNode;
}
removeNode(data: T): void {
const key = this._hashFn(data);
delete this._nodes[key];
collections.forEach(this._nodes, (entry) => {
delete entry.value.outgoing[key];
delete entry.value.incoming[key];
});
}
lookupOrInsertNode(data: T): Node<T> {
const key = this._hashFn(data);
let node = collections.lookup(this._nodes, key);
if (!node) {
node = newNode(data);
this._nodes[key] = node;
}
return node;
}
lookup(data: T): Node<T> | null {
return collections.lookup(this._nodes, this._hashFn(data));
}
}
}

View File

@@ -1,18 +0,0 @@
declare module "gulp-tsb" {
export interface ICancellationToken {
isCancellationRequested(): boolean;
}
export interface IncrementalCompiler {
(token?: ICancellationToken): NodeJS.ReadWriteStream;
src(opts?: {
cwd?: string;
base?: string;
}): NodeJS.ReadStream;
}
export function create(projectPath: string, existingOptions: any, verbose?: boolean, onError?: (message: any) => void): IncrementalCompiler;
}

View File

@@ -4,20 +4,20 @@
*--------------------------------------------------------------------------------------------*/
var gulp = require('gulp');
var tsb = require('gulp-tsb');
var tsb = require('../../../../build/lib/tsb');
var util = require('./lib/util');
var watcher = require('./lib/watch');
var assign = require('object-assign');
var compilation = tsb.create(assign({ verbose: true }, require('./tsconfig.json').compilerOptions));
gulp.task('compile', function() {
gulp.task('compile', function () {
return gulp.src('**/*.ts', { base: '.' })
.pipe(compilation())
.pipe(gulp.dest(''));
});
gulp.task('watch', function() {
gulp.task('watch', function () {
var src = gulp.src('**/*.ts', { base: '.' });
return watcher('**/*.ts', { base: '.' })
@@ -28,10 +28,10 @@ gulp.task('watch', function() {
gulp.task('default', ['compile']);
function cloneArray(arr) {
_.foo();
var r = [];
for (var i = 0, len = arr.length; i < len; i++) {
r[i] = doClone(arr[i]);
}
return r;
}
_.foo();
var r = [];
for (var i = 0, len = arr.length; i < len; i++) {
r[i] = doClone(arr[i]);
}
return r;
}

View File

@@ -336,7 +336,7 @@
}
},
{
"c": "gulp-tsb",
"c": "../../../../build/lib/tsb",
"t": "source.js meta.var.expr.js string.quoted.single.js",
"r": {
"dark_plus": "string: #CE9178",
@@ -1355,6 +1355,18 @@
"hc_light": "storage.type: #0F4A85"
}
},
{
"c": " ",
"t": "source.js meta.function.expression.js",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF",
"hc_light": "default: #292929"
}
},
{
"c": "(",
"t": "source.js meta.function.expression.js meta.parameters.js punctuation.definition.parameters.begin.js",
@@ -2051,6 +2063,18 @@
"hc_light": "storage.type: #0F4A85"
}
},
{
"c": " ",
"t": "source.js meta.function.expression.js",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF",
"hc_light": "default: #292929"
}
},
{
"c": "(",
"t": "source.js meta.function.expression.js meta.parameters.js punctuation.definition.parameters.begin.js",
@@ -3312,7 +3336,7 @@
}
},
{
"c": " ",
"c": "\t",
"t": "source.js meta.function.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -3384,7 +3408,7 @@
}
},
{
"c": " ",
"c": "\t",
"t": "source.js meta.function.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -3492,7 +3516,7 @@
}
},
{
"c": " ",
"c": "\t",
"t": "source.js meta.function.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -3900,7 +3924,7 @@
}
},
{
"c": " ",
"c": "\t\t",
"t": "source.js meta.function.js meta.block.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -4092,7 +4116,7 @@
}
},
{
"c": " ",
"c": "\t",
"t": "source.js meta.function.js meta.block.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -4116,7 +4140,7 @@
}
},
{
"c": " ",
"c": "\t",
"t": "source.js meta.function.js meta.block.js",
"r": {
"dark_plus": "default: #D4D4D4",

View File

@@ -163,7 +163,6 @@
"gulp-replace": "^0.5.4",
"gulp-sourcemaps": "^3.0.0",
"gulp-svgmin": "^4.1.0",
"gulp-tsb": "4.0.6",
"gulp-untar": "^0.0.7",
"gulp-vinyl-zip": "^2.1.2",
"husky": "^0.13.1",

View File

@@ -5983,16 +5983,6 @@ gulp-symdest@^1.2.0:
queue "^3.1.0"
vinyl-fs "^3.0.3"
gulp-tsb@4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/gulp-tsb/-/gulp-tsb-4.0.6.tgz#526f07a2c74e1d2f8932b1500316f2a64b33363c"
integrity sha512-55HSu1zvOOq7D+OqPScvGQaJPKveLbM1T5jEnSJUhbcbwX1Kx0SWv4UVe7MfFcBwFe3wMiWSkKoajNONEv5E9g==
dependencies:
ansi-colors "^1.0.1"
fancy-log "^1.3.2"
through "^2.3.6"
vinyl "^2.1.0"
gulp-untar@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4"