Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit829988b

Browse files
ayazhafizmhevery
authored andcommitted
fix(language-service): do not treat file URIs as general URLs (#39917)
In the past, the legacy (VE-based) language service would use a`UrlResolver` instance to resolve file paths, primarily for compilerresources like external templates. The problem with this is that theUrlResolver is designed to resolve URLs in general, and so for a pathlike `/a/b/#c`, `#c` is treated as hash/fragment rather than as partof the path, which can lead to unexpected path resolution (f.x.,`resolve('a/b/#c/d.ts', './d.html')` would produce `'a/b/d.html'` ratherthan the expected `'a/b/#c/d.html'`).This commit resolves the issue by using Node's `path` module to resolvefile paths directly, which aligns more with how resources are resolvedin the Ivy compiler.The testing story here is not great, and the API for validating a filepath could be a little bit prettier/robust. However, since the VE-basedlanguage service is going into more of a "maintenance mode" now thatthere is a clear path for the Ivy-based LS moving forward, I think it isokay not to spend too much time here.Closesangular/vscode-ng-language-service#892Closesangular/vscode-ng-language-service#1001PRClose#39917
1 parent35309bb commit829988b

File tree

7 files changed

+50
-12
lines changed

7 files changed

+50
-12
lines changed

‎packages/language-service/src/typescript_host.ts‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import{analyzeNgModules,AotSummaryResolver,CompileDirectiveSummary,CompileMetadataResolver,CompileNgModuleMetadata,CompilePipeSummary,CompilerConfig,createOfflineCompileUrlResolver,DirectiveNormalizer,DirectiveResolver,DomElementSchemaRegistry,FormattedError,FormattedMessageChain,HtmlParser,isFormattedError,JitSummaryResolver,Lexer,NgAnalyzedModules,NgModuleResolver,Parser,ParseTreeResult,PipeResolver,ResourceLoader,StaticReflector,StaticSymbol,StaticSymbolCache,StaticSymbolResolver,TemplateParser}from'@angular/compiler';
9+
import{analyzeNgModules,AotSummaryResolver,CompileDirectiveSummary,CompileMetadataResolver,CompileNgModuleMetadata,CompilePipeSummary,CompilerConfig,DirectiveNormalizer,DirectiveResolver,DomElementSchemaRegistry,FormattedError,FormattedMessageChain,HtmlParser,isFormattedError,JitSummaryResolver,Lexer,NgAnalyzedModules,NgModuleResolver,Parser,ParseTreeResult,PipeResolver,ResourceLoader,StaticReflector,StaticSymbol,StaticSymbolCache,StaticSymbolResolver,TemplateParser,UrlResolver}from'@angular/compiler';
1010
import{SchemaMetadata,ViewEncapsulation,ɵConsoleasConsole}from'@angular/core';
11+
import*aspathfrom'path';
1112
import*astssfrom'typescript/lib/tsserverlibrary';
1213

1314
import{createLanguageService}from'./language_service';
@@ -64,6 +65,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
6465
privatereadonlyfileToComponent=newMap<string,StaticSymbol>();
6566
privatereadonlycollectedErrors=newMap<string,any[]>();
6667
privatereadonlyfileVersions=newMap<string,string>();
68+
privatereadonlyurlResolver:UrlResolver;
6769

6870
privatelastProgram:tss.Program|undefined=undefined;
6971
privateanalyzedModules:NgAnalyzedModules={
@@ -93,6 +95,16 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
9395
this.staticSymbolResolver=newStaticSymbolResolver(
9496
this.reflectorHost,this.staticSymbolCache,this.summaryResolver,
9597
(e,filePath)=>this.collectError(e,filePath));
98+
this.urlResolver={
99+
resolve:(baseUrl:string,url:string)=>{
100+
// In practice, `directoryExists` is always defined.
101+
// https://github.com/microsoft/TypeScript/blob/0b6c9254a850dd07056259d4eefca7721745af75/src/server/project.ts#L1608-L1614
102+
if(tsLsHost.directoryExists!(baseUrl)){
103+
returnpath.resolve(baseUrl,url);
104+
}
105+
returnpath.resolve(path.dirname(baseUrl),url);
106+
}
107+
};
96108
}
97109

98110
// The resolver is instantiated lazily and should not be accessed directly.
@@ -125,7 +137,6 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
125137
constpipeResolver=newPipeResolver(staticReflector);
126138
constelementSchemaRegistry=newDomElementSchemaRegistry();
127139
constresourceLoader=newDummyResourceLoader();
128-
consturlResolver=createOfflineCompileUrlResolver();
129140
consthtmlParser=newDummyHtmlParser();
130141
// This tracks the CompileConfig in codegen.ts. Currently these options
131142
// are hard-coded.
@@ -134,7 +145,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
134145
useJit:false,
135146
});
136147
constdirectiveNormalizer=
137-
newDirectiveNormalizer(resourceLoader,urlResolver,htmlParser,config);
148+
newDirectiveNormalizer(resourceLoader,this.urlResolver,htmlParser,config);
138149
this._resolver=newCompileMetadataResolver(
139150
config,htmlParser,moduleResolver,directiveResolver,pipeResolver,
140151
newJitSummaryResolver(),elementSchemaRegistry,directiveNormalizer,newConsole(),
@@ -192,12 +203,11 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
192203
}
193204

