提交 9deb8d4a 编写于 作者: A Alex Dima

Read monaco.d.ts.recipe files as needed (don't prepare them up front)

上级 7e8384ba
......@@ -11,7 +11,6 @@ const bom = require("gulp-bom");
const sourcemaps = require("gulp-sourcemaps");
const tsb = require("gulp-tsb");
const path = require("path");
const ts = require("typescript");
const _ = require("underscore");
const monacodts = require("../monaco/api");
const nls = require("./nls");
......@@ -112,43 +111,42 @@ class MonacoGenerator {
this._executeSoonTimer = null;
this._isWatch = isWatch;
this.stream = es.through();
this._inputFiles = monacodts.getIncludesInRecipe().map((moduleId) => {
if (/\.d\.ts$/.test(moduleId)) {
// This source file is already in .d.ts form
return path.join(REPO_SRC_FOLDER, moduleId);
this._watchers = [];
this._watchedFiles = {};
let onWillReadFile = (moduleId, filePath) => {
if (!this._isWatch) {
return;
}
else {
return path.join(REPO_SRC_FOLDER, `${moduleId}.ts`);
if (this._watchedFiles[filePath]) {
return;
}
});
// Install watchers
this._watchers = [];
if (this._isWatch) {
this._inputFiles.forEach((filePath) => {
this._watchedFiles[filePath] = true;
const watcher = fs.watch(filePath);
watcher.addListener('change', () => {
this._inputFileChanged[filePath] = true;
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
this._watchers.push(watcher);
});
};
this._fsProvider = new class extends monacodts.FSProvider {
readFileSync(moduleId, filePath) {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
const recipeWatcher = fs.watch(monacodts.RECIPE_PATH);
recipeWatcher.addListener('change', () => {
this._recipeFileChanged = true;
this._executeSoon();
});
this._watchers.push(recipeWatcher);
}
this._inputFileChanged = {};
this._inputFiles.forEach(file => this._inputFileChanged[file] = true);
this._recipeFileChanged = true;
this._dtsFilesContents = {};
this._dtsFilesContents2 = {};
}
_executeSoon() {
if (this._executeSoonTimer !== null) {
// Already scheduled
return;
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
......@@ -159,49 +157,10 @@ class MonacoGenerator {
this._watchers.forEach(watcher => watcher.close());
}
_run() {
let somethingChanged = false;
const setDTSFileContent = (file, contents) => {
if (this._dtsFilesContents[file] === contents) {
return;
}
this._dtsFilesContents[file] = contents;
this._dtsFilesContents2[file] = ts.createSourceFile(file, contents, ts.ScriptTarget.ES5);
somethingChanged = true;
};
const fileMap = {};
this._inputFiles.forEach((inputFile) => {
if (!this._inputFileChanged[inputFile]) {
return;
}
this._inputFileChanged[inputFile] = false;
const inputFileContents = fs.readFileSync(inputFile).toString();
if (/\.d\.ts$/.test(inputFile)) {
// This is a .d.ts file
setDTSFileContent(inputFile, inputFileContents);
return;
}
fileMap[inputFile] = inputFileContents;
});
if (Object.keys(fileMap).length > 0) {
const service = ts.createLanguageService(new monacodts.TypeScriptLanguageServiceHost({}, fileMap, {}));
Object.keys(fileMap).forEach((fileName) => {
const output = service.getEmitOutput(fileName, true).outputFiles[0].text;
const destFileName = fileName.replace(/\.ts$/, '.d.ts');
setDTSFileContent(destFileName, output);
});
}
if (this._recipeFileChanged) {
this._recipeFileChanged = false;
somethingChanged = true;
}
if (!somethingChanged) {
// Nothing changed
return null;
}
let r = monacodts.run2('src', this._dtsFilesContents2);
let r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts genration error - Cannot continue`);
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
......
......@@ -12,7 +12,6 @@ import * as bom from 'gulp-bom';
import * as sourcemaps from 'gulp-sourcemaps';
import * as tsb from 'gulp-tsb';
import * as path from 'path';
import * as ts from 'typescript';
import * as _ from 'underscore';
import * as monacodts from '../monaco/api';
import * as nls from './nls';
......@@ -135,62 +134,55 @@ const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
class MonacoGenerator {
private readonly _isWatch: boolean;
public readonly stream: NodeJS.ReadWriteStream;
/**
* This list is never changed for the lifetime of this object.
*/
private readonly _inputFiles: string[];
private readonly _watchers: fs.FSWatcher[];
private _inputFileChanged: { [filePath: string]: boolean; };
private _recipeFileChanged: boolean;
private _dtsFilesContents: { [filePath: string]: string; };
private _dtsFilesContents2: { [filePath: string]: ts.SourceFile; };
private readonly _watchers: fs.FSWatcher[];
private readonly _watchedFiles: { [filePath: string]: boolean; };
private readonly _fsProvider: monacodts.FSProvider;
private readonly _declarationResolver: monacodts.DeclarationResolver;
constructor(isWatch: boolean) {
this._isWatch = isWatch;
this.stream = es.through();
this._inputFiles = monacodts.getIncludesInRecipe().map((moduleId) => {
if (/\.d\.ts$/.test(moduleId)) {
// This source file is already in .d.ts form
return path.join(REPO_SRC_FOLDER, moduleId);
} else {
return path.join(REPO_SRC_FOLDER, `${moduleId}.ts`);
this._watchers = [];
this._watchedFiles = {};
let onWillReadFile = (moduleId: string, filePath: string) => {
if (!this._isWatch) {
return;
}
});
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
// Install watchers
this._watchers = [];
if (this._isWatch) {
this._inputFiles.forEach((filePath) => {
const watcher = fs.watch(filePath);
watcher.addListener('change', () => {
this._inputFileChanged[filePath] = true;
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
this._watchers.push(watcher);
});
};
this._fsProvider = new class extends monacodts.FSProvider {
public readFileSync(moduleId: string, filePath: string): Buffer {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
const recipeWatcher = fs.watch(monacodts.RECIPE_PATH);
recipeWatcher.addListener('change', () => {
this._recipeFileChanged = true;
this._executeSoon();
});
this._watchers.push(recipeWatcher);
}
this._inputFileChanged = {};
this._inputFiles.forEach(file => this._inputFileChanged[file] = true);
this._recipeFileChanged = true;
this._dtsFilesContents = {};
this._dtsFilesContents2 = {};
}
private _executeSoonTimer: NodeJS.Timer | null = null;
private _executeSoon(): void {
if (this._executeSoonTimer !== null) {
// Already scheduled
return;
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
......@@ -203,59 +195,10 @@ class MonacoGenerator {
}
private _run(): monacodts.IMonacoDeclarationResult | null {
let somethingChanged = false;
const setDTSFileContent = (file: string, contents: string): void => {
if (this._dtsFilesContents[file] === contents) {
return;
}
this._dtsFilesContents[file] = contents;
this._dtsFilesContents2[file] = ts.createSourceFile(file, contents, ts.ScriptTarget.ES5);
somethingChanged = true;
};
const fileMap: { [fileName: string]: string; } = {};
this._inputFiles.forEach((inputFile) => {
if (!this._inputFileChanged[inputFile]) {
return;
}
this._inputFileChanged[inputFile] = false;
const inputFileContents = fs.readFileSync(inputFile).toString();
if (/\.d\.ts$/.test(inputFile)) {
// This is a .d.ts file
setDTSFileContent(inputFile, inputFileContents);
return;
}
fileMap[inputFile] = inputFileContents;
});
if (Object.keys(fileMap).length > 0) {
const service = ts.createLanguageService(new monacodts.TypeScriptLanguageServiceHost({}, fileMap, {}));
Object.keys(fileMap).forEach((fileName) => {
const output = service.getEmitOutput(fileName, true).outputFiles[0].text;
const destFileName = fileName.replace(/\.ts$/, '.d.ts');
setDTSFileContent(destFileName, output);
});
}
if (this._recipeFileChanged) {
this._recipeFileChanged = false;
somethingChanged = true;
}
if (!somethingChanged) {
// Nothing changed
return null;
}
let r = monacodts.run2('src', this._dtsFilesContents2);
let r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts genration error - Cannot continue`);
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
......
......@@ -8,29 +8,17 @@ const fs = require("fs");
const ts = require("typescript");
const path = require("path");
const util = require("gulp-util");
const dtsv = '1';
const dtsv = '2';
const tsfmt = require('../../tsfmt.json');
function log(message, ...rest) {
util.log(util.colors.cyan('[monaco.d.ts]'), message, ...rest);
}
const SRC = path.join(__dirname, '../../src');
const OUT_ROOT = path.join(__dirname, '../../');
exports.RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
var CURRENT_PROCESSING_RULE = '';
function logErr(message, ...rest) {
util.log(util.colors.red('[monaco.d.ts]'), 'WHILE HANDLING RULE: ', CURRENT_PROCESSING_RULE);
util.log(util.colors.red('[monaco.d.ts]'), message, ...rest);
}
function _logErr(message, ...rest) {
util.log(util.colors.red(`[monaco.d.ts]`), message, ...rest);
}
function moduleIdToPath(out, moduleId) {
if (/\.d\.ts/.test(moduleId)) {
return path.join(SRC, moduleId);
}
return path.join(OUT_ROOT, out, moduleId) + '.d.ts';
}
function isDeclaration(a) {
return (a.kind === ts.SyntaxKind.InterfaceDeclaration
|| a.kind === ts.SyntaxKind.EnumDeclaration
......@@ -339,11 +327,11 @@ function generateDeclarationFile(recipe, sourceFileGetter) {
}
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m1) {
CURRENT_PROCESSING_RULE = line;
let moduleId = m1[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
_logErr(`gulp watch restart required. ${moduleId} was added to 'monaco.d.ts.recipe'.`);
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
......@@ -357,7 +345,9 @@ function generateDeclarationFile(recipe, sourceFileGetter) {
}
let declaration = getTopLevelDeclaration(sourceFile, typeName);
if (!declaration) {
logErr('Cannot find type ' + typeName);
logErr(`While handling ${line}`);
logErr(`Cannot find ${typeName}`);
failed = true;
return;
}
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
......@@ -366,11 +356,11 @@ function generateDeclarationFile(recipe, sourceFileGetter) {
}
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m2) {
CURRENT_PROCESSING_RULE = line;
let moduleId = m2[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
_logErr(`gulp watch restart required. ${moduleId} was added to 'monaco.d.ts.recipe'.`);
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
......@@ -413,10 +403,10 @@ function generateDeclarationFile(recipe, sourceFileGetter) {
}
if (version !== dtsv) {
if (!version) {
_logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
}
else {
_logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
}
return null;
}
......@@ -441,31 +431,6 @@ function generateDeclarationFile(recipe, sourceFileGetter) {
enums: resultEnums
};
}
function getIncludesInRecipe() {
let recipe = fs.readFileSync(exports.RECIPE_PATH).toString();
let lines = recipe.split(/\r\n|\n|\r/);
let result = [];
lines.forEach(line => {
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m1) {
let moduleId = m1[1];
result.push(moduleId);
return;
}
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m2) {
let moduleId = m2[1];
result.push(moduleId);
return;
}
});
return result;
}
exports.getIncludesInRecipe = getIncludesInRecipe;
function getFilesToWatch(out) {
return getIncludesInRecipe().map((moduleId) => moduleIdToPath(out, moduleId));
}
exports.getFilesToWatch = getFilesToWatch;
function _run(sourceFileGetter) {
log('Starting monaco.d.ts generation');
const recipe = fs.readFileSync(exports.RECIPE_PATH).toString();
......@@ -489,35 +454,57 @@ function _run(sourceFileGetter) {
isTheSame
};
}
function run(out, inputFiles) {
let SOURCE_FILE_MAP = {};
const sourceFileGetter = (moduleId) => {
if (!SOURCE_FILE_MAP[moduleId]) {
let filePath = path.normalize(moduleIdToPath(out, moduleId));
if (!inputFiles.hasOwnProperty(filePath)) {
logErr('CANNOT FIND FILE ' + filePath + '. YOU MIGHT NEED TO RESTART gulp');
class FSProvider {
existsSync(filePath) {
return fs.existsSync(filePath);
}
readFileSync(_moduleId, filePath) {
return fs.readFileSync(filePath);
}
}
exports.FSProvider = FSProvider;
class DeclarationResolver {
constructor(_fsProvider) {
this._fsProvider = _fsProvider;
this._sourceFileCache = Object.create(null);
}
invalidateCache(moduleId) {
this._sourceFileCache[moduleId] = null;
}
getDeclarationSourceFile(moduleId) {
if (!this._sourceFileCache[moduleId]) {
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
}
return this._sourceFileCache[moduleId];
}
_getDeclarationSourceFile(moduleId) {
if (/\.d\.ts$/.test(moduleId)) {
const fileName = path.join(SRC, moduleId);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
let fileContents = inputFiles[filePath];
let sourceFile = ts.createSourceFile(filePath, fileContents, ts.ScriptTarget.ES5);
SOURCE_FILE_MAP[moduleId] = sourceFile;
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
return ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5);
}
const fileName = path.join(SRC, `${moduleId}.ts`);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
return SOURCE_FILE_MAP[moduleId];
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
const fileMap = {
'file.ts': fileContents
};
return _run(sourceFileGetter);
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
const text = service.getEmitOutput('file.ts', true).outputFiles[0].text;
return ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5);
}
}
function run2(out, sourceFileMap) {
const sourceFileGetter = (moduleId) => {
let filePath = path.normalize(moduleIdToPath(out, moduleId));
return sourceFileMap[filePath];
};
exports.DeclarationResolver = DeclarationResolver;
function run3(resolver) {
const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId);
return _run(sourceFileGetter);
}
exports.run2 = run2;
function complainErrors() {
logErr('Not running monaco.d.ts generation due to compile errors');
}
exports.complainErrors = complainErrors;
exports.run3 = run3;
class TypeScriptLanguageServiceHost {
constructor(libs, files, compilerOptions) {
this._libs = libs;
......@@ -563,31 +550,10 @@ class TypeScriptLanguageServiceHost {
return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
}
exports.TypeScriptLanguageServiceHost = TypeScriptLanguageServiceHost;
function execute() {
const OUTPUT_FILES = {};
const SRC_FILES = {};
const SRC_FILE_TO_EXPECTED_NAME = {};
getIncludesInRecipe().forEach((moduleId) => {
if (/\.d\.ts$/.test(moduleId)) {
let fileName = path.join(SRC, moduleId);
OUTPUT_FILES[moduleIdToPath('src', moduleId)] = fs.readFileSync(fileName).toString();
return;
}
let fileName = path.join(SRC, moduleId) + '.ts';
SRC_FILES[fileName] = fs.readFileSync(fileName).toString();
SRC_FILE_TO_EXPECTED_NAME[fileName] = moduleIdToPath('src', moduleId);
});
const languageService = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, SRC_FILES, {}));
var t1 = Date.now();
Object.keys(SRC_FILES).forEach((fileName) => {
const emitOutput = languageService.getEmitOutput(fileName, true);
OUTPUT_FILES[SRC_FILE_TO_EXPECTED_NAME[fileName]] = emitOutput.outputFiles[0].text;
});
console.log(`Generating .d.ts took ${Date.now() - t1} ms`);
let r = run('src', OUTPUT_FILES);
let r = run3(new DeclarationResolver(new FSProvider()));
if (!r) {
throw new Error(`monaco.d.ts genration error - Cannot continue`);
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
......
......@@ -8,7 +8,7 @@ import * as ts from 'typescript';
import * as path from 'path';
import * as util from 'gulp-util';
const dtsv = '1';
const dtsv = '2';
const tsfmt = require('../../tsfmt.json');
......@@ -17,30 +17,14 @@ function log(message: any, ...rest: any[]): void {
}
const SRC = path.join(__dirname, '../../src');
const OUT_ROOT = path.join(__dirname, '../../');
export const RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
var CURRENT_PROCESSING_RULE = '';
function logErr(message: any, ...rest: any[]): void {
util.log(util.colors.red('[monaco.d.ts]'), 'WHILE HANDLING RULE: ', CURRENT_PROCESSING_RULE);
util.log(util.colors.red('[monaco.d.ts]'), message, ...rest);
}
function _logErr(message: any, ...rest: any[]): void {
util.log(util.colors.red(`[monaco.d.ts]`), message, ...rest);
}
function moduleIdToPath(out: string, moduleId: string): string {
if (/\.d\.ts/.test(moduleId)) {
return path.join(SRC, moduleId);
}
return path.join(OUT_ROOT, out, moduleId) + '.d.ts';
}
export interface ISourceFileMap {
[moduleId: string]: ts.SourceFile;
}
export type SourceFileGetter = (moduleId: string) => ts.SourceFile | null;
type SourceFileGetter = (moduleId: string) => ts.SourceFile | null;
type TSTopLevelDeclaration = ts.InterfaceDeclaration | ts.EnumDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration | ts.FunctionDeclaration | ts.ModuleDeclaration;
type TSTopLevelDeclare = TSTopLevelDeclaration | ts.VariableStatement;
......@@ -410,11 +394,11 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m1) {
CURRENT_PROCESSING_RULE = line;
let moduleId = m1[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
_logErr(`gulp watch restart required. ${moduleId} was added to 'monaco.d.ts.recipe'.`);
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
......@@ -431,7 +415,9 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet
}
let declaration = getTopLevelDeclaration(sourceFile, typeName);
if (!declaration) {
logErr('Cannot find type ' + typeName);
logErr(`While handling ${line}`);
logErr(`Cannot find ${typeName}`);
failed = true;
return;
}
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
......@@ -441,11 +427,11 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m2) {
CURRENT_PROCESSING_RULE = line;
let moduleId = m2[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
_logErr(`gulp watch restart required. ${moduleId} was added to 'monaco.d.ts.recipe'.`);
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
......@@ -494,9 +480,9 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet
if (version !== dtsv) {
if (!version) {
_logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
} else {
_logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
}
return null;
}
......@@ -525,35 +511,6 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet
};
}
export function getIncludesInRecipe(): string[] {
let recipe = fs.readFileSync(RECIPE_PATH).toString();
let lines = recipe.split(/\r\n|\n|\r/);
let result: string[] = [];
lines.forEach(line => {
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m1) {
let moduleId = m1[1];
result.push(moduleId);
return;
}
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m2) {
let moduleId = m2[1];
result.push(moduleId);
return;
}
});
return result;
}
export function getFilesToWatch(out: string): string[] {
return getIncludesInRecipe().map((moduleId) => moduleIdToPath(out, moduleId));
}
export interface IMonacoDeclarationResult {
content: string;
usageContent: string;
......@@ -591,48 +548,69 @@ function _run(sourceFileGetter: SourceFileGetter): IMonacoDeclarationResult | nu
};
}
function run(out: string, inputFiles: { [file: string]: string; }): IMonacoDeclarationResult | null {
export class FSProvider {
public existsSync(filePath: string): boolean {
return fs.existsSync(filePath);
}
public readFileSync(_moduleId: string, filePath: string): Buffer {
return fs.readFileSync(filePath);
}
}
export class DeclarationResolver {
let SOURCE_FILE_MAP: { [moduleId: string]: ts.SourceFile; } = {};
const sourceFileGetter = (moduleId: string): ts.SourceFile | null => {
if (!SOURCE_FILE_MAP[moduleId]) {
let filePath = path.normalize(moduleIdToPath(out, moduleId));
private _sourceFileCache: { [moduleId: string]: ts.SourceFile | null; };
if (!inputFiles.hasOwnProperty(filePath)) {
logErr('CANNOT FIND FILE ' + filePath + '. YOU MIGHT NEED TO RESTART gulp');
return null;
constructor(private readonly _fsProvider: FSProvider) {
this._sourceFileCache = Object.create(null);
}
let fileContents = inputFiles[filePath];
let sourceFile = ts.createSourceFile(filePath, fileContents, ts.ScriptTarget.ES5);
SOURCE_FILE_MAP[moduleId] = sourceFile;
public invalidateCache(moduleId: string): void {
this._sourceFileCache[moduleId] = null;
}
return SOURCE_FILE_MAP[moduleId];
};
return _run(sourceFileGetter);
}
public getDeclarationSourceFile(moduleId: string): ts.SourceFile | null {
if (!this._sourceFileCache[moduleId]) {
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
}
return this._sourceFileCache[moduleId];
}
export function run2(out: string, sourceFileMap: ISourceFileMap): IMonacoDeclarationResult | null {
const sourceFileGetter = (moduleId: string): ts.SourceFile | null => {
let filePath = path.normalize(moduleIdToPath(out, moduleId));
return sourceFileMap[filePath];
private _getDeclarationSourceFile(moduleId: string): ts.SourceFile | null {
if (/\.d\.ts$/.test(moduleId)) {
const fileName = path.join(SRC, moduleId);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
return ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5);
}
const fileName = path.join(SRC, `${moduleId}.ts`);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
const fileMap: IFileMap = {
'file.ts': fileContents
};
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
const text = service.getEmitOutput('file.ts', true).outputFiles[0].text;
return ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5);
}
}
export function run3(resolver: DeclarationResolver): IMonacoDeclarationResult | null {
const sourceFileGetter = (moduleId: string) => resolver.getDeclarationSourceFile(moduleId);
return _run(sourceFileGetter);
}
export function complainErrors() {
logErr('Not running monaco.d.ts generation due to compile errors');
}
interface ILibMap { [libName: string]: string; }
interface IFileMap { [fileName: string]: string; }
export class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
private readonly _libs: ILibMap;
private readonly _files: IFileMap;
......@@ -686,34 +664,9 @@ export class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
}
export function execute(): IMonacoDeclarationResult {
const OUTPUT_FILES: { [file: string]: string; } = {};
const SRC_FILES: IFileMap = {};
const SRC_FILE_TO_EXPECTED_NAME: { [filename: string]: string; } = {};
getIncludesInRecipe().forEach((moduleId) => {
if (/\.d\.ts$/.test(moduleId)) {
let fileName = path.join(SRC, moduleId);
OUTPUT_FILES[moduleIdToPath('src', moduleId)] = fs.readFileSync(fileName).toString();
return;
}
let fileName = path.join(SRC, moduleId) + '.ts';
SRC_FILES[fileName] = fs.readFileSync(fileName).toString();
SRC_FILE_TO_EXPECTED_NAME[fileName] = moduleIdToPath('src', moduleId);
});
const languageService = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, SRC_FILES, {}));
var t1 = Date.now();
Object.keys(SRC_FILES).forEach((fileName) => {
const emitOutput = languageService.getEmitOutput(fileName, true);
OUTPUT_FILES[SRC_FILE_TO_EXPECTED_NAME[fileName]] = emitOutput.outputFiles[0].text;
});
console.log(`Generating .d.ts took ${Date.now() - t1} ms`);
let r = run('src', OUTPUT_FILES);
let r = run3(new DeclarationResolver(new FSProvider()));
if (!r) {
throw new Error(`monaco.d.ts genration error - Cannot continue`);
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
......@@ -86,4 +86,4 @@ declare namespace monaco.worker {
}
//dtsv=1
\ No newline at end of file
//dtsv=2
\ No newline at end of file
......@@ -5543,4 +5543,4 @@ declare namespace monaco.worker {
}
//dtsv=1
\ No newline at end of file
//dtsv=2
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册