@angular/language-service 11.2.8 → 11.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundles/ivy.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v11.2.8
2
+ * @license Angular v11.2.9
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  * License: MIT
5
5
  */
@@ -20399,7 +20399,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
20399
20399
  * Use of this source code is governed by an MIT-style license that can be
20400
20400
  * found in the LICENSE file at https://angular.io/license
20401
20401
  */
20402
- const VERSION$1 = new Version('11.2.8');
20402
+ const VERSION$1 = new Version('11.2.9');
20403
20403
 
20404
20404
  /**
20405
20405
  * @license
@@ -21056,7 +21056,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21056
21056
  */
21057
21057
  function createDirectiveDefinitionMap(meta) {
21058
21058
  const definitionMap = new DefinitionMap();
21059
- definitionMap.set('version', literal('11.2.8'));
21059
+ definitionMap.set('version', literal('11.2.9'));
21060
21060
  // e.g. `type: MyDirective`
21061
21061
  definitionMap.set('type', meta.internalType);
21062
21062
  // e.g. `selector: 'some-dir'`
@@ -21277,7 +21277,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21277
21277
  */
21278
21278
  function createPipeDefinitionMap(meta) {
21279
21279
  const definitionMap = new DefinitionMap();
21280
- definitionMap.set('version', literal('11.2.8'));
21280
+ definitionMap.set('version', literal('11.2.9'));
21281
21281
  definitionMap.set('ngImport', importExpr(Identifiers$1.core));
21282
21282
  // e.g. `type: MyPipe`
21283
21283
  definitionMap.set('type', meta.internalType);
@@ -21309,7 +21309,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21309
21309
  * Use of this source code is governed by an MIT-style license that can be
21310
21310
  * found in the LICENSE file at https://angular.io/license
21311
21311
  */
21312
- const VERSION$2 = new Version('11.2.8');
21312
+ const VERSION$2 = new Version('11.2.9');
21313
21313
 
21314
21314
  /**
21315
21315
  * @license
@@ -25632,10 +25632,38 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
25632
25632
  * operation.
25633
25633
  */
25634
25634
  PerfPhase[PerfPhase["LsReferencesAndRenames"] = 16] = "LsReferencesAndRenames";
25635
+ /**
25636
+ * Time spent by the Angular Language Service calculating a "quick info" operation.
25637
+ */
25638
+ PerfPhase[PerfPhase["LsQuickInfo"] = 17] = "LsQuickInfo";
25639
+ /**
25640
+ * Time spent by the Angular Language Service calculating a "get type definition" or "get
25641
+ * definition" operation.
25642
+ */
25643
+ PerfPhase[PerfPhase["LsDefinition"] = 18] = "LsDefinition";
25644
+ /**
25645
+ * Time spent by the Angular Language Service calculating a "get completions" (AKA autocomplete)
25646
+ * operation.
25647
+ */
25648
+ PerfPhase[PerfPhase["LsCompletions"] = 19] = "LsCompletions";
25649
+ /**
25650
+ * Time spent by the Angular Language Service calculating a "view template typecheck block"
25651
+ * operation.
25652
+ */
25653
+ PerfPhase[PerfPhase["LsTcb"] = 20] = "LsTcb";
25654
+ /**
25655
+ * Time spent by the Angular Language Service calculating diagnostics.
25656
+ */
25657
+ PerfPhase[PerfPhase["LsDiagnostics"] = 21] = "LsDiagnostics";
25658
+ /**
25659
+ * Time spent by the Angular Language Service calculating a "get component locations for template"
25660
+ * operation.
25661
+ */
25662
+ PerfPhase[PerfPhase["LsComponentLocations"] = 22] = "LsComponentLocations";
25635
25663
  /**
25636
25664
  * Tracks the number of `PerfPhase`s, and must appear at the end of the list.
25637
25665
  */
25638
- PerfPhase[PerfPhase["LAST"] = 17] = "LAST";
25666
+ PerfPhase[PerfPhase["LAST"] = 23] = "LAST";
25639
25667
  })(PerfPhase || (PerfPhase = {}));