194205
// update template references and fileToComponent
195-
consturlResolver=createOfflineCompileUrlResolver();
196206
for(constngModuleofthis.analyzedModules.ngModules){
197207
for(constdirectiveofngModule.declaredDirectives){
198208
const{metadata}=this.resolver.getNonNormalizedDirectiveMetadata(directive.reference)!;
199209
if(metadata.isComponent&&metadata.template&&metadata.template.templateUrl){
200-
consttemplateName=urlResolver.resolve(
210+
consttemplateName=this.urlResolver.resolve(
201211
this.reflector.componentModuleUrl(directive.reference),
202212
metadata.template.templateUrl);
203213
this.fileToComponent.set(templateName,directive.reference);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
*@license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import{Component}from'@angular/core';
10+
11+
@Component({
12+
selector:'inner',
13+
templateUrl:'./inner.html',
14+
})
15+
exportclassInnerComponent{
16+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<div>Hello</div>

‎packages/language-service/test/project/app/main.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
import{CommonModule}from'@angular/common';
1010
import{NgModule}from'@angular/core';
1111
import{FormsModule}from'@angular/forms';
12+
import{InnerComponent}from'./#inner/component';
1213
import{AppComponent}from'./app.component';
1314
import*asParsingCasesfrom'./parsing-cases';
1415

1516
@NgModule({
1617
imports:[CommonModule,FormsModule],
1718
declarations:[
1819
AppComponent,
20+
InnerComponent,
1921
ParsingCases.CounterDirective,
2022
ParsingCases.HintModel,
2123
ParsingCases.NumberModel,

‎packages/language-service/test/test_utils.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function loadTourOfHeroes(): ReadonlyMap<string, string> {
6969
constvalue=fs.readFileSync(absPath,'utf8');
7070
files.set(key,value);
7171
}else{
72-
constkey=path.join('/',filePath);
72+
constkey=path.join('/',path.relative(root,absPath));
7373
files.set(key,'[[directory]]');
7474
dirs.push(absPath);
7575
}
@@ -189,7 +189,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
189189
if(this.overrideDirectory.has(directoryName))returntrue;
190190
consteffectiveName=this.getEffectiveName(directoryName);
191191
if(effectiveName===directoryName){
192-
returnTOH.has(directoryName);
192+
returnTOH.get(directoryName)==='[[directory]]';
193193
}
194194
if(effectiveName==='/'+this.node_modules){
195195
returntrue;

‎packages/language-service/test/ts_plugin_spec.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ describe('plugin', () => {
5858
constcompilerDiags=tsLS.getCompilerOptionsDiagnostics();
5959
expect(compilerDiags).toEqual([]);
6060
constsourceFiles=program.getSourceFiles().filter(f=>!f.fileName.endsWith('.d.ts'));
61-
// there arethree .ts files in the test project
62-
expect(sourceFiles.length).toBe(3);
61+
// there arefour .ts files in the test project
62+
expect(sourceFiles.length).toBe(4);
6363
for(const{fileName}ofsourceFiles){
6464
constsyntacticDiags=tsLS.getSyntacticDiagnostics(fileName);
6565
expect(syntacticDiags).toEqual([]);
@@ -133,9 +133,10 @@ describe('plugin', () => {
133133

134134
it('should return external templates when getExternalFiles() is called',()=>{
135135
constexternalTemplates=getExternalFiles(mockProject);
136-
expect(externalTemplates).toEqual([
136+
expect(newSet(externalTemplates)).toEqual(newSet([
137137
'/app/test.ng',
138-
]);
138+
'/app/#inner/inner.html',
139+
]));
139140
});
140141

141142
it('should not return external template that does not exist',()=>{

‎packages/language-service/test/typescript_host_spec.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import*asngcfrom'@angular/compiler';
109
import*astsfrom'typescript';
1110

1211
import{TypeScriptServiceHost}from'../src/typescript_host';
@@ -109,6 +108,15 @@ describe('TypeScriptServiceHost', () => {
109108
expect(template.source).toContain('<h2>{{hero.name}} details!</h2>');
110109
});
111110

111+
// https://github.com/angular/vscode-ng-language-service/issues/892
112+
it('should resolve external templates with `#` in the path',()=>{
113+
consttsLSHost=newMockTypescriptHost(['/app/main.ts']);
114+
consttsLS=ts.createLanguageService(tsLSHost);
115+
constngLSHost=newTypeScriptServiceHost(tsLSHost,tsLS);
116+
ngLSHost.getAnalyzedModules();
117+
expect(ngLSHost.getExternalTemplates()).toContain('/app/#inner/inner.html');
118+
});
119+
112120
// https://github.com/angular/angular/issues/32301
113121
it('should clear caches when program changes',()=>{
114122
consttsLSHost=newMockTypescriptHost(['/app/main.ts']);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp