diff --git a/packages/core/__tests__/cli/check.test.ts b/packages/core/__tests__/cli/check.test.ts index ece8ac78e..4e2b2b69f 100644 --- a/packages/core/__tests__/cli/check.test.ts +++ b/packages/core/__tests__/cli/check.test.ts @@ -200,9 +200,8 @@ describe('CLI: single-pass typechecking', () => { let checkResult = await project.check({ reject: false }); - expect(checkResult.exitCode).toBe(1); - expect(checkResult.stdout).toEqual(''); - expect(stripAnsi(checkResult.stderr)).toMatchInlineSnapshot(` + expect(checkResult.exitCode).not.toBe(0); + expect(stripAnsi(checkResult.stdout)).toMatchInlineSnapshot(` "my-component.hbs:1:22 - error TS2551: Property 'targett' does not exist on type 'MyComponent'. Did you mean 'target'? 1 {{@message}}, {{this.targett}} diff --git a/packages/core/__tests__/language-server/completions.test.ts b/packages/core/__tests__/language-server/completions.test.ts index bc45b39ad..e7e321402 100644 --- a/packages/core/__tests__/language-server/completions.test.ts +++ b/packages/core/__tests__/language-server/completions.test.ts @@ -19,16 +19,14 @@ describe('Language Server: Completions', () => { project.write('index.hbs', ''); let server = await project.startLanguageServer(); - let completions = server.getCompletions(project.fileURI('index.hbs'), { - line: 0, - character: 6, - }); + const { uri } = await server.openTextDocument(project.filePath('index.hbs'), 'handlebars'); + let completions = await server.sendCompletionRequest(uri, Position.create(0, 6)); - let completion = completions?.find((item) => item.label === 'LinkTo'); + let completion = completions?.items.find((item) => item.label === 'LinkTo'); expect(completion?.kind).toEqual(CompletionItemKind.Field); - let details = server.getCompletionDetails(completion!); + let details = await server.sendCompletionResolveRequest(completion!); expect(details.detail).toEqual('(property) Globals.LinkTo: LinkToComponent'); }); @@ -65,10 +63,8 @@ describe('Language Server: Completions', () => { project.write('index.hbs', code); let server = await project.startLanguageServer(); - let completions = server.getCompletions(project.fileURI('index.hbs'), { - line: 0, - character: 4, - }); + const { uri } = await server.openTextDocument(project.filePath('index.hbs'), 'handlebars'); + let completions = await server.sendCompletionRequest(uri, Position.create(0, 4)); // Ensure we don't spew all ~900 completions available at the top level // in module scope in a JS/TS file. diff --git a/packages/core/__tests__/language-server/diagnostic-augmentation.test.ts b/packages/core/__tests__/language-server/diagnostic-augmentation.test.ts index 8ae1cb791..2d2529f8c 100644 --- a/packages/core/__tests__/language-server/diagnostic-augmentation.test.ts +++ b/packages/core/__tests__/language-server/diagnostic-augmentation.test.ts @@ -940,7 +940,8 @@ describe('Language Server: Diagnostic Augmentation', () => { }); let server = await project.startLanguageServer(); - let diagnostics = server.getDiagnostics(project.fileURI('index.hbs')); + const { uri } = await server.openTextDocument(project.filePath('index.hbs'), 'handlebars'); + let diagnostics = await server.sendDocumentDiagnosticRequest(uri); expect(diagnostics.items.reverse()).toMatchInlineSnapshot(` [ diff --git a/packages/core/src/cli/run-volar-tsc.ts b/packages/core/src/cli/run-volar-tsc.ts index 9a78f43c7..79698182a 100644 --- a/packages/core/src/cli/run-volar-tsc.ts +++ b/packages/core/src/cli/run-volar-tsc.ts @@ -1,5 +1,5 @@ import { runTsc } from '@volar/typescript/lib/quickstart/runTsc.js'; -import { createGtsLanguagePlugin } from '../volar/gts-language-plugin.js'; +import { createEmberLanguagePlugin } from '../volar/ember-language-plugin.js'; import { findConfig } from '../config/index.js'; import { createRequire } from 'node:module'; @@ -29,7 +29,7 @@ export function run(): void { // not sure whether it's better to be lenient, but we were getting test failures // on environment-ember-loose's `yarn run test`. if (glintConfig) { - const gtsLanguagePlugin = createGtsLanguagePlugin(glintConfig); + const gtsLanguagePlugin = createEmberLanguagePlugin(glintConfig); return [gtsLanguagePlugin]; } else { return []; diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index bc98fa028..c3545102a 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -13,8 +13,6 @@ export class GlintConfig { public readonly environment: GlintEnvironment; public readonly checkStandaloneTemplates: boolean; - private extensions: Array; - public constructor( ts: typeof import('typescript'), configPath: string, @@ -25,32 +23,6 @@ export class GlintConfig { this.rootDir = path.dirname(configPath); this.environment = GlintEnvironment.load(config.environment, { rootDir: this.rootDir }); this.checkStandaloneTemplates = config.checkStandaloneTemplates ?? true; - this.extensions = this.environment.getConfiguredFileExtensions(); - } - - /** - * Indicates whether this configuration object applies to the file at the - * given path. - */ - public includesFile(rawFileName: string): boolean { - return this.extensions.some((ext) => rawFileName.endsWith(ext)); - } - - // Given the path of a template or script (potentially with a custom extension), - // returns the corresponding .js or .ts path we present to the TS language service. - public getSynthesizedScriptPathForTS(filename: string): string { - let extension = path.extname(filename); - let filenameWithoutExtension = filename.slice(0, filename.lastIndexOf(extension)); - switch (this.environment.getSourceKind(filename)) { - case 'template': - return `${filenameWithoutExtension}${this.checkStandaloneTemplates ? '.ts' : '.js'}`; - case 'typed-script': - return `${filenameWithoutExtension}.ts`; - case 'untyped-script': - return `${filenameWithoutExtension}.js`; - default: - return filename; - } } } diff --git a/packages/core/src/transform/diagnostics/augmentation.ts b/packages/core/src/transform/diagnostics/augmentation.ts index 327e405c6..42cf878cb 100644 --- a/packages/core/src/transform/diagnostics/augmentation.ts +++ b/packages/core/src/transform/diagnostics/augmentation.ts @@ -1,6 +1,6 @@ import type ts from 'typescript'; import { Diagnostic } from './index.js'; -import MappingTree, { MappingSource } from '../template/mapping-tree.js'; +import GlimmerASTMappingTree, { MappingSource } from '../template/glimmer-ast-mapping-tree.js'; /** * Given a diagnostic and a mapping tree node corresponding to its location, @@ -9,17 +9,20 @@ import MappingTree, { MappingSource } from '../template/mapping-tree.js'; */ export function augmentDiagnostic( diagnostic: T, - mappingForDiagnostic: (diagnostic: T) => MappingTree | null, + mappingForDiagnostic: (diagnostic: T) => GlimmerASTMappingTree | null, ): T { // TODO: fix any types, remove casting return rewriteMessageText(diagnostic, mappingForDiagnostic as any) as T; } -type DiagnosticHandler = (diagnostic: Diagnostic, mapping: MappingTree) => Diagnostic | undefined; +type DiagnosticHandler = ( + diagnostic: Diagnostic, + mapping: GlimmerASTMappingTree, +) => Diagnostic | undefined; function rewriteMessageText( diagnostic: Diagnostic, - mappingGetter: (diagnostic: Diagnostic) => MappingTree | null, + mappingGetter: (diagnostic: Diagnostic) => GlimmerASTMappingTree | null, ): Diagnostic { const handler = diagnosticHandlers[diagnostic.code?.toString() ?? '']; if (!handler) { @@ -48,7 +51,7 @@ const bindHelpers = ['component', 'helper', 'modifier']; function checkAssignabilityError( diagnostic: Diagnostic, - mapping: MappingTree, + mapping: GlimmerASTMappingTree, ): Diagnostic | undefined { let node = mapping.sourceNode; let parentNode = mapping.parent?.sourceNode; @@ -123,7 +126,7 @@ function checkAssignabilityError( function noteNamedArgsAffectArity( diagnostic: Diagnostic, - mapping: MappingTree, + mapping: GlimmerASTMappingTree, ): Diagnostic | undefined { // In normal template entity invocations, named args (if specified) are effectively // passed as the final positional argument. Because of this, the reported "expected @@ -153,7 +156,10 @@ function noteNamedArgsAffectArity( } } -function checkResolveError(diagnostic: Diagnostic, mapping: MappingTree): Diagnostic | undefined { +function checkResolveError( + diagnostic: Diagnostic, + mapping: GlimmerASTMappingTree, +): Diagnostic | undefined { // The diagnostic might fall on a lone identifier or a full path; if the former, // we need to traverse up through the path to find the true parent. let sourceMapping = mapping.sourceNode.type === 'Identifier' ? mapping.parent : mapping; @@ -199,7 +205,7 @@ function checkResolveError(diagnostic: Diagnostic, mapping: MappingTree): Diagno function checkImplicitAnyError( diagnostic: Diagnostic, - mapping: MappingTree, + mapping: GlimmerASTMappingTree, ): Diagnostic | undefined { let message = diagnostic.message; @@ -229,7 +235,7 @@ function checkImplicitAnyError( function checkIndexAccessError( diagnostic: Diagnostic, - mapping: MappingTree, + mapping: GlimmerASTMappingTree, ): Diagnostic | undefined { if (mapping.sourceNode.type === 'Identifier') { let message = diagnostic.message; @@ -252,10 +258,10 @@ function addGlintDetails(diagnostic: Diagnostic, details: string): Diagnostic { // Find the nearest mapping node at or above the given one whose `source` AST node // matches one of the given types. function findAncestor( - mapping: MappingTree, + mapping: GlimmerASTMappingTree, ...types: Array ): Extract | null { - let current: MappingTree | null = mapping; + let current: GlimmerASTMappingTree | null = mapping; do { if (types.includes(current.sourceNode.type as K)) { return current.sourceNode as Extract; diff --git a/packages/core/src/transform/template/mapping-tree.ts b/packages/core/src/transform/template/glimmer-ast-mapping-tree.ts similarity index 93% rename from packages/core/src/transform/template/mapping-tree.ts rename to packages/core/src/transform/template/glimmer-ast-mapping-tree.ts index 57f41f6a4..ba3f0f025 100644 --- a/packages/core/src/transform/template/mapping-tree.ts +++ b/packages/core/src/transform/template/glimmer-ast-mapping-tree.ts @@ -48,13 +48,13 @@ export class TemplateEmbedding { * level of granularity as TS itself uses when reporting on the transformed * output. */ -export default class MappingTree { - public parent: MappingTree | null = null; +export default class GlimmerASTMappingTree { + public parent: GlimmerASTMappingTree | null = null; public constructor( public transformedRange: Range, public originalRange: Range, - public children: Array = [], + public children: Array = [], public sourceNode: MappingSource, ) { children.forEach((child) => (child.parent = this)); @@ -65,7 +65,7 @@ export default class MappingTree { * that contains the given range, or `null` if that range doesn't fall within * this mapping tree. */ - public narrowestMappingForTransformedRange(range: Range): MappingTree | null { + public narrowestMappingForTransformedRange(range: Range): GlimmerASTMappingTree | null { if (range.start < this.transformedRange.start || range.end > this.transformedRange.end) { return null; } @@ -85,7 +85,7 @@ export default class MappingTree { * that contains the given range, or `null` if that range doesn't fall within * this mapping tree. */ - public narrowestMappingForOriginalRange(range: Range): MappingTree | null { + public narrowestMappingForOriginalRange(range: Range): GlimmerASTMappingTree | null { if (range.start < this.originalRange.start || range.end > this.originalRange.end) { return null; } diff --git a/packages/core/src/transform/template/inlining/companion-file.ts b/packages/core/src/transform/template/inlining/companion-file.ts index 4417b84e1..3ea14bcef 100644 --- a/packages/core/src/transform/template/inlining/companion-file.ts +++ b/packages/core/src/transform/template/inlining/companion-file.ts @@ -3,7 +3,7 @@ import type ts from 'typescript'; import { GlintEnvironment } from '../../../config/index.js'; import { CorrelatedSpansResult, isEmbeddedInClass, PartialCorrelatedSpan } from './index.js'; import { RewriteResult } from '../map-template-contents.js'; -import MappingTree, { ParseError } from '../mapping-tree.js'; +import GlimmerASTMappingTree, { ParseError } from '../glimmer-ast-mapping-tree.js'; import { templateToTypescript } from '../template-to-typescript.js'; import { Directive, SourceFile, TransformError } from '../transformed-module.js'; import { TSLib } from '../../util.js'; @@ -113,7 +113,7 @@ export function calculateCompanionTemplateSpans( originalLength: template.contents.length, insertionPoint: options.insertionPoint, transformedSource: transformedTemplate.result.code, - mapping: transformedTemplate.result.mapping, + glimmerAstMapping: transformedTemplate.result.mapping, }, { originalFile: template, @@ -124,7 +124,7 @@ export function calculateCompanionTemplateSpans( }, ); } else { - let mapping = new MappingTree( + let mapping = new GlimmerASTMappingTree( { start: 0, end: 0 }, { start: 0, end: template.contents.length }, [], @@ -137,12 +137,19 @@ export function calculateCompanionTemplateSpans( originalLength: template.contents.length, insertionPoint: options.insertionPoint, transformedSource: '', - mapping, + glimmerAstMapping: mapping, }); } } } +/** + * Find and return the TS AST node which can serve as a proper insertion point + * for the transformed template code, which is: + * + * - The default export class declaration + * - a named export that matches a class declaration + */ function findCompanionTemplateTarget( ts: TSLib, sourceFile: ts.SourceFile, @@ -155,6 +162,7 @@ function findCompanionTemplateTarget( mods?.some((mod) => mod.kind === ts.SyntaxKind.DefaultKeyword) && mods.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword) ) { + // We've found a `export default class` statement; return it. return statement; } @@ -164,6 +172,8 @@ function findCompanionTemplateTarget( } } + // We didn't find a default export, but maybe there is a named export that + // matches one of the class statements we found above. for (let statement of sourceFile.statements) { if (ts.isExportAssignment(statement) && !statement.isExportEquals) { if (ts.isIdentifier(statement.expression) && statement.expression.text in classes) { diff --git a/packages/core/src/transform/template/inlining/tagged-strings.ts b/packages/core/src/transform/template/inlining/tagged-strings.ts index 128834837..f4ead45c2 100644 --- a/packages/core/src/transform/template/inlining/tagged-strings.ts +++ b/packages/core/src/transform/template/inlining/tagged-strings.ts @@ -106,7 +106,7 @@ export function calculateTaggedTemplateSpans( originalLength: templateLocation.end - templateLocation.start, insertionPoint: templateLocation.start, transformedSource: transformedTemplate.result.code, - mapping: transformedTemplate.result.mapping, + glimmerAstMapping: transformedTemplate.result.mapping, }); } } diff --git a/packages/core/src/transform/template/map-template-contents.ts b/packages/core/src/transform/template/map-template-contents.ts index 10aebdb85..546a6703f 100644 --- a/packages/core/src/transform/template/map-template-contents.ts +++ b/packages/core/src/transform/template/map-template-contents.ts @@ -1,5 +1,8 @@ import { AST, preprocess } from '@glimmer/syntax'; -import MappingTree, { MappingSource, TemplateEmbedding } from './mapping-tree.js'; +import GlimmerASTMappingTree, { + MappingSource, + TemplateEmbedding, +} from './glimmer-ast-mapping-tree.js'; import { Directive, DirectiveKind, Range } from './transformed-module.js'; import { assert } from '../util.js'; @@ -101,7 +104,7 @@ export type RewriteResult = { result?: { code: string; directives: Array; - mapping: MappingTree; + mapping: GlimmerASTMappingTree; }; }; @@ -121,7 +124,8 @@ export type MapTemplateContentsOptions = { }; /** - * Given the text of an embedded template, invokes the given callback + * Given the text of a handlebars template (either standalone .hbs file, or the contents + * of an embedded `` within a .gts file), invokes the given callback * with a set of tools to emit mapped contents corresponding to * that template, tracking the text emitted in order to provide * a mapping of ranges in the input to ranges in the output. @@ -162,7 +166,7 @@ export function mapTemplateContents( }); let segmentsStack: string[][] = [[]]; - let mappingsStack: MappingTree[][] = [[]]; + let mappingsStack: GlimmerASTMappingTree[][] = [[]]; let indent = ''; let offset = 0; let needsIndent = false; @@ -180,7 +184,7 @@ export function mapTemplateContents( callback: () => void, ): void => { let start = offset; - let mappings: MappingTree[] = []; + let mappings: GlimmerASTMappingTree[] = []; let segments: string[] = []; segmentsStack.unshift(segments); @@ -201,7 +205,7 @@ export function mapTemplateContents( let end = offset; let tsRange = { start, end }; - mappingsStack[0].push(new MappingTree(tsRange, hbsRange, mappings, source)); + mappingsStack[0].push(new GlimmerASTMappingTree(tsRange, hbsRange, mappings, source)); segmentsStack[0].push(...segments); } }; @@ -270,7 +274,7 @@ export function mapTemplateContents( assert(segmentsStack.length === 1); let code = segmentsStack[0].join(''); - let mapping = new MappingTree( + let mapping = new GlimmerASTMappingTree( { start: 0, end: code.length }, { start: 0, diff --git a/packages/core/src/transform/template/rewrite-module.ts b/packages/core/src/transform/template/rewrite-module.ts index b3488083f..bd9f8b149 100644 --- a/packages/core/src/transform/template/rewrite-module.ts +++ b/packages/core/src/transform/template/rewrite-module.ts @@ -54,7 +54,7 @@ export function rewriteModule( /** * Locates any embedded templates in the given AST and returns a corresponding - * `PartialReplacedSpan` for each, as well as any errors encountered. These + * `PartialCorrelatedSpan` for each, as well as any errors encountered. These * spans are then used in `rewriteModule` above to calculate the full set of * source-to-source location information as well as the final transformed source * string. @@ -106,6 +106,12 @@ function calculateCorrelatedSpans( ts.transform(ast, [ (context) => function visit(node: T): T { + // Here we look for ```hbs``` tagged template expressions, originally introduced + // in the now-removed GlimmerX environment. We can consider getting rid of this, but + // then again there are still some use cases in the wild (e.g. Glimmer Next / GXT) + // where have tagged templates closing over outer scope is desirable: + // https://github.com/lifeart/glimmer-next/tree/master/glint-environment-gxt + // https://discord.com/channels/480462759797063690/717767358743183412/1259061848632721480 if (ts.isTaggedTemplateExpression(node)) { let meta = emitMetadata.get(node); let result = calculateTaggedTemplateSpans(ts, node, meta, script, environment); @@ -302,27 +308,27 @@ function calculateTransformedSource( /** * Given an array of `PartialCorrelatedSpan`s for a file, calculates * their `transformedLength` and `transformedStart` values, resulting - * in full `ReplacedSpan`s. + * in full `CorrelatedSpan`s. */ function completeCorrelatedSpans( partialSpans: Array, ): Array { - let replacedSpans: Array = []; + let correlatedSpans: Array = []; for (let i = 0; i < partialSpans.length; i++) { let current = partialSpans[i]; let transformedLength = current.transformedSource.length; let transformedStart = current.insertionPoint; if (i > 0) { - let previous = replacedSpans[i - 1]; + let previous = correlatedSpans[i - 1]; transformedStart = previous.transformedStart + previous.transformedSource.length + (current.insertionPoint - previous.insertionPoint - previous.originalLength); } - replacedSpans.push({ ...current, transformedStart, transformedLength }); + correlatedSpans.push({ ...current, transformedStart, transformedLength }); } - return replacedSpans; + return correlatedSpans; } diff --git a/packages/core/src/transform/template/template-to-typescript.ts b/packages/core/src/transform/template/template-to-typescript.ts index 00b8712d9..6d5a2df20 100644 --- a/packages/core/src/transform/template/template-to-typescript.ts +++ b/packages/core/src/transform/template/template-to-typescript.ts @@ -3,7 +3,7 @@ import { unreachable, assert } from '../util.js'; import { EmbeddingSyntax, mapTemplateContents, RewriteResult } from './map-template-contents.js'; import ScopeStack from './scope-stack.js'; import { GlintEmitMetadata, GlintSpecialForm } from '@glint/core/config-types'; -import { TextContent } from './mapping-tree.js'; +import { TextContent } from './glimmer-ast-mapping-tree.js'; const SPLATTRIBUTES = '...attributes'; diff --git a/packages/core/src/transform/template/transformed-module.ts b/packages/core/src/transform/template/transformed-module.ts index fed8b3361..263809c54 100644 --- a/packages/core/src/transform/template/transformed-module.ts +++ b/packages/core/src/transform/template/transformed-module.ts @@ -1,10 +1,11 @@ -import MappingTree from './mapping-tree.js'; +import GlimmerASTMappingTree from './glimmer-ast-mapping-tree.js'; import { assert } from '../util.js'; import { CodeMapping } from '@volar/language-core'; export type Range = { start: number; end: number }; -export type RangeWithMapping = Range & { mapping?: MappingTree }; +export type RangeWithMapping = Range & { mapping?: GlimmerASTMappingTree }; export type RangeWithMappingAndSource = RangeWithMapping & { source: SourceFile }; + export type CorrelatedSpan = { /** Where this span of content originated */ originalFile: SourceFile; @@ -20,8 +21,8 @@ export type CorrelatedSpan = { transformedStart: number; /** The length of this span in the transformed output */ transformedLength: number; - /** A mapping of offsets within this span between its original and transformed versions */ - mapping?: MappingTree; + /** (Glimmer/Handlebars spans only:) A mapping of offsets within this span between its original and transformed versions */ + glimmerAstMapping?: GlimmerASTMappingTree; }; export type DirectiveKind = 'ignore' | 'expect-error'; @@ -50,6 +51,8 @@ export type SourceFile = { * both the original and transformed source text of the module, as * well any errors encountered during transformation. * + * It is used heavily for bidirectional source mapping between the original TS/HBS code + * and the singular transformed TS output (aka the Intermediate Representation). * It can be queried with an offset or range in either the * original or transformed source to determine the corresponding * offset or range in the other. @@ -64,7 +67,7 @@ export default class TransformedModule { public toDebugString(): string { let mappingStrings = this.correlatedSpans.map((span) => - span.mapping?.toDebugString({ + span.glimmerAstMapping?.toDebugString({ originalStart: span.originalStart, originalSource: span.originalFile.contents.slice( span.originalStart, @@ -105,7 +108,7 @@ export default class TransformedModule { if (startInfo.correlatedSpan === endInfo.correlatedSpan) { let { correlatedSpan } = startInfo; - let mapping = correlatedSpan.mapping?.narrowestMappingForTransformedRange({ + let mapping = correlatedSpan.glimmerAstMapping?.narrowestMappingForTransformedRange({ start: start - correlatedSpan.originalStart, end: end - correlatedSpan.originalStart, }); @@ -133,7 +136,7 @@ export default class TransformedModule { if (startInfo.correlatedSpan && startInfo.correlatedSpan === endInfo.correlatedSpan) { let { correlatedSpan } = startInfo; - let mapping = correlatedSpan.mapping?.narrowestMappingForOriginalRange({ + let mapping = correlatedSpan.glimmerAstMapping?.narrowestMappingForOriginalRange({ start: start - correlatedSpan.transformedStart, end: end - correlatedSpan.transformedStart, }); @@ -157,14 +160,14 @@ export default class TransformedModule { originalOffset, ); - if (!correlatedSpan.mapping) { + if (!correlatedSpan.glimmerAstMapping) { return null; } - let templateMapping = correlatedSpan.mapping?.children[0]; + let templateMapping = correlatedSpan.glimmerAstMapping?.children[0]; assert( - correlatedSpan.mapping?.sourceNode.type === 'TemplateEmbedding' && + correlatedSpan.glimmerAstMapping?.sourceNode.type === 'TemplateEmbedding' && templateMapping?.sourceNode.type === 'Template', 'Internal error: unexpected mapping structure.' + ` (${templateMapping?.sourceNode.type})`, ); @@ -234,7 +237,7 @@ export default class TransformedModule { * - to * - `[[ZEROLEN-A]]χ.emitContent(χ.resolveOrReturn([[expectsAtLeastOneArg]])());[[ZEROLEN-B]]` */ - public toVolarMappings(): CodeMapping[] { + public toVolarMappings(filenameFilter?: string): CodeMapping[] { const sourceOffsets: number[] = []; const generatedOffsets: number[] = []; const lengths: number[] = []; @@ -263,7 +266,7 @@ export default class TransformedModule { lengths.push(length); }; - let recurse = (span: CorrelatedSpan, mapping: MappingTree): void => { + let recurse = (span: CorrelatedSpan, mapping: GlimmerASTMappingTree): void => { const children = mapping.children; let { originalRange, transformedRange } = mapping; let hbsStart = span.originalStart + originalRange.start; @@ -298,12 +301,17 @@ export default class TransformedModule { }; this.correlatedSpans.forEach((span) => { - if (span.mapping) { - // this span is transformation from embedded