From c8265f18af998633d9cb870b256fb791d380960d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 26 Jun 2019 13:34:12 +0200 Subject: [PATCH 1/2] Fix span of simple enum cases The span should start with the enum case itself, not the preceding `case` keyword. This matters is there are many cases in a list. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index b507c2ed14fb..4f84ab34e52c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -895,7 +895,7 @@ object desugar { pats map { case id: Ident => expandSimpleEnumCase(id.name.asTermName, mods, - Span(pdef.span.start, id.span.end, id.span.start)) + Span(id.span.start, id.span.end, id.span.start)) } else { val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) From 1a1f424958ed1df0face143ca473eb671f594a6c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 26 Jun 2019 13:41:46 +0200 Subject: [PATCH 2/2] Improve handling of nameSpan Even with the fix to enum spans, we could still get a case where a point to a name is missing (maybe because there is a long comment between the start of the definition and the name). The current fix makes the computation succeed more often, but it is not perfect. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 61b16d1e0d74..0dd1fe07d24e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -351,7 +351,23 @@ object Trees { if (span.exists) { val point = span.point if (rawMods.is(Synthetic) || name.toTermName == nme.ERROR) Span(point) - else Span(point, point + name.stripModuleClassSuffix.lastPart.length, point) + else { + val realName = name.stripModuleClassSuffix.lastPart.toString + val nameStart = + if (point != span.start) point + else { + // Point might be too far away from start to be recorded. In this case we fall back to scanning + // forwards from the start offset for the name. + // Note: This might be inaccurate since scanning might hit accidentally the same + // name (e.g. in a comment) before finding the real definition. + // To make this behavior more robust we'd have to change the trees for definitions to contain + // a fully positioned Ident in place of a name. + val idx = source.content().indexOfSlice(realName, point) + if (idx >= 0) idx + else point // use `point` anyway. This is important if no source exists so scanning fails + } + Span(point, point + realName.length, point) + } } else span }