From d744921f855a6c5d4f4df62895bc3b17b8e0e532 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 18 Dec 2013 16:55:15 +0100 Subject: SI-8064 Automatic position repair for macro expansion - Replace NoPosition with the focus of the macro application - Focus all range positions, for example, those of spliced arguments --- .../scala/tools/nsc/typechecker/Macros.scala | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'src/compiler/scala/tools/nsc') diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 006ab792fc..c32b986d9c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -760,7 +760,31 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { macroLogLite("" + expanded + "\n" + showRaw(expanded)) val freeSyms = expanded.freeTerms ++ expanded.freeTypes freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym)) - Success(atPos(enclosingMacroPosition.focus)(expanded)) + // Macros might have spliced arguments with range positions into non-compliant + // locations, notably, under a tree without a range position. Or, they might + // splice a tree that `resetAttrs` has assigned NoPosition. + // + // Here, we just convert all positions in the tree to offset positions, and + // convert NoPositions to something sensible. + // + // Given that the IDE now sees the expandee (by using -Ymacro-expand:discard), + // this loss of position fidelity shouldn't cause any real problems. + // + // Alternatively, we could pursue a way to exclude macro expansions from position + // invariant checking, or find a way not to touch expansions that happen to validate. + // + // This would be useful for cases like: + // + // macro1 { macro2 { "foo" } } + // + // to allow `macro1` to see the range position of the "foo". + val expandedPos = enclosingMacroPosition.focus + def fixPosition(pos: Position) = + if (pos == NoPosition) expandedPos else pos.focus + expanded.foreach(t => t.pos = fixPosition(t.pos)) + + val result = atPos(enclosingMacroPosition.focus)(expanded) + Success(result) } expanded match { case expanded: Expr[_] if expandee.symbol.isTermMacro => validateResultingTree(expanded.tree) -- cgit v1.2.3