refactor(language-service): pull out interfaces on package toplevel (#40621)

Two motivations behind this change:

1. We would like to expose the types of the Language Service to external
   users (like the VSCode extension) via the npm package, on the top
   level of the package
2. We would like the View Engine and Ivy LS to share a common interface
   (notably after the inclusion of `getTcb`, the Ivy LS upholds a
   strict superset of `ts.LanguageService`; previously both VE and Ivy
   LS were aligned on `ts.LanguageService`.)

To this end, this commit refactors the exports on the toplevel of the
`language-service/` package to just be types common to both the VE and
Ivy language services. The VE and Ivy build targets then import and use
these types accordingly, and the expectation is that an external user
will just import the relevant typings from the toplevel package without
diving into either the VE or Ivy sources.

Follow up on #40607

PR Close #40621
This commit is contained in:
ayazhafiz 2021-01-28 14:43:37 -06:00 committed by Misko Hevery
parent 6ad057d28c
commit 950875c1ba
11 changed files with 69 additions and 66 deletions

View File

@ -382,12 +382,6 @@
"packages/forms/src/directives/validators.ts",
"packages/forms/src/validators.ts"
],
[
"packages/language-service/src/completions.ts",
"packages/language-service/src/template.ts",
"packages/language-service/src/typescript_host.ts",
"packages/language-service/src/language_service.ts"
],
[
"packages/language-service/src/template.ts",
"packages/language-service/src/typescript_host.ts"

View File

@ -2,11 +2,20 @@ load("//tools:defaults.bzl", "pkg_npm", "ts_library")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "api",
srcs = [
"api.ts",
],
deps = [
"@npm//typescript",
],
)
ts_library(
name = "language-service",
srcs = glob(
srcs = ["index.ts"] + glob(
[
"*.ts",
"src/**/*.ts",
],
exclude = [
@ -14,6 +23,7 @@ ts_library(
],
),
deps = [
":api",
":ts_utils",
"//packages:types",
"//packages/compiler",

View File

@ -0,0 +1,42 @@
/**
* @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
*/
/**
* @module
* @description
* Entry point for all public APIs of the language service package.
*/
import * as ts from 'typescript';
export type GetTcbResponse = {
/**
* The filename of the SourceFile this typecheck block belongs to.
* The filename is entirely opaque and unstable, useful only for debugging
* purposes.
*/
fileName: string,
/** The content of the SourceFile this typecheck block belongs to. */
content: string,
/**
* Spans over node(s) in the typecheck block corresponding to the
* TS code generated for template node under the current cursor position.
*
* When the cursor position is over a source for which there is no generated
* code, `selections` is empty.
*/
selections: ts.TextSpan[],
}|undefined;
/**
* `NgLanguageService` describes an instance of an Angular language service,
* whose API surface is a strict superset of TypeScript's language service.
*/
export interface NgLanguageService extends ts.LanguageService {
getTcb(fileName: string, position: number): GetTcbResponse;
}

View File

@ -6,4 +6,5 @@
* found in the LICENSE file at https://angular.io/license
*/
export * from './language-service';
export * from './api';
export {create, getExternalFiles} from './src/ts_plugin';

View File

@ -20,6 +20,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/typecheck",
"//packages/compiler-cli/src/ngtsc/typecheck/api",
"//packages/compiler-cli/src/ngtsc/util",
"//packages/language-service:api",
"@npm//@types/node",
"@npm//typescript",
],

View File

@ -15,6 +15,7 @@ import {TypeCheckShimGenerator} from '@angular/compiler-cli/src/ngtsc/typecheck'
import {OptimizeFor, TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
import {findFirstMatchingNode} from '@angular/compiler-cli/src/ngtsc/typecheck/src/comments';
import * as ts from 'typescript/lib/tsserverlibrary';
import {GetTcbResponse} from '../api';
import {LanguageServiceAdapter, LSParseConfigHost} from './adapters';
import {CompilerFactory} from './compiler_factory';
@ -25,25 +26,6 @@ import {ReferencesAndRenameBuilder} from './references';
import {getTargetAtPosition, TargetContext, TargetNodeKind} from './template_target';
import {getTemplateInfoAtPosition, isTypeScriptFile} from './utils';
export type GetTcbResponse = {
/**
* The filename of the SourceFile this typecheck block belongs to.
* The filename is entirely opaque and unstable, useful only for debugging
* purposes.
*/
fileName: string,
/** The content of the SourceFile this typecheck block belongs to. */
content: string,
/**
* Spans over node(s) in the typecheck block corresponding to the
* TS code generated for template node under the current cursor position.
*
* When the cursor position is over a source for which there is no generated
* code, `selections` is empty.
*/
selections: ts.TextSpan[],
}|undefined;
export class LanguageService {
private options: CompilerOptions;
readonly compilerFactory: CompilerFactory;

View File

@ -7,11 +7,8 @@
*/
import * as ts from 'typescript/lib/tsserverlibrary';
import {GetTcbResponse, LanguageService} from './language_service';
export interface NgLanguageService extends ts.LanguageService {
getTcb(fileName: string, position: number): GetTcbResponse;
}
import {GetTcbResponse, NgLanguageService} from '../api';
import {LanguageService} from './language_service';
export function create(info: ts.server.PluginCreateInfo): NgLanguageService {
const {project, languageService: tsLS, config} = info;

View File

@ -1,19 +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
*/
/// <reference types="node" />
/**
* @module
* @description
* Entry point for all public APIs of the language service package.
*/
export {createLanguageService} from './src/language_service';
export * from './src/ts_plugin';
export {Declaration, Definition, Diagnostic, LanguageService, LanguageServiceHost, Span, TemplateSource} from './src/types';
export {TypeScriptServiceHost, createLanguageServiceFromTypescript} from './src/typescript_host';

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as path from 'path';
import * as tss from 'typescript/lib/tsserverlibrary';
import {getTemplateCompletions} from './completions';

View File

@ -7,6 +7,7 @@
*/
import * as tss from 'typescript/lib/tsserverlibrary';
import {NgLanguageService} from '../api';
import {createLanguageService} from './language_service';
import {TypeScriptServiceHost} from './typescript_host';
@ -41,7 +42,7 @@ export function getExternalFiles(project: tss.server.Project): string[] {
});
}
export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
export function create(info: tss.server.PluginCreateInfo): NgLanguageService {
const {languageService: tsLS, languageServiceHost: tsLSHost, config, project} = info;
// This plugin could operate under two different modes:
// 1. TS + Angular
@ -135,6 +136,11 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
return undefined;
}
function getTcb(fileName: string, position: number) {
// Not implemented in VE Language Service
return undefined;
}
return {
// First clone the original TS language service
...tsLS,
@ -147,5 +153,6 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
getTypeDefinitionAtPosition,
getReferencesAtPosition,
findRenameLocations,
getTcb,
};
}

View File

@ -11,21 +11,10 @@ import {SchemaMetadata, ViewEncapsulation, ɵConsole as Console} from '@angular/
import * as path from 'path';
import * as tss from 'typescript/lib/tsserverlibrary';
import {createLanguageService} from './language_service';
import {ReflectorHost} from './reflector_host';
import {ExternalTemplate, InlineTemplate} from './template';
import {findTightestNode, getClassDeclFromDecoratorProp, getDirectiveClassLike, getPropertyAssignmentFromValue} from './ts_utils';
import {AstResult, Declaration, DeclarationError, DiagnosticMessageChain, LanguageService, LanguageServiceHost, Span, TemplateSource} from './types';
/**
* Create a `LanguageServiceHost`
*/
export function createLanguageServiceFromTypescript(
host: tss.LanguageServiceHost, service: tss.LanguageService): LanguageService {
const ngHost = new TypeScriptServiceHost(host, service);
const ngServer = createLanguageService(ngHost);
return ngServer;
}
import {AstResult, Declaration, DeclarationError, DiagnosticMessageChain, LanguageServiceHost, Span, TemplateSource} from './types';
/**
* The language service never needs the normalized versions of the metadata. To avoid parsing