25640
25668
  /**
25641
25669
  * Represents some occurrence during compilation, and is tracked with a counter.
@@ -30267,9 +30295,16 @@ Either add the @Injectable() decorator to '${provider.node.name
30267
30295
  const meta = this._resolveLiteral(decorator);
30268
30296
  const component = reflectObjectLiteral(meta);
30269
30297
  const containingFile = node.getSourceFile().fileName;
30270
- const resolveStyleUrl = (styleUrl, nodeForError, resourceType) => {
30271
- const resourceUrl = this._resolveResourceOrThrow(styleUrl, containingFile, nodeForError, resourceType);
30272
- return this.resourceLoader.preload(resourceUrl);
30298
+ const resolveStyleUrl = (styleUrl) => {
30299
+ try {
30300
+ const resourceUrl = this.resourceLoader.resolve(styleUrl, containingFile);
30301
+ return this.resourceLoader.preload(resourceUrl);
30302
+ }
30303
+ catch (_a) {
30304
+ // Don't worry about failures to preload. We can handle this problem during analysis by
30305
+ // producing a diagnostic.
30306
+ return undefined;
30307
+ }
30273
30308
  };
30274
30309
  // A Promise that waits for the template and all <link>ed styles within it to be preloaded.
30275
30310
  const templateAndTemplateStyleResources = this._preloadAndParseTemplate(node, decorator, component, containingFile)
@@ -30277,9 +30312,7 @@ Either add the @Injectable() decorator to '${provider.node.name
30277
30312
  if (template === null) {
30278
30313
  return undefined;
30279
30314
  }
30280
- const nodeForError = getTemplateDeclarationNodeForError(template.declaration);
30281
- return Promise
30282
- .all(template.styleUrls.map(styleUrl => resolveStyleUrl(styleUrl, nodeForError, 1 /* StylesheetFromTemplate */)))
30315
+ return Promise.all(template.styleUrls.map(styleUrl => resolveStyleUrl(styleUrl)))
30283
30316
  .then(() => undefined);
30284
30317
  });
30285
30318
  // Extract all the styleUrls in the decorator.
@@ -30294,7 +30327,7 @@ Either add the @Injectable() decorator to '${provider.node.name
30294
30327
  return Promise
30295
30328
  .all([
30296
30329
  templateAndTemplateStyleResources,
30297
- ...componentStyleUrls.map(styleUrl => resolveStyleUrl(styleUrl.url, styleUrl.nodeForError, 2 /* StylesheetFromDecorator */))
30330
+ ...componentStyleUrls.map(styleUrl => resolveStyleUrl(styleUrl.url))
30298
30331
  ])
30299
30332
  .then(() => undefined);
30300
30333
  }
@@ -30304,6 +30337,8 @@ Either add the @Injectable() decorator to '${provider.node.name
30304
30337
  this.perf.eventCount(PerfEvent.AnalyzeComponent);
30305
30338
  const containingFile = node.getSourceFile().fileName;
30306
30339
  this.literalCache.delete(decorator);
30340
+ let diagnostics;
30341
+ let isPoisoned = false;
30307
30342
  // @Component inherits @Directive, so begin by extracting the @Directive metadata and building
30308
30343
  // on it.
30309
30344
  const directiveResult = extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.defaultImportRecorder, this.isCore, flags, this.annotateForClosureCompiler, this.elementSchemaRegistry.getDefaultComponentElementName());
@@ -30371,14 +30406,23 @@ Either add the @Injectable() decorator to '${provider.node.name
30371
30406
  ...this._extractComponentStyleUrls(component), ...this._extractTemplateStyleUrls(template)
30372
30407
  ];
30373
30408
  for (const styleUrl of styleUrls) {
30374
- const resourceType = styleUrl.source === 2 /* StylesheetFromDecorator */ ?
30375
- 2 /* StylesheetFromDecorator */ :
30376
- 1 /* StylesheetFromTemplate */;
30377
- const resourceUrl = this._resolveResourceOrThrow(styleUrl.url, containingFile, styleUrl.nodeForError, resourceType);
30378
- const resourceStr = this.resourceLoader.load(resourceUrl);
30379
- styles.push(resourceStr);
30380
- if (this.depTracker !== null) {
30381
- this.depTracker.addResourceDependency(node.getSourceFile(), absoluteFrom(resourceUrl));
30409
+ try {
30410
+ const resourceUrl = this.resourceLoader.resolve(styleUrl.url, containingFile);
30411
+ const resourceStr = this.resourceLoader.load(resourceUrl);
30412
+ styles.push(resourceStr);
30413
+ if (this.depTracker !== null) {
30414
+ this.depTracker.addResourceDependency(node.getSourceFile(), absoluteFrom(resourceUrl));
30415
+ }
30416
+ }
30417
+ catch (_b) {
30418
+ if (diagnostics === undefined) {
30419
+ diagnostics = [];
30420
+ }
30421
+ const resourceType = styleUrl.source === 2 /* StylesheetFromDecorator */ ?
30422
+ 2 /* StylesheetFromDecorator */ :
30423
+ 1 /* StylesheetFromTemplate */;
30424
+ diagnostics.push(this.makeResourceNotFoundError(styleUrl.url, styleUrl.nodeForError, resourceType)
30425
+ .toDiagnostic());
30382
30426
  }
30383
30427
  }
30384
30428
  let inlineStyles = null;
@@ -30421,8 +30465,9 @@ Either add the @Injectable() decorator to '${provider.node.name
30421
30465
  styles: styleResources,
30422
30466
  template: templateResource,
30423
30467
  },
