From ff5b050a927b854fd19dd52e5757835c4c724bbb Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Thu, 28 Sep 2017 10:53:04 -0700 Subject: [PATCH] fix(compiler): correctly map error message locations (#19424) --- .../compiler/src/output/abstract_emitter.ts | 2 +- .../compiler/test/output/ts_emitter_spec.ts | 43 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/compiler/src/output/abstract_emitter.ts b/packages/compiler/src/output/abstract_emitter.ts index b8e96b8e9b..ea2d01da30 100644 --- a/packages/compiler/src/output/abstract_emitter.ts +++ b/packages/compiler/src/output/abstract_emitter.ts @@ -161,7 +161,7 @@ export class EmitterVisitorContext { spanOf(line: number, column: number): ParseSourceSpan|null { const emittedLine = this._lines[line - this._preambleLineCount]; if (emittedLine) { - let columnsLeft = column - emittedLine.indent; + let columnsLeft = column - _createIndent(emittedLine.indent).length; for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) { const part = emittedLine.parts[partIndex]; if (part.length > columnsLeft) { diff --git a/packages/compiler/test/output/ts_emitter_spec.ts b/packages/compiler/test/output/ts_emitter_spec.ts index b472ac6c12..7efaa2fa4c 100644 --- a/packages/compiler/test/output/ts_emitter_spec.ts +++ b/packages/compiler/test/output/ts_emitter_spec.ts @@ -9,7 +9,7 @@ import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol'; import * as o from '@angular/compiler/src/output/output_ast'; import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter'; - +import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '@angular/compiler/src/parse_util'; import {stripSourceMapAndNewLine} from './abstract_emitter_spec'; const someGenFilePath = 'somePackage/someGenFile'; @@ -420,5 +420,46 @@ export function main() { '/* SomePreamble */', 'a;' ].join('\n')); }); + + describe('emitter context', () => { + it('should be able to back to the generating span', () => { + const file = new ParseSourceFile('some content', 'a.ts'); + const returnSpan = new ParseSourceSpan( + new ParseLocation(file, 100, 10, 10), new ParseLocation(file, 200, 20, 10)); + const referenceSpan = new ParseSourceSpan( + new ParseLocation(file, 150, 15, 10), new ParseLocation(file, 175, 17, 10)); + const statements = [new o.ClassStmt( + 'SomeClass', null, [], [], new o.ClassMethod(null, [], []), + [new o.ClassMethod('someMethod', [new o.FnParam('a', o.INT_TYPE)], [ + o.variable('someVar', o.INT_TYPE).set(o.literal(0)).toDeclStmt(), + new o.ReturnStatement(o.variable('someVar', null, referenceSpan), returnSpan) + ])])]; + const {sourceText, context} = + emitter.emitStatementsAndContext('a.ts', 'a.ts', statements, '/* some preamble /*\n\n'); + const spanOf = (text: string, after: number = 0) => { + const location = sourceText.indexOf(text, after); + const {line, col} = calculateLineCol(sourceText, location); + return context.spanOf(line, col); + }; + const returnLoc = sourceText.indexOf('return'); + expect(spanOf('return someVar')).toEqual(returnSpan, 'return span calculated incorrectly'); + expect(spanOf(';', returnLoc)).toEqual(returnSpan, 'reference span calculated incorrectly'); + expect(spanOf('someVar', returnLoc)) + .toEqual(referenceSpan, 'return span calculated incorrectly'); + }); + }); }); } + +function calculateLineCol(text: string, offset: number): {line: number, col: number} { + const lines = text.split('\n'); + let line = 0; + for (let cur = 0; cur < text.length; line++) { + const next = cur + lines[line].length + 1; + if (next > offset) { + return {line, col: offset - cur}; + } + cur = next; + } + return {line, col: 0}; +} \ No newline at end of file