public void ImplicitExpressionAcceptsIdentifierTypedAfterDotIfLastChangeWasProvisionalAcceptanceOfDot() { // Arrange TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo bar"), 1, new StringTextBuffer("foo @foo. bar")); TextChange charTyped = new TextChange(9, 0, new StringTextBuffer("foo @foo. bar"), 1, new StringTextBuffer("foo @foo.b bar")); TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(dotTyped.OldBuffer); // Apply the dot change Assert.AreEqual(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped)); // Act (apply the identifier start char change) PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped); // Assert Assert.AreEqual(PartialParseResult.Accepted, result, "The change was not fully accepted!"); Assert.IsFalse(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not"); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock( new MarkupSpan("foo "), new ExpressionBlock( new TransitionSpan(RazorParser.TransitionString, hidden: false, acceptedCharacters: AcceptedCharacters.None), new ImplicitExpressionSpan("foo.b", CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false, acceptedCharacters: AcceptedCharacters.NonWhiteSpace) ), new MarkupSpan(" bar"))); }
private void CreateAutoBlockCompleter(PartialParseResult parseResult, TextChange textChange) { if (IsFlagSet(parseResult, PartialParseResult.AutoCompleteBlock)) { _autoBlockCompletor = new AutoBlockCompletor(TextView, textChange.NewPosition, _razorEditorParser.GetAutoCompleteString()); return; } if (textChange.OldLength == 0 && textChange.NewLength > 0 && textChange.NewLength <= 2 && Whitespace.IsNewLine((textChange.NewBuffer as IShimTextBuffer).Snapshot.GetText(textChange.NewPosition, textChange.NewLength)) && _viewBuffer.ContentType.IsOfType("RazorCSharp")) { ITextSnapshot currentSnapshot = _viewBuffer.CurrentSnapshot; ITextSnapshotLine lineFromPosition = currentSnapshot.GetLineFromPosition(textChange.NewPosition); string text = lineFromPosition.GetText(); int num = Math.Min(lineFromPosition.Length, textChange.NewPosition - lineFromPosition.Start) - 1; while (num >= 0 && char.IsWhiteSpace(text[num])) { num--; } if (num >= 1 && text[num] == '{' && text[num - 1] == '@') { int num2 = textChange.NewPosition + textChange.NewLength; ITextSnapshotLine lineFromPosition2 = currentSnapshot.GetLineFromPosition(num2); string text2 = lineFromPosition2.GetText(); int num3 = num2 - lineFromPosition2.Start; while (num3 < lineFromPosition2.Length && char.IsWhiteSpace(text2[num3])) { num3++; } if (num3 < lineFromPosition2.Length && text2[num3] == '}') { _autoBlockCompletor = new AutoBlockCompletor(TextView, textChange.NewPosition, string.Empty); } } } }
internal static void WriteDebugTree(string sourceFile, Block document, PartialParseResult result, TextChange change, RazorEditorParser parser, bool treeStructureChanged) { if (!OutputDebuggingEnabled) { return; } RunTask(() => { string outputFileName = Normalize(sourceFile) + "_tree"; string outputPath = Path.Combine(Path.GetDirectoryName(sourceFile), outputFileName); var treeBuilder = new StringBuilder(); WriteTree(document, treeBuilder); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Last Change: {0}", change); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Normalized To: {0}", change.Normalize()); treeBuilder.AppendLine(); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result); treeBuilder.AppendLine(); if (result.HasFlag(PartialParseResult.Rejected)) { treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged); treeBuilder.AppendLine(); } if (result.HasFlag(PartialParseResult.AutoCompleteBlock)) { treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Auto Complete Insert String: \"{0}\"", parser.GetAutoCompleteString()); treeBuilder.AppendLine(); } File.WriteAllText(outputPath, treeBuilder.ToString()); }); }
public void CheckForStructureChangesStartsFullReparseIfChangeOverlapsMultipleSpans() { // Arrange RazorEditorParser parser = new RazorEditorParser(CreateHost(), TestLinePragmaFileName); ITextBuffer original = new StringTextBuffer("Foo @bar Baz"); ITextBuffer changed = new StringTextBuffer("Foo @bap Daz"); TextChange change = new TextChange(7, 3, original, 3, changed); ManualResetEventSlim parseComplete = new ManualResetEventSlim(); int parseCount = 0; parser.DocumentParseComplete += (sender, args) => { Interlocked.Increment(ref parseCount); parseComplete.Set(); }; Assert.Equal(PartialParseResult.Rejected, parser.CheckForStructureChanges(new TextChange(0, 0, new StringTextBuffer(String.Empty), 12, original))); MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait); // Wait for the parse to finish parseComplete.Reset(); // Act PartialParseResult result = parser.CheckForStructureChanges(change); // Assert Assert.Equal(PartialParseResult.Rejected, result); MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait); Assert.Equal(2, parseCount); }
public void ImplicitExpressionRejectsChangeWhichWouldHaveBeenAcceptedIfLastChangeWasProvisionallyAcceptedOnDifferentSpan() { // Arrange TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo @bar"), 1, new StringTextBuffer("foo @foo. @bar")); TextChange charTyped = new TextChange(14, 0, new StringTextBuffer("foo @foo. @barb"), 1, new StringTextBuffer("foo @foo. @barb")); TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(dotTyped.OldBuffer); // Apply the dot change Assert.AreEqual(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped)); // Act (apply the identifier start char change) PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped); // Assert Assert.AreEqual(PartialParseResult.Rejected, result, "The change was accepted despite the previous change being provisionally accepted!"); Assert.IsFalse(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not"); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock( new MarkupSpan("foo "), new ExpressionBlock( new TransitionSpan(RazorParser.TransitionString, hidden: false, acceptedCharacters: AcceptedCharacters.None), new ImplicitExpressionSpan("foo", VBCodeParser.DefaultKeywords, acceptTrailingDot: false, acceptedCharacters: AcceptedCharacters.NonWhiteSpace) ), new MarkupSpan(". "), new ExpressionBlock( new TransitionSpan(RazorParser.TransitionString, hidden: false, acceptedCharacters: AcceptedCharacters.None), new ImplicitExpressionSpan("barb", VBCodeParser.DefaultKeywords, acceptTrailingDot: false, acceptedCharacters: AcceptedCharacters.NonWhiteSpace) ), new MarkupSpan(String.Empty))); }
public void ImplicitExpressionProvisionallyAcceptsDotlessCommitInsertions() { SpanFactory factory = SpanFactory.CreateCsHtml(); var changed = new StringTextBuffer("foo @DateT. baz"); var old = new StringTextBuffer("foo @DateT baz"); var textChange = new TextChange(10, 0, old, 1, changed); TestParserManager manager = CreateParserManager(); Action <TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) => { PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange); // Assert Assert.Equal(expectedResult, result); Assert.Equal(1, manager.ParseCount); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock( factory.Markup("foo "), new ExpressionBlock( factory.CodeTransition(), factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)), factory.Markup(" baz"))); }; manager.InitializeWithDocument(textChange.OldBuffer); // This is the process of a dotless commit when doing "." insertions to commit intellisense changes. applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateT."); old = changed; changed = new StringTextBuffer("foo @DateTime. baz"); textChange = new TextChange(10, 0, old, 3, changed); applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime."); }
public void ImplicitExpressionAcceptsIdentifierTypedAfterDotIfLastChangeWasProvisionalAcceptanceOfDot() { var factory = SpanFactory.CreateCsHtml(); // Arrange TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo bar"), 1, new StringTextBuffer("foo @foo. bar")); TextChange charTyped = new TextChange(9, 0, new StringTextBuffer("foo @foo. bar"), 1, new StringTextBuffer("foo @foo.b bar")); TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(dotTyped.OldBuffer); // Apply the dot change Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped)); // Act (apply the identifier start char change) PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped); // Assert Assert.Equal(PartialParseResult.Accepted, result); Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not"); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock( factory.Markup("foo "), new ExpressionBlock( factory.CodeTransition(), factory.Code("foo.b") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) .Accepts(AcceptedCharacters.NonWhiteSpace)), factory.Markup(" bar"))); }
public void ImplicitExpressionAcceptsDotlessCommitInsertionsInStatementBlockAfterIdentifiers() { SpanFactory factory = SpanFactory.CreateCsHtml(); StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine + " @DateTime." + Environment.NewLine + "}"); StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine + " @DateTime" + Environment.NewLine + "}"); var textChange = new TextChange(17, 0, old, 1, changed); using (TestParserManager manager = CreateParserManager()) { Action <TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) => { PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange); // Assert Assert.Equal(expectedResult, result); Assert.Equal(1, manager.ParseCount); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock( factory.EmptyHtml(), new StatementBlock( factory.CodeTransition(), factory.MetaCode("{").Accepts(AcceptedCharacters.None), factory.Code("\r\n ").AsStatement(), new ExpressionBlock( factory.CodeTransition(), factory.Code(expectedCode) .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true) .Accepts(AcceptedCharacters.NonWhiteSpace)), factory.Code("\r\n").AsStatement(), factory.MetaCode("}").Accepts(AcceptedCharacters.None)), factory.EmptyHtml())); }; manager.InitializeWithDocument(textChange.OldBuffer); // This is the process of a dotless commit when doing "." insertions to commit intellisense changes. applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime."); old = changed; changed = new StringTextBuffer("@{" + Environment.NewLine + " @DateTime.." + Environment.NewLine + "}"); textChange = new TextChange(18, 0, old, 1, changed); applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime.."); old = changed; changed = new StringTextBuffer("@{" + Environment.NewLine + " @DateTime.Now." + Environment.NewLine + "}"); textChange = new TextChange(18, 0, old, 3, changed); applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime.Now."); } }
public PartialParseResult CheckForStructureChangesAndWait(TextChange change) { PartialParseResult result = Parser.CheckForStructureChanges(change); if (result.HasFlag(PartialParseResult.Rejected)) { WaitForParse(); } return(result); }
private PartialParseResult HandleDotlessCommitInsertion(Span target) { PartialParseResult result = PartialParseResult.Accepted; if (!AcceptTrailingDot && target.Content.LastOrDefault() == '.') { result |= PartialParseResult.Provisional; } return(result); }
/// <summary> /// Determines if a change will cause a structural change to the document and if not, applies it to the existing tree. /// If a structural change would occur, automatically starts a reparse /// </summary> /// <remarks> /// NOTE: The initial incremental parsing check and actual incremental parsing (if possible) occurs /// on the callers thread. However, if a full reparse is needed, this occurs on a background thread. /// </remarks> /// <param name="change">The change to apply to the parse tree</param> /// <returns>A PartialParseResult value indicating the result of the incremental parse</returns> public virtual PartialParseResult CheckForStructureChanges(TextChange change) { // Validate the change long?elapsedMs = null; #if EDITOR_TRACING Stopwatch sw = new Stopwatch(); sw.Start(); #endif RazorEditorTrace.TraceLine(RazorResources.FormatTrace_EditorReceivedChange(Path.GetFileName(FileName), change)); if (change.NewBuffer == null) { throw new ArgumentException(RazorResources.FormatStructure_Member_CannotBeNull( "Buffer", "TextChange"), "change"); } PartialParseResult result = PartialParseResult.Rejected; // If there isn't already a parse underway, try partial-parsing string changeString = String.Empty; using (_parser.SynchronizeMainThreadState()) { // Capture the string value of the change while we're synchronized changeString = change.ToString(); // Check if we can partial-parse if (CurrentParseTree != null && _parser.IsIdle) { result = TryPartialParse(change); } } // If partial parsing failed or there were outstanding parser tasks, start a full reparse if (result.HasFlag(PartialParseResult.Rejected)) { _parser.QueueChange(change); } // Otherwise, remember if this was provisionally accepted for next partial parse LastResultProvisional = result.HasFlag(PartialParseResult.Provisional); VerifyFlagsAreValid(result); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif RazorEditorTrace.TraceLine( RazorResources.FormatTrace_EditorProcessedChange( Path.GetFileName(FileName), changeString, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?", result.ToString())); return(result); }
private PartialParseResult TryAcceptChange(Span target, TextChange change, PartialParseResult acceptResult = PartialParseResult.Accepted) { string content = change.ApplyChange(target); if (StartsWithKeyword(content)) { return(PartialParseResult.Rejected | PartialParseResult.SpanContextChanged); } return(acceptResult); }
private PartialParseResult TryAcceptChange(Span target, SourceChange change, PartialParseResult acceptResult = PartialParseResult.Accepted) { var content = change.GetEditedContent(target); if (StartsWithKeyword(content)) { return(PartialParseResult.Rejected | PartialParseResult.SpanContextChanged); } return(acceptResult); }
public void ApplyChangeReturnsRejectedIfTerminatorStringNull() { // Arrange var span = new CodeSpan(new SourceLocation(0, 0, 0), "foo"); var change = new TextChange(0, 0, new StringTextBuffer("foo"), 1, new StringTextBuffer("bfoo")); // Act PartialParseResult result = span.ApplyChange(change); // Assert Assert.AreEqual(PartialParseResult.Rejected, result); }
private PartialParseResult TryPartialParse(TextChange change) { PartialParseResult result = PartialParseResult.Rejected; // Try the last change owner if ( _lastChangeOwner != null && _lastChangeOwner.EditHandler.OwnsChange(_lastChangeOwner, change) ) { EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange( _lastChangeOwner, change ); result = editResult.Result; if (!editResult.Result.HasFlag(PartialParseResult.Rejected)) { _lastChangeOwner.ReplaceWith(editResult.EditedSpan); } return(result); } // Locate the span responsible for this change _lastChangeOwner = CurrentParseTree.LocateOwner(change); if (LastResultProvisional) { // Last change owner couldn't accept this, so we must do a full reparse result = PartialParseResult.Rejected; } else if (_lastChangeOwner != null) { EditResult editRes = _lastChangeOwner.EditHandler.ApplyChange( _lastChangeOwner, change ); result = editRes.Result; if (!editRes.Result.HasFlag(PartialParseResult.Rejected)) { _lastChangeOwner.ReplaceWith(editRes.EditedSpan); } if (result.HasFlag(PartialParseResult.AutoCompleteBlock)) { _lastAutoCompleteSpan = _lastChangeOwner; } else { _lastAutoCompleteSpan = null; } } return(result); }
protected static void RunFullReparseTest(TextChange change, PartialParseResult additionalFlags = (PartialParseResult)0) { // Arrange TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(change.OldBuffer); // Act PartialParseResult result = manager.CheckForStructureChangesAndWait(change); // Assert Assert.Equal(PartialParseResult.Rejected | additionalFlags, result); Assert.Equal(2, manager.ParseCount); }
public void SpanWithAcceptTrailingDotOnAcceptsIntelliSenseReplaceWhichActuallyInsertsDot() { // Arrange var span = new ImplicitExpressionSpan("abcd", CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true, acceptedCharacters: AcceptedCharacters.None); var newBuffer = new StringTextBuffer("abcd."); var oldBuffer = new StringTextBuffer("abcd"); var textChange = new TextChange(0, 4, oldBuffer, 5, newBuffer); // Act PartialParseResult result = span.ApplyChange(textChange); // Assert Assert.AreEqual(PartialParseResult.Accepted, result); }
public void SpanWithAcceptTrailingDotOffProvisionallyAcceptsEndReplacementWithTrailingDot() { // Arrange var span = new ImplicitExpressionSpan("abcd.", CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false, acceptedCharacters: AcceptedCharacters.None); var newBuffer = new StringTextBuffer("abcdef."); var oldBuffer = new StringTextBuffer("abcd."); var textChange = new TextChange(0, 5, oldBuffer, 7, newBuffer); // Act PartialParseResult result = span.ApplyChange(textChange); // Assert Assert.AreEqual(PartialParseResult.Accepted | PartialParseResult.Provisional, result); }
protected static void RunFullReparseTest(TextChange change, PartialParseResult additionalFlags = (PartialParseResult)0) { // Arrange TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(change.OldBuffer); // Act PartialParseResult result = manager.CheckForStructureChangesAndWait(change); // Assert Assert.AreEqual(PartialParseResult.Rejected | additionalFlags, result, "The specified change did not cause a structural change"); Assert.AreEqual(2, manager.ParseCount, "Expected that the change would cause a full reparse"); }
private PartialParseResult TryPartialParse(TextChange change) { PartialParseResult result = PartialParseResult.Rejected; // Try the last change owner if (_lastChangeOwner != null && _lastChangeOwner.EditHandler.OwnsChange(_lastChangeOwner, change)) { EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change); result = editResult.Result; if (!editResult.Result.HasFlag(PartialParseResult.Rejected)) { _lastChangeOwner.ReplaceWith(editResult.EditedSpan); } // If the last change was provisional, then the result of this span's attempt to parse partially goes // Otherwise, accept the change if this span accepted it, but if it didn't, just do the standard search. if (LastResultProvisional || result.HasFlag(PartialParseResult.Accepted)) { return(result); } } // Locate the span responsible for this change _lastChangeOwner = CurrentParseTree.LocateOwner(change); if (LastResultProvisional) { // Last change owner couldn't accept this, so we must do a full reparse result = PartialParseResult.Rejected; } else if (_lastChangeOwner != null) { EditResult editRes = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change); result = editRes.Result; if (!editRes.Result.HasFlag(PartialParseResult.Rejected)) { _lastChangeOwner.ReplaceWith(editRes.EditedSpan); } if (result.HasFlag(PartialParseResult.AutoCompleteBlock)) { _lastAutoCompleteSpan = _lastChangeOwner; } else { _lastAutoCompleteSpan = null; } } return(result); }
protected static void RunPartialParseTest(TextChange change, Block newTreeRoot, PartialParseResult additionalFlags = (PartialParseResult)0) { // Arrange TestParserManager manager = CreateParserManager(); manager.InitializeWithDocument(change.OldBuffer); // Act PartialParseResult result = manager.CheckForStructureChangesAndWait(change); // Assert Assert.Equal(PartialParseResult.Accepted | additionalFlags, result); Assert.Equal(1, manager.ParseCount); ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, newTreeRoot); }
public void ApplyChangeReturnsRejectedWithoutAutoCompleteBlockIfTerminatorStringNonNullAndEditIsNewlineInsertOnSecondLine() { // Arrange var span = new CodeSpan(new SourceLocation(0, 0, 0), "foo\r\nbar\r\nbaz") { AutoCompleteString = "}" }; var change = new TextChange(8, 0, new StringTextBuffer("foo\r\nbar\r\nbaz"), 2, new StringTextBuffer("foo\r\nb\r\nar\r\nbaz")); // Act PartialParseResult result = span.ApplyChange(change); // Assert Assert.AreEqual(PartialParseResult.Rejected, result); }
private static void VerifyFlagsAreValid(PartialParseResult result) { Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) || ((result & PartialParseResult.Rejected) == PartialParseResult.Rejected), "Partial Parse result does not have either of Accepted or Rejected flags set"); Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) || ((result & PartialParseResult.SpanContextChanged) != PartialParseResult.SpanContextChanged), "Partial Parse result was Accepted AND had SpanContextChanged flag set"); Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) || ((result & PartialParseResult.AutoCompleteBlock) != PartialParseResult.AutoCompleteBlock), "Partial Parse result was Accepted AND had AutoCompleteBlock flag set"); Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) || ((result & PartialParseResult.Provisional) != PartialParseResult.Provisional), "Partial Parse result was Rejected AND had Provisional flag set"); }
/// <summary> /// Determines if a change will cause a structural change to the document and if not, applies it to the existing tree. /// If a structural change would occur, automatically starts a reparse /// </summary> /// <remarks> /// NOTE: The initial incremental parsing check and actual incremental parsing (if possible) occurs /// on the callers thread. However, if a full reparse is needed, this occurs on a background thread. /// </remarks> /// <param name="change">The change to apply to the parse tree</param> /// <returns>A PartialParseResult value indicating the result of the incremental parse</returns> public virtual PartialParseResult CheckForStructureChanges(TextChange change) { // Validate the change if (change.NewBuffer == null) { throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, RazorResources.Structure_Member_CannotBeNull, "Buffer", "TextChange"), "change"); } PartialParseResult result = PartialParseResult.Rejected; // Lock the state objects lock (_lock) { // If there isn't already a parse underway, try partial-parsing if (CurrentParseTree != null && _outstandingParserTasks.Count == 0) { result = TryPartialParse(change); } // If partial parsing failed or there were outstanding parser tasks, start a full reparse if (result.HasFlag(PartialParseResult.Rejected)) { QueueFullReparse(change); } #if DEBUG else { if (CurrentParseTree != null) { RazorDebugHelpers.WriteDebugTree(FileName, CurrentParseTree, result, change, this, false); } if (_currentCompileUnit != null) { RazorDebugHelpers.WriteGeneratedCode(FileName, _currentCompileUnit); } } #endif // Otherwise, remember if this was provisionally accepted for next partial parse LastResultProvisional = result.HasFlag(PartialParseResult.Provisional); } VerifyFlagsAreValid(result); return(result); }
public virtual EditResult ApplyChange(Span target, TextChange change, bool force) { PartialParseResult result = PartialParseResult.Accepted; TextChange normalized = change.Normalize(); if (!force) { result = CanAcceptChange(target, normalized); } // If the change is accepted then apply the change if (result.HasFlag(PartialParseResult.Accepted)) { return(new EditResult(result, UpdateSpan(target, normalized))); } return(new EditResult(result, new SpanBuilder(target))); }
/// <summary> /// Applies the specified change to this span, optionally forcing it to accept it /// </summary> /// <param name="force">If true, no evaluation is performed, the content of the span is simply updated based on the change</param> /// <remarks> /// If this method returns a value with the PartialParseResults.Accepted flag, the change has been applied to the span. /// If force was specified, this does not indicate that the partial parsing was successful, only that the Span now reflects the applied change. /// </remarks> /// <returns>true if the change was successfully applied, false if it wasn't</returns> public PartialParseResult ApplyChange(TextChange change, bool force) { PartialParseResult result = PartialParseResult.Accepted; TextChange normalized = change.Normalize(); if (!force) { result = CanAcceptChange(normalized); } // If the change is accepted then apply the change if (result.HasFlag(PartialParseResult.Accepted)) { UpdateContent(normalized); } return(result); }
private void CheckForStructureChanges(TextChange textChange) { SetProvisionallyAcceptedState(false); PartialParseResult partialParseResult = _razorEditorParser.CheckForStructureChanges(textChange); CreateAutoBlockCompleter(partialParseResult, textChange); if (IsFlagSet(partialParseResult, PartialParseResult.Rejected)) { _pendingShimTextChange = new TextChange?(textChange); } if (IsFlagSet(partialParseResult, PartialParseResult.Provisional)) { SetProvisionallyAcceptedState(true); } if (IsFlagSet(partialParseResult, PartialParseResult.SpanContextChanged)) { _spanContextChanged = true; } }
public void ImplicitExpressionRejectsWholeIdentifierReplacementToKeyword() { // Arrange RazorEngineHost host = CreateHost(); RazorEditorParser parser = new RazorEditorParser(host, @"C:\This\Is\A\Test\Path"); TestParserManager manager = new TestParserManager(parser); StringTextBuffer old = new StringTextBuffer("foo @date baz"); StringTextBuffer changed = new StringTextBuffer("foo @if baz"); TextChange textChange = new TextChange(5, 4, old, 2, changed); manager.InitializeWithDocument(old); // Act PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange); // Assert Assert.Equal(PartialParseResult.Rejected, result); Assert.Equal(2, manager.ParseCount); }
private PartialParseResult HandleReplacement(Span target, TextChange change) { // Special Case for IntelliSense commits. // When IntelliSense commits, we get two changes (for example user typed "Date", then committed "DateTime" by pressing ".") // 1. Insert "." at the end of this span // 2. Replace the "Date." at the end of the span with "DateTime." // We need partial parsing to accept case #2. string oldText = GetOldText(target, change); PartialParseResult result = PartialParseResult.Rejected; if (EndsWithDot(oldText) && EndsWithDot(change.NewText)) { result = PartialParseResult.Accepted; if (!AcceptTrailingDot) { result |= PartialParseResult.Provisional; } } return(result); }
private PartialParseResult HandleInsertionAfterIdPart(Span target, TextChange change) { // If the insertion is a full identifier part, accept it if (ParserHelpers.IsIdentifier(change.NewText, requireIdentifierStart: false)) { return(TryAcceptChange(target, change)); } else if (EndsWithDot(change.NewText)) { // Accept it, possibly provisionally PartialParseResult result = PartialParseResult.Accepted; if (!AcceptTrailingDot) { result |= PartialParseResult.Provisional; } return(TryAcceptChange(target, change, result)); } else { return(PartialParseResult.Rejected); } }
private PartialParseResult TryAcceptChange(Span target, TextChange change, PartialParseResult acceptResult = PartialParseResult.Accepted) { string content = change.ApplyChange(target); if (StartsWithKeyword(content)) { return PartialParseResult.Rejected | PartialParseResult.SpanContextChanged; } return acceptResult; }
public EditResult(PartialParseResult result, SpanBuilder editedSpan) { Result = result; EditedSpan = editedSpan; }
private bool IsFlagSet(PartialParseResult toTest, PartialParseResult flag) { return (toTest & flag) > (PartialParseResult)0; }