30424
- isPoisoned: false,
30468
+ isPoisoned,
30425
30469
  },
30470
+ diagnostics,
30426
30471
  };
30427
30472
  if (changeDetection !== null) {
30428
30473
  output.analysis.meta.changeDetection = changeDetection;
@@ -30651,12 +30696,15 @@ Either add the @Injectable() decorator to '${provider.node.name
30651
30696
  let styles = [];
30652
30697
  if (analysis.styleUrls !== null) {
30653
30698
  for (const styleUrl of analysis.styleUrls) {
30654
- const resourceType = styleUrl.source === 2 /* StylesheetFromDecorator */ ?
30655
- 2 /* StylesheetFromDecorator */ :
30656
- 1 /* StylesheetFromTemplate */;
30657
- const resolvedStyleUrl = this._resolveResourceOrThrow(styleUrl.url, containingFile, styleUrl.nodeForError, resourceType);
30658
- const styleText = this.resourceLoader.load(resolvedStyleUrl);
30659
- styles.push(styleText);
30699
+ try {
30700
+ const resolvedStyleUrl = this.resourceLoader.resolve(styleUrl.url, containingFile);
30701
+ const styleText = this.resourceLoader.load(resolvedStyleUrl);
30702
+ styles.push(styleText);
30703
+ }
30704
+ catch (e) {
30705
+ // Resource resolve failures should already be in the diagnostics list from the analyze
30706
+ // stage. We do not need to do anything with them when updating resources.
30707
+ }
30660
30708
  }
30661
30709
  }
30662
30710
  if (analysis.inlineStyles !== null) {
@@ -30778,8 +30826,15 @@ Either add the @Injectable() decorator to '${provider.node.name
30778
30826
  const styleUrlsExpr = component.get('styleUrls');
30779
30827
  if (styleUrlsExpr !== undefined && ts$1.isArrayLiteralExpression(styleUrlsExpr)) {
30780
30828
  for (const expression of stringLiteralElements(styleUrlsExpr)) {
30781
- const resourceUrl = this._resolveResourceOrThrow(expression.text, containingFile, expression, 2 /* StylesheetFromDecorator */);
30782
- styles.add({ path: absoluteFrom(resourceUrl), expression });
30829
+ try {
30830
+ const resourceUrl = this.resourceLoader.resolve(expression.text, containingFile);
30831
+ styles.add({ path: absoluteFrom(resourceUrl), expression });
30832
+ }
30833
+ catch (_a) {
30834
+ // Errors in style resource extraction do not need to be handled here. We will produce
30835
+ // diagnostics for each one that fails in the analysis, after we evaluate the `styleUrls`
30836
+ // expression to determine _all_ style resources, not just the string literals.
30837
+ }
30783
30838
  }
30784
30839
  }
30785
30840
  const stylesExpr = component.get('styles');
@@ -30798,20 +30853,25 @@ Either add the @Injectable() decorator to '${provider.node.name
30798
30853
  if (typeof templateUrl !== 'string') {
30799
30854
  throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
30800
30855
  }
30801
- const resourceUrl = this._resolveResourceOrThrow(templateUrl, containingFile, templateUrlExpr, 0 /* Template */);
30802
- const templatePromise = this.resourceLoader.preload(resourceUrl);
30803
- // If the preload worked, then actually load and parse the template, and wait for any style
30804
- // URLs to resolve.
30805
- if (templatePromise !== undefined) {
30806
- return templatePromise.then(() => {
30807
- const templateDecl = this.parseTemplateDeclaration(decorator, component, containingFile);
30808
- const template = this.extractTemplate(node, templateDecl);
30809
- this.preanalyzeTemplateCache.set(node, template);
30810
- return template;
30811
- });
30856
+ try {
30857
+ const resourceUrl = this.resourceLoader.resolve(templateUrl, containingFile);
30858
+ const templatePromise = this.resourceLoader.preload(resourceUrl);
30859
+ // If the preload worked, then actually load and parse the template, and wait for any style
30860
+ // URLs to resolve.
30861
+ if (templatePromise !== undefined) {
30862
+ return templatePromise.then(() => {
30863
+ const templateDecl = this.parseTemplateDeclaration(decorator, component, containingFile);
30864
+ const template = this.extractTemplate(node, templateDecl);
30865
+ this.preanalyzeTemplateCache.set(node, template);
30866
+ return template;
30867
+ });
30868
+ }
30869
+ else {
30870
+ return Promise.resolve(null);
30871
+ }
30812
30872
  }
30813
- else {
30814
- return Promise.resolve(null);
30873
+ catch (e) {
30874
+ throw this.makeResourceNotFoundError(templateUrl, templateUrlExpr, 0 /* Template */);
30815
30875
  }
30816
30876
  }
30817
30877
  else {
@@ -30943,16 +31003,21 @@ Either add the @Injectable() decorator to '${provider.node.name
30943
31003
  if (typeof templateUrl !== 'string') {
30944
31004
  throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
30945
31005
  }
30946
- const resourceUrl = this._resolveResourceOrThrow(templateUrl, containingFile, templateUrlExpr, 0 /* Template */);
30947
- return {
30948
- isInline: false,
30949
- interpolationConfig,
30950
- preserveWhitespaces,
30951
- templateUrl,
30952
- templateUrlExpression: templateUrlExpr,
30953
- resolvedTemplateUrl: resourceUrl,
30954
- sourceMapUrl: sourceMapUrl(resourceUrl),
30955
- };
31006
+ try {
31007
+ const resourceUrl = this.resourceLoader.resolve(templateUrl, containingFile);
31008
+ return {
31009
+ isInline: false,
31010
+ interpolationConfig,
31011
+ preserveWhitespaces,
31012
+ templateUrl,
31013
+ templateUrlExpression: templateUrlExpr,
31014
+ resolvedTemplateUrl: resourceUrl,
31015
+ sourceMapUrl: sourceMapUrl(resourceUrl),
31016
+ };
31017
+ }
31018
+ catch (e) {
31019
+ throw this.makeResourceNotFoundError(templateUrl, templateUrlExpr, 0 /* Template */);
31020
+ }
30956
31021
  }
30957
31022
  else if (component.has('template')) {
30958
31023
  return {
@@ -31005,30 +31070,20 @@ Either add the @Injectable() decorator to '${provider.node.name
31005
31070
  }
31006
31071
  this.cycleAnalyzer.recordSyntheticImport(origin, imported);
31007
31072
  }
31008
- /**
31009
- * Resolve the url of a resource relative to the file that contains the reference to it.
31010
- *
31011
- * Throws a FatalDiagnosticError when unable to resolve the file.
31012
- */
31013
- _resolveResourceOrThrow(file, basePath, nodeForError, resourceType) {
31014
- try {
31015
- return this.resourceLoader.resolve(file, basePath);
31016
- }
31017
- catch (e) {
31018
- let errorText;
31019
- switch (resourceType) {
31020
- case 0 /* Template */:
31021
- errorText = `Could not find template file '${file}'.`;
31022
- break;
31023
- case 1 /* StylesheetFromTemplate */:
31024
- errorText = `Could not find stylesheet file '${file}' linked from the template.`;
31025
- break;
31026
- case 2 /* StylesheetFromDecorator */:
31027
- errorText = `Could not find stylesheet file '${file}'.`;
31028
- break;
31029
- }
31030
- throw new FatalDiagnosticError(ErrorCode.COMPONENT_RESOURCE_NOT_FOUND, nodeForError, errorText);
31073
+ makeResourceNotFoundError(file, nodeForError, resourceType) {
31074
+ let errorText;
31075
+ switch (resourceType) {
31076
+ case 0 /* Template */:
31077
+ errorText = `Could not find template file '${file}'.`;
31078
+ break;
31079
+ case 1 /* StylesheetFromTemplate */:
31080
+ errorText = `Could not find stylesheet file '${file}' linked from the template.`;
31081
+ break;
31082
+ case 2 /* StylesheetFromDecorator */:
31083
+ errorText = `Could not find stylesheet file '${file}'.`;
31084
+ break;
31031
31085
  }
31086
+ return new FatalDiagnosticError(ErrorCode.COMPONENT_RESOURCE_NOT_FOUND, nodeForError, errorText);
31032
31087
  }
31033
31088
  _extractTemplateStyleUrls(template) {
31034
31089
  if (template.styleUrls === null) {
@@ -40590,24 +40645,30 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
40590
40645
  };
40591
40646
  }
40592
40647
  function getExtendedConfigPath(configFile, extendsValue, host, fs) {
40593
- let extendedConfigPath = null;
40648
+ const result = getExtendedConfigPathWorker(configFile, extendsValue, host, fs);
40649
+ if (result !== null) {
40650
+ return result;
40651
+ }
40652
+ // Try to resolve the paths with a json extension append a json extension to the file in case if
40653
+ // it is missing and the resolution failed. This is to replicate TypeScript behaviour, see:
40654
+ // https://github.com/microsoft/TypeScript/blob/294a5a7d784a5a95a8048ee990400979a6bc3a1c/src/compiler/commandLineParser.ts#L2806
40655
+ return getExtendedConfigPathWorker(configFile, `${extendsValue}.json`, host, fs);
40656
+ }
40657
+ function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
40594
40658
  if (extendsValue.startsWith('.') || fs.isRooted(extendsValue)) {
40595
- extendedConfigPath = host.resolve(host.dirname(configFile), extendsValue);
40596
- extendedConfigPath = host.extname(extendedConfigPath) ?
40597
- extendedConfigPath :
40598
- absoluteFrom(`${extendedConfigPath}.json`);
40659
+ const extendedConfigPath = host.resolve(host.dirname(configFile), extendsValue);
40660
+ if (host.exists(extendedConfigPath)) {
40661
+ return extendedConfigPath;
40662
+ }
40599
40663
  }
40600
40664
  else {
40601
40665
  const parseConfigHost = createParseConfigHost(host, fs);
40602
40666
  // Path isn't a rooted or relative path, resolve like a module.
40603
40667
  const { resolvedModule, } = ts$1.nodeModuleNameResolver(extendsValue, configFile, { moduleResolution: ts$1.ModuleResolutionKind.NodeJs, resolveJsonModule: true }, parseConfigHost);
40604
40668
  if (resolvedModule) {
40605
- extendedConfigPath = absoluteFrom(resolvedModule.resolvedFileName);
40669
+ return absoluteFrom(resolvedModule.resolvedFileName);
40606
40670
  }
40607
40671
  }
40608
- if (extendedConfigPath !== null && host.exists(extendedConfigPath)) {
40609
- return extendedConfigPath;
40610
- }
40611
40672
  return null;
40612
40673
  }
40613
40674
 
@@ -43501,49 +43562,52 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43501
43562
  return this.options;
43502
43563
  }
43503
43564
  getSemanticDiagnostics(fileName) {
43504
- const compiler = this.compilerFactory.getOrCreate();
43505
- const ttc = compiler.getTemplateTypeChecker();
43506
- const diagnostics = [];
43507
- if (isTypeScriptFile(fileName)) {
43508
- const program = compiler.getNextProgram();
43509
- const sourceFile = program.getSourceFile(fileName);
43510
- if (sourceFile) {
43511
- const ngDiagnostics = compiler.getDiagnosticsForFile(sourceFile, OptimizeFor.SingleFile);
43512
- // There are several kinds of diagnostics returned by `NgCompiler` for a source file:
43513
- //
43514
- // 1. Angular-related non-template diagnostics from decorated classes within that file.
43515
- // 2. Template diagnostics for components with direct inline templates (a string literal).
43516
- // 3. Template diagnostics for components with indirect inline templates (templates computed
43517
- // by expression).
43518
- // 4. Template diagnostics for components with external templates.
43519
- //
43520
- // When showing diagnostics for a TS source file, we want to only include kinds 1 and 2 -
43521
- // those diagnostics which are reported at a location within the TS file itself. Diagnostics
43522
- // for external templates will be shown when editing that template file (the `else` block)
43523
- // below.
43524
- //
43525
- // Currently, indirect inline template diagnostics (kind 3) are not shown at all by the
43526
- // Language Service, because there is no sensible location in the user's code for them. Such
43527
- // templates are an edge case, though, and should not be common.
43528
- //
43529
- // TODO(alxhub): figure out a good user experience for indirect template diagnostics and
43530
- // show them from within the Language Service.
43531
- diagnostics.push(...ngDiagnostics.filter(diag => diag.file !== undefined && diag.file.fileName === sourceFile.fileName));
43565
+ return this.withCompilerAndPerfTracing(PerfPhase.LsDiagnostics, (compiler) => {
43566
+ const ttc = compiler.getTemplateTypeChecker();
43567
+ const diagnostics = [];
43568
+ if (isTypeScriptFile(fileName)) {
43569
+ const program = compiler.getNextProgram();
43570
+ const sourceFile = program.getSourceFile(fileName);
43571
+ if (sourceFile) {
43572
+ const ngDiagnostics = compiler.getDiagnosticsForFile(sourceFile, OptimizeFor.SingleFile);
43573
+ // There are several kinds of diagnostics returned by `NgCompiler` for a source file:
43574
+ //
43575
+ // 1. Angular-related non-template diagnostics from decorated classes within that
43576
+ // file.
43577
+ // 2. Template diagnostics for components with direct inline templates (a string
43578
+ // literal).
43579
+ // 3. Template diagnostics for components with indirect inline templates (templates
43580
+ // computed
43581
+ // by expression).
43582
+ // 4. Template diagnostics for components with external templates.
43583
+ //
43584
+ // When showing diagnostics for a TS source file, we want to only include kinds 1 and
43585
+ // 2 - those diagnostics which are reported at a location within the TS file itself.
43586
+ // Diagnostics for external templates will be shown when editing that template file
43587
+ // (the `else` block) below.
43588
+ //
43589
+ // Currently, indirect inline template diagnostics (kind 3) are not shown at all by
43590
+ // the Language Service, because there is no sensible location in the user's code for
43591
+ // them. Such templates are an edge case, though, and should not be common.
43592
+ //
43593
+ // TODO(alxhub): figure out a good user experience for indirect template diagnostics
43594
+ // and show them from within the Language Service.
43595
+ diagnostics.push(...ngDiagnostics.filter(diag => diag.file !== undefined && diag.file.fileName === sourceFile.fileName));
43596
+ }
43532
43597
  }
43533
- }
43534
- else {
43535
- const components = compiler.getComponentsWithTemplateFile(fileName);
43536
- for (const component of components) {
43537
- if (ts.isClassDeclaration(component)) {
43538
- diagnostics.push(...ttc.getDiagnosticsForComponent(component));
43598
+ else {
43599
+ const components = compiler.getComponentsWithTemplateFile(fileName);
43600
+ for (const component of components) {
43601
+ if (ts.isClassDeclaration(component)) {
43602
+ diagnostics.push(...ttc.getDiagnosticsForComponent(component));
43603
+ }
43539
43604
  }
43540
43605
  }
43541
- }
43542
- this.compilerFactory.registerLastKnownProgram();
43543
- return diagnostics;
43606
+ return diagnostics;
43607
+ });
43544
43608
  }
43545
43609
  getDefinitionAndBoundSpan(fileName, position) {
43546
- return this.withCompiler((compiler) => {
43610
+ return this.withCompilerAndPerfTracing(PerfPhase.LsDefinition, (compiler) => {
43547
43611
  if (!isInAngularContext(compiler.getNextProgram(), fileName, position)) {
43548
43612
  return undefined;
43549
43613
  }
@@ -43552,7 +43616,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43552
43616
  });
43553
43617
  }
43554
43618
  getTypeDefinitionAtPosition(fileName, position) {
43555
- return this.withCompiler((compiler) => {
43619
+ return this.withCompilerAndPerfTracing(PerfPhase.LsDefinition, (compiler) => {
43556
43620
  if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43557
43621
  return undefined;
43558
43622
  }
@@ -43561,56 +43625,57 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43561
43625
  });
43562
43626
  }
43563
43627
  getQuickInfoAtPosition(fileName, position) {
43564
- return this.withCompiler((compiler) => {
43565
- if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43566
- return undefined;
43567
- }
43568
- const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
43569
- if (templateInfo === undefined) {
43570
- return undefined;
43571
- }
43572
- const positionDetails = getTargetAtPosition(templateInfo.template, position);
43573
- if (positionDetails === null) {
43574
- return undefined;
43575
- }
43576
- // Because we can only show 1 quick info, just use the bound attribute if the target is a two
43577
- // way binding. We may consider concatenating additional display parts from the other target
43578
- // nodes or representing the two way binding in some other manner in the future.
43579
- const node = positionDetails.context.kind === TargetNodeKind.TwoWayBindingContext ?
43580
- positionDetails.context.nodes[0] :
43581
- positionDetails.context.node;
43582
- return new QuickInfoBuilder(this.tsLS, compiler, templateInfo.component, node).get();
43628
+ return this.withCompilerAndPerfTracing(PerfPhase.LsQuickInfo, (compiler) => {
43629
+ return this.getQuickInfoAtPositionImpl(fileName, position, compiler);
43583
43630
  });
43584
43631
  }
43632
+ getQuickInfoAtPositionImpl(fileName, position, compiler) {
43633
+ if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43634
+ return undefined;
43635
+ }
43636
+ const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
43637
+ if (templateInfo === undefined) {
43638
+ return undefined;
43639
+ }
43640
+ const positionDetails = getTargetAtPosition(templateInfo.template, position);
43641
+ if (positionDetails === null) {
43642
+ return undefined;
43643
+ }
43644
+ // Because we can only show 1 quick info, just use the bound attribute if the target is a two
43645
+ // way binding. We may consider concatenating additional display parts from the other target
43646
+ // nodes or representing the two way binding in some other manner in the future.
43647
+ const node = positionDetails.context.kind === TargetNodeKind.TwoWayBindingContext ?
43648
+ positionDetails.context.nodes[0] :
43649
+ positionDetails.context.node;
43650
+ return new QuickInfoBuilder(this.tsLS, compiler, templateInfo.component, node).get();
43651
+ }
43585
43652
  getReferencesAtPosition(fileName, position) {
43586
- const compiler = this.compilerFactory.getOrCreate();
43587
- const results = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43588
- .getReferencesAtPosition(fileName, position);
43589
- this.compilerFactory.registerLastKnownProgram();
43590
- return results;
43653
+ return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
43654
+ return new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43655
+ .getReferencesAtPosition(fileName, position);
43656
+ });
43591
43657
  }
43592
43658
  getRenameInfo(fileName, position) {
43593
- var _a, _b, _c;
43594
- const compiler = this.compilerFactory.getOrCreate();
43595
- const renameInfo = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43596
- .getRenameInfo(absoluteFrom(fileName), position);
43597
- if (!renameInfo.canRename) {
43598
- return renameInfo;
43599
- }
43600
- const quickInfo = (_a = this.getQuickInfoAtPosition(fileName, position)) !== null && _a !== void 0 ? _a : this.tsLS.getQuickInfoAtPosition(fileName, position);
43601
- const kind = (_b = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kind) !== null && _b !== void 0 ? _b : ts.ScriptElementKind.unknown;
43602
- const kindModifiers = (_c = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kindModifiers) !== null && _c !== void 0 ? _c : ts.ScriptElementKind.unknown;
43603
- return Object.assign(Object.assign({}, renameInfo), { kind, kindModifiers });
43659
+ return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
43660
+ var _a, _b, _c;
43661
+ const renameInfo = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43662
+ .getRenameInfo(absoluteFrom(fileName), position);
43663
+ if (!renameInfo.canRename) {
43664
+ return renameInfo;
43665
+ }
43666
+ const quickInfo = (_a = this.getQuickInfoAtPositionImpl(fileName, position, compiler)) !== null && _a !== void 0 ? _a : this.tsLS.getQuickInfoAtPosition(fileName, position);
43667
+ const kind = (_b = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kind) !== null && _b !== void 0 ? _b : ts.ScriptElementKind.unknown;
43668
+ const kindModifiers = (_c = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kindModifiers) !== null && _c !== void 0 ? _c : ts.ScriptElementKind.unknown;
43669
+ return Object.assign(Object.assign({}, renameInfo), { kind, kindModifiers });
43670
+ });
43604
43671
  }
43605
43672
  findRenameLocations(fileName, position) {
43606
- const compiler = this.compilerFactory.getOrCreate();
43607
- const results = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43608
- .findRenameLocations(fileName, position);
43609
- this.compilerFactory.registerLastKnownProgram();
43610
- return results;
43673
+ return this.withCompilerAndPerfTracing(PerfPhase.LsReferencesAndRenames, (compiler) => {
43674
+ return new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
43675
+ .findRenameLocations(fileName, position);
43676
+ });
43611
43677
  }
43612
- getCompletionBuilder(fileName, position) {
43613
- const compiler = this.compilerFactory.getOrCreate();
43678
+ getCompletionBuilder(fileName, position, compiler) {
43614
43679
  const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
43615
43680
  if (templateInfo === undefined) {
43616
43681
  return null;
@@ -43627,23 +43692,26 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43627
43692
  return new CompletionBuilder(this.tsLS, compiler, templateInfo.component, node, positionDetails, isTypeScriptFile(fileName));
43628
43693
  }
43629
43694
  getCompletionsAtPosition(fileName, position, options) {
43630
- return this.withCompiler((compiler) => {
43631
- if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43632
- return undefined;
43633
- }
43634
- const builder = this.getCompletionBuilder(fileName, position);
43635
- if (builder === null) {
43636
- return undefined;
43637
- }
43638
- return builder.getCompletionsAtPosition(options);
43695
+ return this.withCompilerAndPerfTracing(PerfPhase.LsCompletions, (compiler) => {
43696
+ return this.getCompletionsAtPositionImpl(fileName, position, options, compiler);
43639
43697
  });
43640
43698
  }
43699
+ getCompletionsAtPositionImpl(fileName, position, options, compiler) {
43700
+ if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43701
+ return undefined;
43702
+ }
43703
+ const builder = this.getCompletionBuilder(fileName, position, compiler);
43704
+ if (builder === null) {
43705
+ return undefined;
43706
+ }
43707
+ return builder.getCompletionsAtPosition(options);
43708
+ }
43641
43709
  getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences) {
43642
- return this.withCompiler((compiler) => {
43710
+ return this.withCompilerAndPerfTracing(PerfPhase.LsCompletions, (compiler) => {
43643
43711
  if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43644
43712
  return undefined;
43645
43713
  }
43646
- const builder = this.getCompletionBuilder(fileName, position);
43714
+ const builder = this.getCompletionBuilder(fileName, position, compiler);
43647
43715
  if (builder === null) {
43648
43716
  return undefined;
43649
43717
  }
@@ -43651,11 +43719,11 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43651
43719
  });
43652
43720
  }
43653
43721
  getCompletionEntrySymbol(fileName, position, entryName) {
43654
- return this.withCompiler((compiler) => {
43722
+ return this.withCompilerAndPerfTracing(PerfPhase.LsCompletions, (compiler) => {
43655
43723
  if (!isTemplateContext(compiler.getNextProgram(), fileName, position)) {
43656
43724
  return undefined;
43657
43725
  }
43658
- const builder = this.getCompletionBuilder(fileName, position);
43726
+ const builder = this.getCompletionBuilder(fileName, position, compiler);
43659
43727
  if (builder === null) {
43660
43728
  return undefined;
43661
43729
  }
@@ -43665,7 +43733,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43665
43733
  });
43666
43734
  }
43667
43735
  getTcb(fileName, position) {
43668
- return this.withCompiler(compiler => {
43736
+ return this.withCompilerAndPerfTracing(PerfPhase.LsTcb, compiler => {
43669
43737
  const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
43670
43738
  if (templateInfo === undefined) {
43671
43739
  return undefined;
@@ -43705,10 +43773,31 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43705
43773
  };
43706
43774
  });
43707
43775
  }
43708
- withCompiler(p) {
43776
+ /**
43777
+ * Provides an instance of the `NgCompiler` and traces perf results. Perf results are logged only
43778
+ * if the log level is verbose or higher. This method is intended to be called once per public
43779
+ * method call.
43780
+ *
43781
+ * Here is an example of the log output.
43782
+ *
43783
+ * Perf 245 [16:16:39.353] LanguageService#getQuickInfoAtPosition(): {"events":{},"phases":{
43784
+ * "Unaccounted":379,"TtcSymbol":4},"memory":{}}
43785
+ *
43786
+ * Passing name of caller instead of using `arguments.caller` because 'caller', 'callee', and
43787
+ * 'arguments' properties may not be accessed in strict mode.
43788
+ *
43789
+ * @param phase the `PerfPhase` to execute the `p` callback in
43790
+ * @param p callback to be run synchronously with an instance of the `NgCompiler` as argument
43791
+ * @return the result of running the `p` callback
43792
+ */
43793
+ withCompilerAndPerfTracing(phase, p) {
43709
43794
  const compiler = this.compilerFactory.getOrCreate();
43710
- const result = p(compiler);
43795
+ const result = compiler.perfRecorder.inPhase(phase, () => p(compiler));
43711
43796
  this.compilerFactory.registerLastKnownProgram();
43797
+ const logger = this.project.projectService.logger;
43798
+ if (logger.hasLevel(ts.server.LogLevel.verbose)) {
43799
+ logger.perftrc(`LanguageService#${PerfPhase[phase]}: ${JSON.stringify(compiler.perfRecorder.finalize())}`);
43800
+ }
43712
43801
  return result;
43713
43802
  }
43714
43803
  getCompilerOptionsDiagnostics() {
@@ -43716,22 +43805,23 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43716
43805
  if (!(project instanceof ts.server.ConfiguredProject)) {
43717
43806
  return [];
43718
43807
  }
43719
- const diagnostics = [];
43720
- const configSourceFile = ts.readJsonConfigFile(project.getConfigFilePath(), (path) => project.readFile(path));
43721
- if (!this.options.strictTemplates && !this.options.fullTemplateTypeCheck) {
43722
- diagnostics.push({
43723
- messageText: 'Some language features are not available. ' +
43724
- 'To access all features, enable `strictTemplates` in `angularCompilerOptions`.',
43725
- category: ts.DiagnosticCategory.Suggestion,
43726
- code: ngErrorCode(ErrorCode.SUGGEST_STRICT_TEMPLATES),
43727
- file: configSourceFile,
43728
- start: undefined,
43729
- length: undefined,
43730
- });
43731
- }
43732
- const compiler = this.compilerFactory.getOrCreate();
43733
- diagnostics.push(...compiler.getOptionDiagnostics());
43734
- return diagnostics;
43808
+ return this.withCompilerAndPerfTracing(PerfPhase.LsDiagnostics, (compiler) => {
43809
+ const diagnostics = [];
43810
+ const configSourceFile = ts.readJsonConfigFile(project.getConfigFilePath(), (path) => project.readFile(path));
43811
+ if (!this.options.strictTemplates && !this.options.fullTemplateTypeCheck) {
43812
+ diagnostics.push({
43813
+ messageText: 'Some language features are not available. ' +
43814
+ 'To access all features, enable `strictTemplates` in `angularCompilerOptions`.',
43815
+ category: ts.DiagnosticCategory.Suggestion,
43816
+ code: ngErrorCode(ErrorCode.SUGGEST_STRICT_TEMPLATES),
43817
+ file: configSourceFile,
43818
+ start: undefined,
43819
+ length: undefined,
43820
+ });
43821
+ }
43822
+ diagnostics.push(...compiler.getOptionDiagnostics());
43823
+ return diagnostics;
43824
+ });
43735
43825
  }
43736
43826
  watchConfigFile(project) {
43737
43827
  // TODO: Check the case when the project is disposed. An InferredProject