80 lines
2.9 KiB
C#
80 lines
2.9 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using Microsoft.AspNetCore.Razor.Language;
|
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
|
using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span;
|
|
|
|
namespace Microsoft.VisualStudio.Editor.Razor
|
|
{
|
|
internal class RazorSyntaxTreePartialParser
|
|
{
|
|
private Span _lastChangeOwner;
|
|
private bool _lastResultProvisional;
|
|
|
|
public RazorSyntaxTreePartialParser(RazorSyntaxTree syntaxTree)
|
|
{
|
|
if (syntaxTree == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(syntaxTree));
|
|
}
|
|
|
|
// We mutate the existing syntax tree so we need to clone the one passed in so our mutations don't
|
|
// impact external state.
|
|
SyntaxTreeRoot = (Block)syntaxTree.Root.Clone();
|
|
}
|
|
|
|
// Internal for testing
|
|
internal Block SyntaxTreeRoot { get; }
|
|
|
|
public PartialParseResultInternal Parse(SourceChange change)
|
|
{
|
|
var result = GetPartialParseResult(change);
|
|
|
|
// Remember if this was provisionally accepted for next partial parse.
|
|
_lastResultProvisional = (result & PartialParseResultInternal.Provisional) == PartialParseResultInternal.Provisional;
|
|
|
|
return result;
|
|
}
|
|
|
|
private PartialParseResultInternal GetPartialParseResult(SourceChange change)
|
|
{
|
|
var result = PartialParseResultInternal.Rejected;
|
|
|
|
// Try the last change owner
|
|
if (_lastChangeOwner != null && _lastChangeOwner.EditHandler.OwnsChange(_lastChangeOwner, change))
|
|
{
|
|
var editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
|
|
result = editResult.Result;
|
|
if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
|
|
{
|
|
_lastChangeOwner.ReplaceWith(editResult.EditedSpan);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Locate the span responsible for this change
|
|
_lastChangeOwner = SyntaxTreeRoot.LocateOwner(change);
|
|
|
|
if (_lastResultProvisional)
|
|
{
|
|
// Last change owner couldn't accept this, so we must do a full reparse
|
|
result = PartialParseResultInternal.Rejected;
|
|
}
|
|
else if (_lastChangeOwner != null)
|
|
{
|
|
var editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
|
|
result = editResult.Result;
|
|
if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
|
|
{
|
|
_lastChangeOwner.ReplaceWith(editResult.EditedSpan);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|