Fix a bug in the span mapping code
This wasn't quite doing the right thing, and it's simpler than we make it to be.
This commit is contained in:
parent
bafe1b27ff
commit
4927525519
|
|
@ -11,7 +11,6 @@ namespace Microsoft.CodeAnalysis.Experiment
|
||||||
{
|
{
|
||||||
public SpanMapResult(Document document, LinePositionSpan linePositionSpan)
|
public SpanMapResult(Document document, LinePositionSpan linePositionSpan)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,10 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||||
{
|
{
|
||||||
results.Add(new SpanMapResult(document, linePositionSpan));
|
results.Add(new SpanMapResult(document, linePositionSpan));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
results.Add(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(results.ToImmutable());
|
return Task.FromResult(results.ToImmutable());
|
||||||
|
|
@ -161,31 +165,30 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||||
// Internal for testing.
|
// Internal for testing.
|
||||||
internal static bool TryGetLinePositionSpan(TextSpan span, SourceText source, RazorCSharpDocument output, out LinePositionSpan linePositionSpan)
|
internal static bool TryGetLinePositionSpan(TextSpan span, SourceText source, RazorCSharpDocument output, out LinePositionSpan linePositionSpan)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < output.SourceMappings.Count; i++)
|
var mappings = output.SourceMappings;
|
||||||
|
for (var i = 0; i < mappings.Count; i++)
|
||||||
{
|
{
|
||||||
var mapping = output.SourceMappings[i];
|
var mapping = mappings[i];
|
||||||
if (span.Length > mapping.GeneratedSpan.Length)
|
|
||||||
{
|
|
||||||
// If the length of the generated span is smaller they can't match. A C# expression
|
|
||||||
// won't cover multiple generated spans.
|
|
||||||
//
|
|
||||||
// This heuristic is useful in the Razor context to filter out zero-length
|
|
||||||
// spans.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var original = mapping.OriginalSpan.AsTextSpan();
|
var original = mapping.OriginalSpan.AsTextSpan();
|
||||||
var generated = mapping.GeneratedSpan.AsTextSpan();
|
var generated = mapping.GeneratedSpan.AsTextSpan();
|
||||||
|
|
||||||
|
if (!generated.Contains(span))
|
||||||
|
{
|
||||||
|
// If the search span isn't contained within the generated span, it is not a match.
|
||||||
|
// A C# identifier won't cover multiple generated spans.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var leftOffset = span.Start - generated.Start;
|
var leftOffset = span.Start - generated.Start;
|
||||||
var rightOffset = span.End - generated.End;
|
var rightOffset = span.End - generated.End;
|
||||||
if (leftOffset >= 0 && rightOffset <= 0)
|
Debug.Assert(leftOffset >= 0);
|
||||||
{
|
Debug.Assert(rightOffset <= 0);
|
||||||
// This span mapping contains the span.
|
|
||||||
var adjusted = new TextSpan(original.Start + leftOffset, (original.End + rightOffset) - (original.Start + leftOffset));
|
// Note: we don't handle imports here - the assumption is that for all of the scenarios we
|
||||||
linePositionSpan = source.Lines.GetLinePositionSpan(adjusted);
|
// support, the span is in the original source document.
|
||||||
return true;
|
var adjusted = new TextSpan(original.Start + leftOffset, (original.End + rightOffset) - (original.Start + leftOffset));
|
||||||
}
|
linePositionSpan = source.Lines.GetLinePositionSpan(adjusted);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
linePositionSpan = default;
|
linePositionSpan = default;
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,62 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||||
Assert.NotNull(container.LatestDocument);
|
Assert.NotNull(container.LatestDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetLinePositionSpan_SpanMatchesSourceMapping_ReturnsTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = @"
|
||||||
|
@SomeProperty
|
||||||
|
";
|
||||||
|
var sourceText = SourceText.From(content);
|
||||||
|
var codeDocument = GetCodeDocument(content);
|
||||||
|
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||||
|
var generatedCode = csharpDocument.GeneratedCode;
|
||||||
|
|
||||||
|
var symbol = "SomeProperty";
|
||||||
|
var span = new TextSpan(generatedCode.IndexOf(symbol), symbol.Length);
|
||||||
|
|
||||||
|
// Position of `SomeProperty` in the source code.
|
||||||
|
var expectedLineSpan = new LinePositionSpan(new LinePosition(1, 1), new LinePosition(1, 13));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = GeneratedCodeContainer.TryGetLinePositionSpan(span, sourceText, csharpDocument, out var lineSpan);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal(expectedLineSpan, lineSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetLinePositionSpan_SpanMatchesSourceMapping_MatchingOnPosition_ReturnsTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = @"
|
||||||
|
@SomeProperty
|
||||||
|
@SomeProperty
|
||||||
|
@SomeProperty
|
||||||
|
";
|
||||||
|
var sourceText = SourceText.From(content);
|
||||||
|
var codeDocument = GetCodeDocument(content);
|
||||||
|
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||||
|
var generatedCode = csharpDocument.GeneratedCode;
|
||||||
|
|
||||||
|
var symbol = "SomeProperty";
|
||||||
|
|
||||||
|
// Second occurrence
|
||||||
|
var span = new TextSpan(generatedCode.IndexOf(symbol, generatedCode.IndexOf(symbol) + symbol.Length), symbol.Length);
|
||||||
|
|
||||||
|
// Position of `SomeProperty` in the source code.
|
||||||
|
var expectedLineSpan = new LinePositionSpan(new LinePosition(2, 1), new LinePosition(2, 13));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = GeneratedCodeContainer.TryGetLinePositionSpan(span, sourceText, csharpDocument, out var lineSpan);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal(expectedLineSpan, lineSpan);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TryGetLinePositionSpan_SpanWithinSourceMapping_ReturnsTrue()
|
public void TryGetLinePositionSpan_SpanWithinSourceMapping_ReturnsTrue()
|
||||||
{
|
{
|
||||||
|
|
@ -73,8 +129,6 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||||
var csharpDocument = codeDocument.GetCSharpDocument();
|
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||||
var generatedCode = csharpDocument.GeneratedCode;
|
var generatedCode = csharpDocument.GeneratedCode;
|
||||||
|
|
||||||
// TODO: Make writing these tests a little less manual.
|
|
||||||
// Position of `SomeProperty` in the generated code.
|
|
||||||
var symbol = "SomeProperty";
|
var symbol = "SomeProperty";
|
||||||
var span = new TextSpan(generatedCode.IndexOf(symbol), symbol.Length);
|
var span = new TextSpan(generatedCode.IndexOf(symbol), symbol.Length);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue