From d39c4bbe374ba9193bbc4f9a981d20ce2f1fd3dd Mon Sep 17 00:00:00 2001 From: ayazhafiz Date: Fri, 30 Oct 2020 17:16:39 -0500 Subject: [PATCH] refactor(language-service): language_service_adapter -> adapters (#39619) This rename is done because we know have a file system adapter over a project as well as the compiler adapter. PR Close #39619 --- packages/compiler-cli/src/perform_compile.ts | 18 ++++---- ...anguage_service_adapter.ts => adapters.ts} | 21 +++++----- .../language-service/ivy/compiler_factory.ts | 2 +- .../language-service/ivy/language_service.ts | 12 +++--- .../legacy/language_service_adapter_spec.ts | 41 ------------------- packages/language-service/ivy/utils.ts | 1 + 6 files changed, 30 insertions(+), 65 deletions(-) rename packages/language-service/ivy/{language_service_adapter.ts => adapters.ts} (86%) delete mode 100644 packages/language-service/ivy/test/legacy/language_service_adapter_spec.ts diff --git a/packages/compiler-cli/src/perform_compile.ts b/packages/compiler-cli/src/perform_compile.ts index 3ec3ca0783..cde0281fc2 100644 --- a/packages/compiler-cli/src/perform_compile.ts +++ b/packages/compiler-cli/src/perform_compile.ts @@ -108,9 +108,10 @@ export function formatDiagnostics( } } +/** Used to read configuration files. */ // TODO(ayazhafiz): split FileSystem into a ReadonlyFileSystem and make this a // subset of that. -export type ParseConfigurationHost = +export type ConfigurationHost = Pick; export interface ParsedConfiguration { @@ -119,11 +120,11 @@ export interface ParsedConfiguration { rootNames: string[]; projectReferences?: readonly ts.ProjectReference[]|undefined; emitFlags: api.EmitFlags; - errors: Diagnostics; + errors: ts.Diagnostic[]; } export function calcProjectFileAndBasePath( - project: string, host: ParseConfigurationHost = getFileSystem()): + project: string, host: ConfigurationHost = getFileSystem()): {projectFile: AbsoluteFsPath, basePath: AbsoluteFsPath} { const absProject = host.resolve(project); const projectIsDir = host.lstat(absProject).isDirectory(); @@ -145,7 +146,7 @@ export function createNgCompilerOptions( export function readConfiguration( project: string, existingOptions?: ts.CompilerOptions, - host: ParseConfigurationHost = getFileSystem()): ParsedConfiguration { + host: ConfigurationHost = getFileSystem()): ParsedConfiguration { try { const {projectFile, basePath} = calcProjectFileAndBasePath(project, host); @@ -223,11 +224,14 @@ export function readConfiguration( emitFlags }; } catch (e) { - const errors: Diagnostics = [{ + const errors: ts.Diagnostic[] = [{ category: ts.DiagnosticCategory.Error, messageText: e.stack, - source: api.SOURCE, - code: api.UNKNOWN_ERROR_CODE + file: undefined, + start: undefined, + length: undefined, + source: 'angular', + code: api.UNKNOWN_ERROR_CODE, }]; return {project: '', errors, rootNames: [], options: {}, emitFlags: api.EmitFlags.Default}; } diff --git a/packages/language-service/ivy/language_service_adapter.ts b/packages/language-service/ivy/adapters.ts similarity index 86% rename from packages/language-service/ivy/language_service_adapter.ts rename to packages/language-service/ivy/adapters.ts index 928c3b3e70..c95d326688 100644 --- a/packages/language-service/ivy/language_service_adapter.ts +++ b/packages/language-service/ivy/adapters.ts @@ -6,7 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {ParseConfigurationHost} from '@angular/compiler-cli'; +/** @fileoverview provides adapters for communicating with the ng compiler */ + +import {ConfigurationHost} from '@angular/compiler-cli'; import {NgCompilerAdapter} from '@angular/compiler-cli/src/ngtsc/core/api'; import {absoluteFrom, AbsoluteFsPath, FileStats, PathSegment, PathString} from '@angular/compiler-cli/src/ngtsc/file_system'; import {isShim} from '@angular/compiler-cli/src/ngtsc/shims'; @@ -88,14 +90,13 @@ export class LanguageServiceAdapter implements NgCompilerAdapter { * because signatures of calls like `FileSystem#readFile` are a bit stricter * than those on the adapter. */ -export class LSParseConfigHost implements ParseConfigurationHost { - private readonly host: ts.server.ServerHost = this.project.projectService.host; - constructor(private readonly project: ts.server.Project) {} +export class LSParseConfigHost implements ConfigurationHost { + constructor(private readonly serverHost: ts.server.ServerHost) {} exists(path: AbsoluteFsPath): boolean { - return this.project.fileExists(path) || this.project.directoryExists(path); + return this.serverHost.fileExists(path) || this.serverHost.directoryExists(path); } readFile(path: AbsoluteFsPath): string { - const content = this.project.readFile(path); + const content = this.serverHost.readFile(path); if (content === undefined) { throw new Error(`LanguageServiceFS#readFile called on unavailable file ${path}`); } @@ -104,10 +105,10 @@ export class LSParseConfigHost implements ParseConfigurationHost { lstat(path: AbsoluteFsPath): FileStats { return { isFile: () => { - return this.project.fileExists(path); + return this.serverHost.fileExists(path); }, isDirectory: () => { - return this.project.directoryExists(path); + return this.serverHost.directoryExists(path); }, isSymbolicLink: () => { throw new Error(`LanguageServiceFS#lstat#isSymbolicLink not implemented`); @@ -115,13 +116,13 @@ export class LSParseConfigHost implements ParseConfigurationHost { }; } pwd(): AbsoluteFsPath { - return this.project.getCurrentDirectory() as AbsoluteFsPath; + return this.serverHost.getCurrentDirectory() as AbsoluteFsPath; } extname(path: AbsoluteFsPath|PathSegment): string { return p.extname(path); } resolve(...paths: string[]): AbsoluteFsPath { - return this.host.resolvePath(this.join(paths[0], ...paths.slice(1))) as AbsoluteFsPath; + return this.serverHost.resolvePath(this.join(paths[0], ...paths.slice(1))) as AbsoluteFsPath; } dirname(file: T): T { return p.dirname(file) as T; diff --git a/packages/language-service/ivy/compiler_factory.ts b/packages/language-service/ivy/compiler_factory.ts index df0f26c243..af2498d16e 100644 --- a/packages/language-service/ivy/compiler_factory.ts +++ b/packages/language-service/ivy/compiler_factory.ts @@ -12,7 +12,7 @@ import {TrackedIncrementalBuildStrategy} from '@angular/compiler-cli/src/ngtsc/i import {TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; import * as ts from 'typescript/lib/tsserverlibrary'; -import {LanguageServiceAdapter} from './language_service_adapter'; +import {LanguageServiceAdapter} from './adapters'; import {isExternalTemplate} from './utils'; /** diff --git a/packages/language-service/ivy/language_service.ts b/packages/language-service/ivy/language_service.ts index db23b16588..b5d4f1d08a 100644 --- a/packages/language-service/ivy/language_service.ts +++ b/packages/language-service/ivy/language_service.ts @@ -6,15 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {CompilerOptions, formatDiagnostics, ParseConfigurationHost, readConfiguration} from '@angular/compiler-cli'; +import {CompilerOptions, ConfigurationHost, readConfiguration} from '@angular/compiler-cli'; import {absoluteFromSourceFile, AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/file_system'; import {TypeCheckShimGenerator} from '@angular/compiler-cli/src/ngtsc/typecheck'; import {OptimizeFor, TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; import * as ts from 'typescript/lib/tsserverlibrary'; +import {LanguageServiceAdapter, LSParseConfigHost} from './adapters'; import {CompilerFactory} from './compiler_factory'; import {DefinitionBuilder} from './definitions'; -import {LanguageServiceAdapter, LSParseConfigHost} from './language_service_adapter'; import {QuickInfoBuilder} from './quick_info'; import {getTargetAtPosition} from './template_target'; import {getTemplateInfoAtPosition, isTypeScriptFile} from './utils'; @@ -27,7 +27,7 @@ export class LanguageService { private readonly parseConfigHost: LSParseConfigHost; constructor(project: ts.server.Project, private readonly tsLS: ts.LanguageService) { - this.parseConfigHost = new LSParseConfigHost(project); + this.parseConfigHost = new LSParseConfigHost(project.projectService.host); this.options = parseNgCompilerOptions(project, this.parseConfigHost); this.strategy = createTypeCheckingProgramStrategy(project); this.adapter = new LanguageServiceAdapter(project); @@ -116,15 +116,15 @@ export class LanguageService { } } -export function parseNgCompilerOptions( - project: ts.server.Project, host: ParseConfigurationHost): CompilerOptions { +function parseNgCompilerOptions( + project: ts.server.Project, host: ConfigurationHost): CompilerOptions { if (!(project instanceof ts.server.ConfiguredProject)) { return {}; } const {options, errors} = readConfiguration(project.getConfigFilePath(), /* existingOptions */ undefined, host); if (errors.length > 0) { - project.error(formatDiagnostics(errors)); + project.setProjectErrors(errors); } return options; diff --git a/packages/language-service/ivy/test/legacy/language_service_adapter_spec.ts b/packages/language-service/ivy/test/legacy/language_service_adapter_spec.ts deleted file mode 100644 index 32d9f4e8be..0000000000 --- a/packages/language-service/ivy/test/legacy/language_service_adapter_spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import * as ts from 'typescript/lib/tsserverlibrary'; - -import {LanguageServiceAdapter} from '../../language_service_adapter'; - -import {MockService, setup, TEST_TEMPLATE} from './mock_host'; - -describe('Language service adapter', () => { - let project: ts.server.Project; - let service: MockService; - - beforeAll(() => { - const {project: _project, service: _service} = setup(); - project = _project; - service = _service; - }); - - it('should mark template dirty if it has not seen the template before', () => { - const adapter = new LanguageServiceAdapter(project); - expect(adapter.isTemplateDirty(TEST_TEMPLATE)).toBeTrue(); - }); - - it('should not mark template dirty if template has not changed', () => { - const adapter = new LanguageServiceAdapter(project); - adapter.readResource(TEST_TEMPLATE); - expect(adapter.isTemplateDirty(TEST_TEMPLATE)).toBeFalse(); - }); - - it('should mark template dirty if template has changed', () => { - const adapter = new LanguageServiceAdapter(project); - service.overwrite(TEST_TEMPLATE, '

Hello World

'); - expect(adapter.isTemplateDirty(TEST_TEMPLATE)).toBeTrue(); - }); -}); diff --git a/packages/language-service/ivy/utils.ts b/packages/language-service/ivy/utils.ts index 1c54df46a1..d76d4d6ea0 100644 --- a/packages/language-service/ivy/utils.ts +++ b/packages/language-service/ivy/utils.ts @@ -10,6 +10,7 @@ import {NgCompiler} from '@angular/compiler-cli/src/ngtsc/core'; import {isExternalResource} from '@angular/compiler-cli/src/ngtsc/metadata'; import {DeclarationNode} from '@angular/compiler-cli/src/ngtsc/reflection'; import {DirectiveSymbol} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; +import {Diagnostic as ngDiagnostic, isNgDiagnostic} from '@angular/compiler-cli/src/transformers/api'; import * as e from '@angular/compiler/src/expression_parser/ast'; // e for expression AST import * as t from '@angular/compiler/src/render3/r3_ast'; // t for template AST import * as ts from 'typescript';