fix(language-service): respect baseUrl compiler option

Fixes #15974
This commit is contained in:
Chuck Jazdzewski 2017-04-13 16:19:59 -07:00 committed by Tobias Bosch
parent 38a7e0d1c7
commit f21ff904c2
3 changed files with 43 additions and 4 deletions

View File

@ -7,6 +7,7 @@
*/
import {AotSummaryResolver, CompileDirectiveMetadata, CompileMetadataResolver, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, InterpolationConfig, NgAnalyzedModules, NgModuleResolver, ParseTreeResult, Parser, PipeResolver, ResourceLoader, StaticAndDynamicReflectionCapabilities, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, SummaryResolver, UrlResolver, analyzeNgModules, componentModuleUrl, createOfflineCompileUrlResolver, extractProgramSymbols} from '@angular/compiler';
import {AngularCompilerOptions} from '@angular/compiler-cli';
import {Type, ViewEncapsulation, ɵConsole as Console} from '@angular/core';
import * as fs from 'fs';
import * as path from 'path';
@ -17,6 +18,7 @@ import {ReflectorHost} from './reflector_host';
import {BuiltinType, CompletionKind, Declaration, DeclarationError, Declarations, Definition, LanguageService, LanguageServiceHost, PipeInfo, Pipes, Signature, Span, Symbol, SymbolDeclaration, SymbolQuery, SymbolTable, TemplateSource, TemplateSources} from './types';
// In TypeScript 2.1 these flags moved
// These helpers work for both 2.0 and 2.1.
const isPrivate = (ts as any).ModifierFlags ?
@ -386,9 +388,13 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
const tsConfigPath = findTsConfig(source.fileName);
const basePath = path.dirname(tsConfigPath || this.context);
result = this._reflectorHost = new ReflectorHost(
() => this.tsService.getProgram(), this.host, {basePath, genDir: basePath});
const options: AngularCompilerOptions = {basePath, genDir: basePath};
const compilerOptions = this.host.getCompilationSettings();
if (compilerOptions && compilerOptions.baseUrl) {
options.baseUrl = compilerOptions.baseUrl;
}
result = this._reflectorHost =
new ReflectorHost(() => this.tsService.getProgram(), this.host, options);
}
return result;
}

View File

@ -281,6 +281,35 @@ describe('diagnostics', () => {
fileName => expectOnlyModuleDiagnostics(ngService.getDiagnostics(fileName)));
});
it('should be able to resolve modules using baseUrl', () => {
const app_component = `
import { Component } from '@angular/core';
import { NgForm } from '@angular/common';
import { Server } from 'app/server';
@Component({
selector: 'example-app',
template: '...',
providers: [Server]
})
export class AppComponent {
onSubmit(form: NgForm) {}
}
`;
const app_server = `
export class Server {}
`;
const fileName = '/app/app.component.ts';
mockHost.override(fileName, app_component);
mockHost.addScript('/other/files/app/server.ts', app_server);
mockHost.overrideOptions(options => {
options.baseUrl = '/other/files';
return options;
});
const diagnostic = ngService.getDiagnostics(fileName);
expect(diagnostic).toEqual([]);
});
function addCode(code: string, cb: (fileName: string, content?: string) => void) {
const fileName = '/app/app.component.ts';
const originalContent = mockHost.getFileContent(fileName);

View File

@ -69,6 +69,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
private overrides = new Map<string, string>();
private projectVersion = 0;
private options: ts.CompilerOptions;
private overrideDirectory = new Set<string>();
constructor(private scriptNames: string[], private data: MockData) {
const moduleFilename = module.filename.replace(/\\/g, '/');
@ -97,6 +98,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
}
if (content) {
this.overrides.set(fileName, content);
this.overrideDirectory.add(path.dirname(fileName));
} else {
this.overrides.delete(fileName);
}
@ -105,13 +107,14 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
addScript(fileName: string, content: string) {
this.projectVersion++;
this.overrides.set(fileName, content);
this.overrideDirectory.add(path.dirname(fileName));
this.scriptNames.push(fileName);
}
forgetAngular() { this.angularPath = undefined; }
overrideOptions(cb: (options: ts.CompilerOptions) => ts.CompilerOptions) {
this.options = cb(this.options);
this.options = cb((Object as any).assign({}, this.options));
this.projectVersion++;
}
@ -136,6 +139,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; }
directoryExists(directoryName: string): boolean {
if (this.overrideDirectory.has(directoryName)) return true;
let effectiveName = this.getEffectiveName(directoryName);
if (effectiveName === directoryName)
return directoryExists(directoryName, this.data);