UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

224 lines (187 loc) 7.25 kB
import { Tree } from '@angular-devkit/schematics'; import * as pathFs from 'path'; import * as ts from 'typescript/lib/tsserverlibrary'; import { CUSTOM_TS_PLUGIN_NAME, CUSTOM_TS_PLUGIN_PATH } from './tsUtils'; /** * Language server host is responsible for **most** of the FS operations / checks * Angular's Ivy LS sometimes bypasses these, calling path methods instead of tsLsHost operations */ export class ServerHost implements ts.server.ServerHost { public readonly args: string[]; public readonly newLine: string; public readonly useCaseSensitiveFileNames: boolean; constructor(private host: Tree) { this.args = ts.sys.args; this.newLine = ts.sys.newLine; this.useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames; } /** * Read a file's content from the Virtual Tree * If file does not exist in virtual tree, check in physical FS */ public readFile(path: string, encoding?: BufferEncoding): string | undefined { let content; // ensure the path is relative, so it can be found in the Tree, reflecting latest state path = pathFs.relative(this.getCurrentDirectory(), path); try { content = this.host.read(path).toString(encoding); } finally { // eslint-disable-next-line no-unsafe-finally return content || ts.sys.readFile(path, encoding); } } public getFileSize(path: string): number { return ts.sys.getFileSize(path); } //#region Watchers // Atm we do not need to have file or dir watchers that access the actual FS // as we are only working with NG's virtual FS // Prior to https://github.com/microsoft/TypeScript/pull/49990 we were more or less required // to add a watcher since it threw an error otherwise public watchFile(_path: string, _callback: ts.FileWatcherCallback, _pollingInterval?: number): ts.FileWatcher { // return ts.sys.watchFile(path, callback, pollingInterval); return undefined; } public watchDirectory(_path: string, _callback: ts.DirectoryWatcherCallback, _recursive?: boolean): ts.FileWatcher { // return ts.sys.watchDirectory(path, callback, recursive); return undefined; } //#endregion public resolvePath(path: string): string { return ts.sys.resolvePath(path); } /** * Checks for file in Virtual Tree w/ relative path * If file does not exist in virtual tree, check in physical FS */ public fileExists(path: string): boolean { // check for file in Tree, as schematics might need for check path = pathFs.relative(this.getCurrentDirectory(), path); let flag = false; try { // Tree.exists throws on invalid paths instead of returning false flag = this.host.exists(path); } finally { // eslint-disable-next-line no-unsafe-finally return flag || ts.sys.fileExists(path); } } public directoryExists(path: string): boolean { let exists: boolean; path = pathFs.relative(this.getCurrentDirectory(), path); try { exists = this.host.getDir(path) !== void 0; } finally { // eslint-disable-next-line no-unsafe-finally return exists || ts.sys.directoryExists(path); } } public getExecutingFilePath(): string { return ts.sys.getExecutingFilePath(); } public getCurrentDirectory(): string { // both TS and NG lang serves work with absolute paths // we provide cwd instead of tree root so paths can be resolved to absolute ones return process.cwd(); } /** * Get all subdirs of a directory from the Tree mapped to absolute paths */ public getDirectories(path: string): string[] { // check directory contents in Tree (w/ relative paths) path = pathFs.relative(this.getCurrentDirectory(), path); // return directory contents w/ absolute paths for LS return this.host.getDir(path).subdirs.map(e => pathFs.resolve(e)); } /** * Get all files of a directory from the Tree mapped to absolute paths */ public readDirectory(path: string): string[] { // check directory contents in Tree (w/ relative paths) path = pathFs.relative(this.getCurrentDirectory(), path); // return directory contents w/ absolute paths for LS return this.host.getDir(path).subfiles.map(e => pathFs.resolve(e)); } public require(initialPath: string, moduleName: string) { try { const paths = [initialPath]; if (moduleName === CUSTOM_TS_PLUGIN_NAME) { moduleName = CUSTOM_TS_PLUGIN_PATH; paths.push(__dirname); } const modulePath = require.resolve(moduleName, { paths }); return { module: require(modulePath), error: undefined, }; } catch (e) { return { module: undefined, error: e as Error, }; } } public gc(): void { global.gc(); } public trace(_s: string): void { /* noop */ } public getModifiedTime(path: string): Date | undefined { return ts.sys.getModifiedTime(path); } public realpath(path: string): string { return ts.sys.realpath(path); } public createSHA256Hash(data: string): string { return ts.sys.createSHA256Hash(data); } public write(data: string): void { ts.sys.write(data); } public writeOutputIsTTY(): boolean { return ts.sys.writeOutputIsTTY(); } public writeFile(path: string, data: string, writeByteOrderMark?: boolean): void { return ts.sys.writeFile(path, data, writeByteOrderMark); } public createDirectory(path: string): void { return ts.sys.createDirectory(path); } public setModifiedTime(path: string, time: Date): void { return ts.sys.setModifiedTime(path, time); } public deleteFile(path: string): void { return ts.sys.deleteFile(path); } public createHash(data: string): string { return ts.sys.createHash(data); } public getMemoryUsage(): number { return ts.sys.getMemoryUsage(); } public exit(exitCode?: number): void { return ts.sys.exit(exitCode); } public setTimeout(callback: (...argsv: any[]) => void, ms: number, ...args: any[]): any { return ts.sys.setTimeout(callback, ms, ...args); } public clearTimeout(timeoutId: any): void { return ts.sys.clearTimeout(timeoutId); } public clearScreen(): void { return ts.sys.clearScreen(); } public base64decode(input: string): string { return ts.sys.base64decode(input); } public base64encode(input: string): string { return ts.sys.base64encode(input); } public setImmediate(callback: (...argsv: any[]) => void, ...args: any[]): any { return setImmediate(callback, ...args); } public clearImmediate(timeoutId: any): void { return clearImmediate(timeoutId); } }