diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs
index 7908a9f116..26ff5b803a 100644
--- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs
+++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs
@@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.Razor
{
- public abstract class RazorTemplateEngineFactoryService : ILanguageService
+ internal abstract class RazorTemplateEngineFactoryService : ILanguageService
{
public abstract RazorTemplateEngine Create(string projectPath, Action configure);
}
diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs
index d246743f59..a16f46400b 100644
--- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs
+++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs
@@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.Razor
{
- public abstract class TagHelperResolver : ILanguageService
+ internal abstract class TagHelperResolver : ILanguageService
{
public abstract TagHelperResolutionResult GetTagHelpers(Compilation compilation);
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDirectiveResolver.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDirectiveResolver.cs
index f0ce0e7e3f..9c1eadae88 100644
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDirectiveResolver.cs
+++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDirectiveResolver.cs
@@ -29,9 +29,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
}
catch (Exception exception)
{
- throw new RazorLanguageServiceException(
- typeof(DefaultRazorEngineDirectiveResolver).FullName,
- nameof(GetRazorEngineDirectivesAsync),
+ throw new InvalidOperationException(
+ Resources.FormatUnexpectedException(
+ typeof(DefaultRazorEngineDirectiveResolver).FullName,
+ nameof(GetRazorEngineDirectivesAsync)),
exception);
}
}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDocumentGenerator.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDocumentGenerator.cs
index 09b3f66ce8..b7c0cce061 100644
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDocumentGenerator.cs
+++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultRazorEngineDocumentGenerator.cs
@@ -27,9 +27,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
}
catch (Exception exception)
{
- throw new RazorLanguageServiceException(
- typeof(DefaultRazorEngineDocumentGenerator).FullName,
- nameof(GenerateDocumentAsync),
+ throw new InvalidOperationException(
+ Resources.FormatUnexpectedException(
+ typeof(DefaultRazorEngineDocumentGenerator).FullName,
+ nameof(GenerateDocumentAsync)),
exception);
}
}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs
index 5ed80730d7..31713fb3b2 100644
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs
+++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs
@@ -74,9 +74,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
{
_errorReporter.ReportError(exception, project);
- throw new RazorLanguageServiceException(
- typeof(DefaultTagHelperResolver).FullName,
- nameof(GetTagHelpersAsync),
+ throw new InvalidOperationException(
+ Resources.FormatUnexpectedException(
+ typeof(DefaultTagHelperResolver).FullName,
+ nameof(GetTagHelpersAsync)),
exception);
}
}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AcceptedCharacters.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AcceptedCharacters.cs
deleted file mode 100644
index 034dda9298..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AcceptedCharacters.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 System.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- [Flags]
- public enum AcceptedCharacters
- {
- None = 0,
- NewLine = 1,
- WhiteSpace = 2,
-
- NonWhiteSpace = 4,
-
- AllWhiteSpace = NewLine | WhiteSpace,
- Any = AllWhiteSpace | NonWhiteSpace,
-
- AnyExceptNewline = NonWhiteSpace | WhiteSpace
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionContext.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionContext.cs
deleted file mode 100644
index f859c1d5c1..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionContext.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 System.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public class AttributeCompletionContext
- {
- public AttributeCompletionContext(
- TagHelperDocumentContext documentContext,
- IEnumerable existingCompletions,
- string currentTagName,
- IEnumerable> attributes,
- string currentParentTagName,
- Func inHTMLSchema)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- if (existingCompletions == null)
- {
- throw new ArgumentNullException(nameof(existingCompletions));
- }
-
- if (currentTagName == null)
- {
- throw new ArgumentNullException(nameof(currentTagName));
- }
-
- if (attributes == null)
- {
- throw new ArgumentNullException(nameof(attributes));
- }
-
- if (inHTMLSchema == null)
- {
- throw new ArgumentNullException(nameof(inHTMLSchema));
- }
-
- DocumentContext = documentContext;
- ExistingCompletions = existingCompletions;
- CurrentTagName = currentTagName;
- Attributes = attributes;
- CurrentParentTagName = currentParentTagName;
- InHTMLSchema = inHTMLSchema;
- }
-
- public TagHelperDocumentContext DocumentContext { get; }
-
- public IEnumerable ExistingCompletions { get; }
-
- public string CurrentTagName { get; }
-
- public IEnumerable> Attributes { get; }
-
- public string CurrentParentTagName { get; }
-
- public Func InHTMLSchema { get; }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionResult.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionResult.cs
deleted file mode 100644
index 066d438054..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/AttributeCompletionResult.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.Collections.Generic;
-using System.Linq;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class AttributeCompletionResult
- {
- private AttributeCompletionResult()
- {
- }
-
- public abstract IReadOnlyDictionary> Completions { get; }
-
- internal static AttributeCompletionResult Create(Dictionary> completions)
- {
- var readonlyCompletions = completions.ToDictionary(
- key => key.Key,
- value => (IEnumerable)value.Value,
- completions.Comparer);
- var result = new DefaultAttributeCompletionResult(readonlyCompletions);
-
- return result;
- }
-
- private class DefaultAttributeCompletionResult : AttributeCompletionResult
- {
- private readonly IReadOnlyDictionary> _completions;
-
- public DefaultAttributeCompletionResult(IReadOnlyDictionary> completions)
- {
- _completions = completions;
- }
-
- public override IReadOnlyDictionary> Completions => _completions;
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/BlockKind.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/BlockKind.cs
deleted file mode 100644
index 5591b31943..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/BlockKind.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public enum BlockKind
- {
- // Code
- Statement,
- Directive,
- Functions,
- Expression,
- Helper,
-
- // Markup
- Markup,
- Section,
- Template,
-
- // Special
- Comment,
- Tag
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ClassifiedSpan.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ClassifiedSpan.cs
deleted file mode 100644
index a254d862dc..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ClassifiedSpan.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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 Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public struct ClassifiedSpan
- {
- public ClassifiedSpan(SourceSpan span, SourceSpan blockSpan, SpanKind spanKind, BlockKind blockKind, AcceptedCharacters acceptedCharacters)
- {
- Span = span;
- BlockSpan = blockSpan;
- SpanKind = spanKind;
- BlockKind = blockKind;
- AcceptedCharacters = acceptedCharacters;
- }
-
- public AcceptedCharacters AcceptedCharacters { get; }
-
- public BlockKind BlockKind { get; }
-
- public SourceSpan BlockSpan { get; }
-
- public SourceSpan Span { get; }
-
- public SpanKind SpanKind { get; }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultRazorSyntaxFactsService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultRazorSyntaxFactsService.cs
deleted file mode 100644
index 944942048b..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultRazorSyntaxFactsService.cs
+++ /dev/null
@@ -1,352 +0,0 @@
-// 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 System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Linq;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Legacy;
-using Microsoft.VisualStudio.Text;
-using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- [Export(typeof(RazorSyntaxFactsService))]
- internal class DefaultRazorSyntaxFactsService : RazorSyntaxFactsService
- {
- public override IReadOnlyList GetClassifiedSpans(RazorSyntaxTree syntaxTree)
- {
- if (syntaxTree == null)
- {
- throw new ArgumentNullException(nameof(syntaxTree));
- }
-
- var spans = Flatten(syntaxTree);
-
- var result = new ClassifiedSpan[spans.Count];
- for (var i = 0; i < spans.Count; i++)
- {
- var span = spans[i];
- result[i] = new ClassifiedSpan(
- new SourceSpan(
- span.Start.FilePath ?? syntaxTree.Source.FilePath,
- span.Start.AbsoluteIndex,
- span.Start.LineIndex,
- span.Start.CharacterIndex,
- span.Length),
- new SourceSpan(
- span.Parent.Start.FilePath ?? syntaxTree.Source.FilePath,
- span.Parent.Start.AbsoluteIndex,
- span.Parent.Start.LineIndex,
- span.Parent.Start.CharacterIndex,
- span.Parent.Length),
- (SpanKind)span.Kind,
- (BlockKind)span.Parent.Type,
- (AcceptedCharacters)span.EditHandler.AcceptedCharacters);
- }
-
- return result;
- }
-
- private List Flatten(RazorSyntaxTree syntaxTree)
- {
- var result = new List();
- AppendFlattenedSpans(syntaxTree.Root, result);
- return result;
-
- void AppendFlattenedSpans(SyntaxTreeNode node, List foundSpans)
- {
- Span spanNode = node as Span;
- if (spanNode != null)
- {
- foundSpans.Add(spanNode);
- }
- else
- {
- TagHelperBlock tagHelperNode = node as TagHelperBlock;
- if (tagHelperNode != null)
- {
- // These aren't in document order, sort them first and then dig in
- List attributeNodes = tagHelperNode.Attributes.Select(kvp => kvp.Value).Where(att => att != null).ToList();
- attributeNodes.Sort((x, y) => x.Start.AbsoluteIndex.CompareTo(y.Start.AbsoluteIndex));
-
- foreach (SyntaxTreeNode curNode in attributeNodes)
- {
- AppendFlattenedSpans(curNode, foundSpans);
- }
- }
-
- Block blockNode = node as Block;
- if (blockNode != null)
- {
- foreach (SyntaxTreeNode curNode in blockNode.Children)
- {
- AppendFlattenedSpans(curNode, foundSpans);
- }
- }
- }
- }
- }
-
- public override IReadOnlyList GetTagHelperSpans(RazorSyntaxTree syntaxTree)
- {
- if (syntaxTree == null)
- {
- throw new ArgumentNullException(nameof(syntaxTree));
- }
-
- var results = new List();
-
- List toProcess = new List();
- List blockChildren = new List();
- toProcess.Add(syntaxTree.Root);
-
- for (var i = 0; i < toProcess.Count; i++)
- {
- var blockNode = toProcess[i];
- TagHelperBlock tagHelperNode = blockNode as TagHelperBlock;
- if (tagHelperNode != null)
- {
- results.Add(new TagHelperSpan(
- new SourceSpan(
- tagHelperNode.Start.FilePath ?? syntaxTree.Source.FilePath,
- tagHelperNode.Start.AbsoluteIndex,
- tagHelperNode.Start.LineIndex,
- tagHelperNode.Start.CharacterIndex,
- tagHelperNode.Length),
- tagHelperNode.Binding));
- }
-
- // collect all child blocks and inject into toProcess as a single InsertRange
- foreach (SyntaxTreeNode curNode in blockNode.Children)
- {
- Block curBlock = curNode as Block;
- if (curBlock != null)
- {
- blockChildren.Add(curBlock);
- }
- }
-
- if (blockChildren.Count > 0)
- {
- toProcess.InsertRange(i + 1, blockChildren);
- blockChildren.Clear();
- }
- }
-
- return results;
- }
-
- public override int? GetDesiredIndentation(RazorSyntaxTree syntaxTree, ITextSnapshot syntaxTreeSnapshot, ITextSnapshotLine line, int indentSize, int tabSize)
- {
- if (syntaxTree == null)
- {
- throw new ArgumentNullException(nameof(syntaxTree));
- }
-
- if (syntaxTreeSnapshot == null)
- {
- throw new ArgumentNullException(nameof(syntaxTreeSnapshot));
- }
-
- if (line == null)
- {
- throw new ArgumentNullException(nameof(line));
- }
-
- if (indentSize < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(indentSize));
- }
-
- if (tabSize < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(tabSize));
- }
-
- // The tricky thing here is that line.Snapshot is very likely newer
- var previousLine = line.Snapshot.GetLineFromLineNumber(line.LineNumber - 1);
- var trackingPoint = line.Snapshot.CreateTrackingPoint(line.End, PointTrackingMode.Negative);
- var previousLineEnd = trackingPoint.GetPosition(syntaxTreeSnapshot);
-
- var simulatedChange = new SourceChange(previousLineEnd, 0, string.Empty);
- var owningSpan = LocateOwner(syntaxTree.Root, simulatedChange);
-
- int? desiredIndentation = null;
-
- if (owningSpan.Kind != SpanKindInternal.Code)
- {
- SyntaxTreeNode owningChild = owningSpan;
- while ((owningChild.Parent != null) && !desiredIndentation.HasValue)
- {
- Block owningParent = owningChild.Parent;
- List children = new List(owningParent.Children);
- for (int i = 0; i < children.Count; i++)
- {
- SyntaxTreeNode curChild = children[i];
- if (!curChild.IsBlock)
- {
- Span curSpan = curChild as Span;
- if (curSpan.Kind == SpanKindInternal.MetaCode)
- {
- // yay! We want to use the start of this span to determine the indent level.
- var startLine = line.Snapshot.GetLineFromLineNumber(curSpan.Start.LineIndex);
- var extraIndent = 0;
-
- // Dev11 337312: Only indent one level deeper if the item after the metacode is a markup block
- if (i < children.Count - 1)
- {
- SyntaxTreeNode nextChild = children[i + 1];
- if (nextChild.IsBlock && ((nextChild as Block).Type == BlockKindInternal.Markup))
- {
- extraIndent = indentSize;
- }
- }
-
- desiredIndentation = GetIndentLevelOfLine(startLine, tabSize) + indentSize;
- }
- }
-
- if (curChild == owningChild)
- {
- break;
- }
- }
-
- owningChild = owningParent;
- }
- }
-
- return desiredIndentation;
- }
-
- private Span LocateOwner(Block root, SourceChange change)
- {
- // Ask each child recursively
- Span owner = null;
- foreach (SyntaxTreeNode element in root.Children)
- {
- if (element.Start.AbsoluteIndex > change.Span.AbsoluteIndex)
- {
- // too far
- break;
- }
-
- int elementLen = element.Length;
- if (element.Start.AbsoluteIndex + elementLen < change.Span.AbsoluteIndex)
- {
- // not far enough
- continue;
- }
-
- if (element.IsBlock)
- {
- Block block = element as Block;
-
- if (element.Start.AbsoluteIndex + elementLen == change.Span.AbsoluteIndex)
- {
- Span lastDescendant = block.FindLastDescendentSpan();
- if ((lastDescendant == null) && (block is TagHelperBlock))
- {
- TagHelperBlock tagHelperBlock = (TagHelperBlock)block;
- if (tagHelperBlock.SourceEndTag != null)
- {
- lastDescendant = tagHelperBlock.SourceEndTag.FindLastDescendentSpan();
- }
- else if (tagHelperBlock.SourceStartTag != null)
- {
- lastDescendant = tagHelperBlock.SourceStartTag.FindLastDescendentSpan();
- }
- }
-
- // Conceptually, lastDescendant should always be non-null, but runtime errs on some
- // cases and makes empty blocks. Runtime will fix these issues as we find them, but make
- // no guarantee that they catch them all.
- if (lastDescendant == null)
- {
- owner = LocateOwner(block, change);
- if (owner != null)
- {
- break;
- }
- }
- else if (lastDescendant.EditHandler.OwnsChange(lastDescendant, change))
- {
- owner = lastDescendant;
- break;
- }
- }
- else
- {
- owner = LocateOwner(block, change);
- if (owner != null)
- {
- break;
- }
- }
- }
- else
- {
- Span span = element as Span;
- if (span.EditHandler.OwnsChange(span, change))
- {
- owner = span;
- break;
- }
- }
- }
-
- if (owner == null)
- {
- TagHelperBlock tagHelperNode = root as TagHelperBlock;
- if (tagHelperNode != null)
- {
- Block sourceStartTag = tagHelperNode.SourceStartTag;
- Block sourceEndTag = tagHelperNode.SourceEndTag;
- if ((sourceStartTag.Start.AbsoluteIndex <= change.Span.AbsoluteIndex) &&
- (sourceStartTag.Start.AbsoluteIndex + sourceStartTag.Length >= change.Span.AbsoluteIndex))
- {
- // intersects the start tag
- return LocateOwner(sourceStartTag, change);
- }
- else if ((sourceEndTag.Start.AbsoluteIndex <= change.Span.AbsoluteIndex) &&
- (sourceEndTag.Start.AbsoluteIndex + sourceEndTag.Length >= change.Span.AbsoluteIndex))
- {
- // intersects the end tag
- return LocateOwner(sourceEndTag, change);
- }
- }
- }
-
- return owner;
- }
-
- private int GetIndentLevelOfLine(ITextSnapshotLine line, int tabSize)
- {
- var indentLevel = 0;
-
- foreach (var c in line.GetText())
- {
- if (!char.IsWhiteSpace(c))
- {
- break;
- }
- else if (c == '\t')
- {
- indentLevel += tabSize;
- }
- else
- {
- indentLevel++;
- }
- }
-
- return indentLevel;
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperCompletionService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperCompletionService.cs
deleted file mode 100644
index e81e01ccce..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperCompletionService.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-// 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 System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Diagnostics;
-using System.Linq;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- [Export(typeof(TagHelperCompletionService))]
- internal class DefaultTagHelperCompletionService : TagHelperCompletionService
- {
- private readonly TagHelperFactsService _tagHelperFactsService;
- private static readonly HashSet _emptyHashSet = new HashSet();
-
- [ImportingConstructor]
- public DefaultTagHelperCompletionService(TagHelperFactsService tagHelperFactsService)
- {
- _tagHelperFactsService = tagHelperFactsService;
- }
-
- /*
- * This API attempts to understand a users context as they're typing in a Razor file to provide TagHelper based attribute IntelliSense.
- *
- * Scenarios for TagHelper attribute IntelliSense follows:
- * 1. TagHelperDescriptor's have matching required attribute names
- * -> Provide IntelliSense for the required attributes of those descriptors to lead users towards a TagHelperified element.
- * 2. TagHelperDescriptor entirely applies to current element. Tag name, attributes, everything is fulfilled.
- * -> Provide IntelliSense for the bound attributes for the applied descriptors.
- *
- * Within each of the above scenarios if an attribute completion has a corresponding bound attribute we associate it with the corresponding
- * BoundAttributeDescriptor. By doing this a user can see what C# type a TagHelper expects for the attribute.
- */
- public override AttributeCompletionResult GetAttributeCompletions(AttributeCompletionContext completionContext)
- {
- if (completionContext == null)
- {
- throw new ArgumentNullException(nameof(completionContext));
- }
-
- var attributeCompletions = completionContext.ExistingCompletions.ToDictionary(
- completion => completion,
- _ => new HashSet(),
- StringComparer.OrdinalIgnoreCase);
-
- var documentContext = completionContext.DocumentContext;
- var descriptorsForTag = _tagHelperFactsService.GetTagHelpersGivenTag(documentContext, completionContext.CurrentTagName, completionContext.CurrentParentTagName);
- if (descriptorsForTag.Count == 0)
- {
- // If the current tag has no possible descriptors then we can't have any additional attributes.
- var defaultResult = AttributeCompletionResult.Create(attributeCompletions);
- return defaultResult;
- }
-
- var prefix = documentContext.Prefix ?? string.Empty;
- Debug.Assert(completionContext.CurrentTagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
-
- var applicableTagHelperBinding = _tagHelperFactsService.GetTagHelperBinding(
- documentContext,
- completionContext.CurrentTagName,
- completionContext.Attributes,
- completionContext.CurrentParentTagName);
-
- var applicableDescriptors = applicableTagHelperBinding?.Descriptors ?? Enumerable.Empty();
- var unprefixedTagName = completionContext.CurrentTagName.Substring(prefix.Length);
-
- if (!completionContext.InHTMLSchema(unprefixedTagName) &&
- applicableDescriptors.All(descriptor => descriptor.TagOutputHint == null))
- {
- // This isn't a known HTML tag and no descriptor has an output element hint. Remove all previous completions.
- attributeCompletions.Clear();
- }
-
- for (var i = 0; i < descriptorsForTag.Count; i++)
- {
- var descriptor = descriptorsForTag[i];
-
- if (applicableDescriptors.Contains(descriptor))
- {
- foreach (var attributeDescriptor in descriptor.BoundAttributes)
- {
- UpdateCompletions(attributeDescriptor.Name, attributeDescriptor);
- }
- }
- else
- {
- var htmlNameToBoundAttribute = descriptor.BoundAttributes.ToDictionary(attribute => attribute.Name, StringComparer.OrdinalIgnoreCase);
-
- foreach (var rule in descriptor.TagMatchingRules)
- {
- foreach (var requiredAttribute in rule.Attributes)
- {
- if (htmlNameToBoundAttribute.TryGetValue(requiredAttribute.Name, out var attributeDescriptor))
- {
- UpdateCompletions(requiredAttribute.Name, attributeDescriptor);
- }
- else
- {
- UpdateCompletions(requiredAttribute.Name, possibleDescriptor: null);
- }
- }
- }
- }
- }
-
- var completionResult = AttributeCompletionResult.Create(attributeCompletions);
- return completionResult;
-
- void UpdateCompletions(string attributeName, BoundAttributeDescriptor possibleDescriptor)
- {
- if (completionContext.Attributes.Any(attribute => string.Equals(attribute.Key, attributeName, StringComparison.OrdinalIgnoreCase)))
- {
- // Attribute is already present on this element it shouldn't exist in the completion list.
- return;
- }
-
- if (!attributeCompletions.TryGetValue(attributeName, out var rules))
- {
- rules = new HashSet();
- attributeCompletions[attributeName] = rules;
- }
-
- if (possibleDescriptor != null)
- {
- rules.Add(possibleDescriptor);
- }
- }
- }
-
- public override ElementCompletionResult GetElementCompletions(ElementCompletionContext completionContext)
- {
- if (completionContext == null)
- {
- throw new ArgumentNullException(nameof(completionContext));
- }
-
- var elementCompletions = new Dictionary>(StringComparer.OrdinalIgnoreCase);
-
- AddAllowedChildrenCompletions(completionContext, elementCompletions);
-
- if (elementCompletions.Count > 0)
- {
- // If the containing element is already a TagHelper and only allows certain children.
- var emptyResult = ElementCompletionResult.Create(elementCompletions);
- return emptyResult;
- }
-
- elementCompletions = completionContext.ExistingCompletions.ToDictionary(
- completion => completion,
- _ => new HashSet(),
- StringComparer.OrdinalIgnoreCase);
-
- var catchAllDescriptors = new HashSet();
- var prefix = completionContext.DocumentContext.Prefix ?? string.Empty;
- var possibleChildDescriptors = _tagHelperFactsService.GetTagHelpersGivenParent(completionContext.DocumentContext, completionContext.ContainingTagName);
- foreach (var possibleDescriptor in possibleChildDescriptors)
- {
- var addRuleCompletions = false;
- var outputHint = possibleDescriptor.TagOutputHint;
-
- foreach (var rule in possibleDescriptor.TagMatchingRules)
- {
- if (rule.TagName == TagHelperMatchingConventions.ElementCatchAllName)
- {
- catchAllDescriptors.Add(possibleDescriptor);
- }
- else if (elementCompletions.ContainsKey(rule.TagName))
- {
- addRuleCompletions = true;
- }
- else if (outputHint != null)
- {
- // If the current descriptor has an output hint we need to make sure it shows up only when its output hint would normally show up.
- // Example: We have a MyTableTagHelper that has an output hint of "table" and a MyTrTagHelper that has an output hint of "tr".
- // If we try typing in a situation like this: |
- // We'd expect to only get "my-table" as a completion because the "body" tag doesn't allow "tr" tags.
- addRuleCompletions = elementCompletions.ContainsKey(outputHint);
- }
- else if (!completionContext.InHTMLSchema(rule.TagName))
- {
- // If there is an unknown HTML schema tag that doesn't exist in the current completion we should add it. This happens for
- // TagHelpers that target non-schema oriented tags.
- addRuleCompletions = true;
- }
-
- if (addRuleCompletions)
- {
- UpdateCompletions(prefix + rule.TagName, possibleDescriptor);
- }
- }
- }
-
- // We needed to track all catch-alls and update their completions after all other completions have been completed.
- // This way, any TagHelper added completions will also have catch-alls listed under their entries.
- foreach (var catchAllDescriptor in catchAllDescriptors)
- {
- foreach (var completionTagName in elementCompletions.Keys)
- {
- if (elementCompletions[completionTagName].Count > 0 ||
- !string.IsNullOrEmpty(prefix) && completionTagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
- {
- // The current completion either has other TagHelper's associated with it or is prefixed with a non-empty
- // TagHelper prefix.
- UpdateCompletions(completionTagName, catchAllDescriptor);
- }
- }
- }
-
- var result = ElementCompletionResult.Create(elementCompletions);
- return result;
-
- void UpdateCompletions(string tagName, TagHelperDescriptor possibleDescriptor)
- {
- if (!elementCompletions.TryGetValue(tagName, out var existingRuleDescriptors))
- {
- existingRuleDescriptors = new HashSet();
- elementCompletions[tagName] = existingRuleDescriptors;
- }
-
- existingRuleDescriptors.Add(possibleDescriptor);
- }
- }
-
- private void AddAllowedChildrenCompletions(
- ElementCompletionContext completionContext,
- Dictionary> elementCompletions)
- {
- if (completionContext.ContainingTagName == null)
- {
- // If we're at the root then there's no containing TagHelper to specify allowed children.
- return;
- }
-
- var prefix = completionContext.DocumentContext.Prefix ?? string.Empty;
- var binding = _tagHelperFactsService.GetTagHelperBinding(
- completionContext.DocumentContext,
- completionContext.ContainingTagName,
- completionContext.Attributes,
- completionContext.ContainingParentTagName);
-
- if (binding == null)
- {
- // Containing tag is not a TagHelper; therefore, it allows any children.
- return;
- }
-
- foreach (var descriptor in binding.Descriptors)
- {
- foreach (var childTag in descriptor.AllowedChildTags)
- {
- var prefixedName = string.Concat(prefix, childTag.Name);
- var descriptors = _tagHelperFactsService.GetTagHelpersGivenTag(
- completionContext.DocumentContext,
- prefixedName,
- completionContext.ContainingTagName);
-
- if (descriptors.Count == 0)
- {
- if (!elementCompletions.ContainsKey(prefixedName))
- {
- elementCompletions[prefixedName] = _emptyHashSet;
- }
-
- continue;
- }
-
- if (!elementCompletions.TryGetValue(prefixedName, out var existingRuleDescriptors))
- {
- existingRuleDescriptors = new HashSet();
- elementCompletions[prefixedName] = existingRuleDescriptors;
- }
-
- existingRuleDescriptors.UnionWith(descriptors);
- }
- }
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperFactsService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperFactsService.cs
deleted file mode 100644
index 8e0b34b431..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DefaultTagHelperFactsService.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-// 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 System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Linq;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- [Export(typeof(TagHelperFactsService))]
- internal class DefaultTagHelperFactsService : TagHelperFactsService
- {
- public override TagHelperBinding GetTagHelperBinding(
- TagHelperDocumentContext documentContext,
- string tagName,
- IEnumerable> attributes,
- string parentTag)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- if (tagName == null)
- {
- throw new ArgumentNullException(nameof(tagName));
- }
-
- if (attributes == null)
- {
- throw new ArgumentNullException(nameof(attributes));
- }
-
- var descriptors = documentContext.TagHelpers;
- if (descriptors == null || descriptors.Count == 0)
- {
- return null;
- }
-
- var prefix = documentContext.Prefix;
- var tagHelperBinder = new TagHelperBinder(prefix, descriptors);
- var binding = tagHelperBinder.GetBinding(tagName, attributes.ToList(), parentTag, parentIsTagHelper: false);
-
- return binding;
- }
-
- public override IEnumerable GetBoundTagHelperAttributes(
- TagHelperDocumentContext documentContext,
- string attributeName,
- TagHelperBinding binding)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- if (attributeName == null)
- {
- throw new ArgumentNullException(nameof(attributeName));
- }
-
- if (binding == null)
- {
- throw new ArgumentNullException(nameof(binding));
- }
-
- var matchingBoundAttributes = new List();
- foreach (var descriptor in binding.Descriptors)
- {
- foreach (var boundAttributeDescriptor in descriptor.BoundAttributes)
- {
- if (TagHelperMatchingConventions.CanSatisfyBoundAttribute(attributeName, boundAttributeDescriptor))
- {
- matchingBoundAttributes.Add(boundAttributeDescriptor);
-
- // Only one bound attribute can match an attribute
- break;
- }
- }
- }
-
- return matchingBoundAttributes;
- }
-
- public override IReadOnlyList GetTagHelpersGivenTag(
- TagHelperDocumentContext documentContext,
- string tagName,
- string parentTag)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- if (tagName == null)
- {
- throw new ArgumentNullException(nameof(tagName));
- }
-
- var matchingDescriptors = new List();
- var descriptors = documentContext?.TagHelpers;
- if (descriptors?.Count == 0)
- {
- return matchingDescriptors;
- }
-
- var prefix = documentContext.Prefix ?? string.Empty;
- if (!tagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
- {
- // Can't possibly match TagHelpers, it doesn't start with the TagHelperPrefix.
- return matchingDescriptors;
- }
-
- var tagNameWithoutPrefix = tagName.Substring(prefix.Length);
- for (var i = 0; i < descriptors.Count; i++)
- {
- var descriptor = descriptors[i];
- foreach (var rule in descriptor.TagMatchingRules)
- {
- if (TagHelperMatchingConventions.SatisfiesTagName(tagNameWithoutPrefix, rule) &&
- TagHelperMatchingConventions.SatisfiesParentTag(parentTag, rule))
- {
- matchingDescriptors.Add(descriptor);
- break;
- }
- }
- }
-
- return matchingDescriptors;
- }
-
- public override IReadOnlyList GetTagHelpersGivenParent(TagHelperDocumentContext documentContext, string parentTag)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- var matchingDescriptors = new List();
- var descriptors = documentContext?.TagHelpers;
- if (descriptors?.Count == 0)
- {
- return matchingDescriptors;
- }
-
- for (var i = 0; i < descriptors.Count; i++)
- {
- var descriptor = descriptors[i];
- foreach (var rule in descriptor.TagMatchingRules)
- {
- if (TagHelperMatchingConventions.SatisfiesParentTag(parentTag, rule))
- {
- matchingDescriptors.Add(descriptor);
- break;
- }
- }
- }
-
- return matchingDescriptors;
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DocumentParseCompleteEventArgs.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DocumentParseCompleteEventArgs.cs
deleted file mode 100644
index c8dc5065c8..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/DocumentParseCompleteEventArgs.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.VisualStudio.Text;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- ///
- /// Arguments for the event in .
- ///
- public sealed class DocumentParseCompleteEventArgs : EventArgs
- {
- public DocumentParseCompleteEventArgs(
- SourceChange change,
- ITextSnapshot buffer,
- bool treeStructureChanged,
- RazorCodeDocument codeDocument)
- {
- SourceChange = change;
- Buffer = buffer;
- TreeStructureChanged = treeStructureChanged;
- CodeDocument = codeDocument;
- }
-
- ///
- /// The which triggered the re-parse.
- ///
- public SourceChange SourceChange { get; }
-
- ///
- /// The text snapshot used in the re-parse.
- ///
- public ITextSnapshot Buffer { get; }
-
- ///
- /// Indicates if the tree structure has actually changed since the previous re-parse.
- ///
- public bool TreeStructureChanged { get; }
-
- ///
- /// The result of the parsing and code generation.
- ///
- public RazorCodeDocument CodeDocument { get; }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionContext.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionContext.cs
deleted file mode 100644
index c38c8485c7..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionContext.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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 System.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public sealed class ElementCompletionContext
- {
- public ElementCompletionContext(
- TagHelperDocumentContext documentContext,
- IEnumerable existingCompletions,
- string containingTagName,
- IEnumerable> attributes,
- string containingParentTagName,
- Func inHTMLSchema)
- {
- if (documentContext == null)
- {
- throw new ArgumentNullException(nameof(documentContext));
- }
-
- if (existingCompletions == null)
- {
- throw new ArgumentNullException(nameof(existingCompletions));
- }
-
- if (inHTMLSchema == null)
- {
- throw new ArgumentNullException(nameof(inHTMLSchema));
- }
-
- DocumentContext = documentContext;
- ExistingCompletions = existingCompletions;
- ContainingTagName = containingTagName;
- Attributes = attributes;
- ContainingParentTagName = containingParentTagName;
- InHTMLSchema = inHTMLSchema;
- }
-
- public TagHelperDocumentContext DocumentContext { get; }
-
- public IEnumerable ExistingCompletions { get; }
-
- public string ContainingTagName { get; }
-
- public IEnumerable> Attributes { get; }
-
- public string ContainingParentTagName { get; }
-
- public Func InHTMLSchema { get; }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionResult.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionResult.cs
deleted file mode 100644
index 88dc0c6a56..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ElementCompletionResult.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.Collections.Generic;
-using System.Linq;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class ElementCompletionResult
- {
- private ElementCompletionResult()
- {
- }
-
- public abstract IReadOnlyDictionary> Completions { get; }
-
- internal static ElementCompletionResult Create(Dictionary> completions)
- {
- var readonlyCompletions = completions.ToDictionary(
- key => key.Key,
- value => (IEnumerable)value.Value,
- completions.Comparer);
- var result = new DefaultElementCompletionResult(readonlyCompletions);
-
- return result;
- }
-
- private class DefaultElementCompletionResult : ElementCompletionResult
- {
- private readonly IReadOnlyDictionary> _completions;
-
- public DefaultElementCompletionResult(IReadOnlyDictionary> completions)
- {
- _completions = completions;
- }
-
- public override IReadOnlyDictionary> Completions => _completions;
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ITagHelperResolver.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ITagHelperResolver.cs
deleted file mode 100644
index 80c2502714..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/ITagHelperResolver.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Razor;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public interface ITagHelperResolver
- {
- Task GetTagHelpersAsync(Project project);
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTagHelperResolver.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTagHelperResolver.cs
deleted file mode 100644
index a646026ba1..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTagHelperResolver.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.ComponentModel.Composition;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Razor;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use TagHelperResolver.
- // ----------------------------------------------------------------------------------------------------
- [Export(typeof(ITagHelperResolver))]
- internal class LegacyTagHelperResolver : DefaultTagHelperResolver, ITagHelperResolver
- {
- [ImportingConstructor]
- public LegacyTagHelperResolver(
- [Import(typeof(VisualStudioWorkspace))] Workspace workspace)
- : base(workspace.Services.GetRequiredService(), workspace)
- {
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTemplateEngineFactoryService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTemplateEngineFactoryService.cs
deleted file mode 100644
index fcae83b4ec..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTemplateEngineFactoryService.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 System.ComponentModel.Composition;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Razor;
-using Inner = Microsoft.CodeAnalysis.Razor.RazorTemplateEngineFactoryService;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use DefaultTemplateEngineFactoryService.
- // ----------------------------------------------------------------------------------------------------
- [Export(typeof(RazorTemplateEngineFactoryService))]
- internal class LegacyTemplateEngineFactoryService : RazorTemplateEngineFactoryService
- {
- private readonly Inner _inner;
- private readonly Workspace _workspace;
-
- [ImportingConstructor]
- public LegacyTemplateEngineFactoryService([Import(typeof(VisualStudioWorkspace))] Workspace workspace)
- {
- if (workspace == null)
- {
- throw new ArgumentNullException(nameof(workspace));
- }
-
- _workspace = workspace;
- _inner = workspace.Services.GetLanguageServices(RazorLanguage.Name).GetRequiredService();
- }
-
- // internal for testing
- internal LegacyTemplateEngineFactoryService(Workspace workspace, Inner inner)
- {
- if (workspace == null)
- {
- throw new ArgumentNullException(nameof(workspace));
- }
-
- if (inner == null)
- {
- throw new ArgumentNullException(nameof(inner));
- }
-
- _workspace = workspace;
- _inner = inner;
- }
-
- public override RazorTemplateEngine Create(string projectPath, Action configure)
- {
- if (projectPath == null)
- {
- throw new ArgumentNullException(nameof(projectPath));
- }
-
- return _inner.Create(projectPath, configure);
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTextBufferCodeDocumentProvider.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTextBufferCodeDocumentProvider.cs
deleted file mode 100644
index 963dfc9fe8..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/LegacyTextBufferCodeDocumentProvider.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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 System.ComponentModel.Composition;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.VisualStudio.Editor.Razor;
-using Microsoft.VisualStudio.Text;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
-{
- [System.Composition.Shared]
- [Export(typeof(TextBufferCodeDocumentProvider))]
- internal class LegacyTextBufferCodeDocumentProvider : TextBufferCodeDocumentProvider
- {
- public override bool TryGetFromBuffer(ITextBuffer textBuffer, out RazorCodeDocument codeDocument)
- {
- if (textBuffer == null)
- {
- throw new ArgumentNullException(nameof(textBuffer));
- }
-
- if (textBuffer.Properties.TryGetProperty(typeof(VisualStudioRazorParser), out VisualStudioRazorParser parser) && parser.CodeDocument != null)
- {
- codeDocument = parser.CodeDocument;
- return true;
- }
-
- // Support the legacy parser for code document extraction.
- if (textBuffer.Properties.TryGetProperty(typeof(RazorEditorParser), out RazorEditorParser legacyParser) && legacyParser.CodeDocument != null)
- {
- codeDocument = legacyParser.CodeDocument;
- return true;
- }
-
- codeDocument = null;
- return false;
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/PartialParseResult.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/PartialParseResult.cs
deleted file mode 100644
index 2571342f69..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/PartialParseResult.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- [Flags]
- public enum PartialParseResult
- {
- Rejected = 1,
-
- Accepted = 2,
-
- Provisional = 4,
-
- SpanContextChanged = 8,
-
- AutoCompleteBlock = 16
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorEditorParser.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorEditorParser.cs
deleted file mode 100644
index de7fbc9977..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorEditorParser.cs
+++ /dev/null
@@ -1,623 +0,0 @@
-// 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 System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Legacy;
-using Microsoft.VisualStudio.Editor.Razor;
-using Microsoft.VisualStudio.Text;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- public class RazorEditorParser : IDisposable
- {
- private RazorTemplateEngine _templateEngine;
-
- private AspNetCore.Razor.Language.Legacy.Span _lastChangeOwner;
- private AspNetCore.Razor.Language.Legacy.Span _lastAutoCompleteSpan;
- private BackgroundParser _parser;
-
- // For testing only.
- internal RazorEditorParser(RazorCodeDocument codeDocument)
- {
- CodeDocument = codeDocument;
- }
-
- public RazorEditorParser(RazorTemplateEngine templateEngine, string filePath)
- {
- if (templateEngine == null)
- {
- throw new ArgumentNullException(nameof(templateEngine));
- }
-
- if (string.IsNullOrEmpty(filePath))
- {
- throw new ArgumentException(
- AspNetCore.Razor.Language.Resources.ArgumentCannotBeNullOrEmpty,
- nameof(filePath));
- }
-
- TemplateEngine = templateEngine;
- FilePath = filePath;
- _parser = new BackgroundParser(this, filePath);
- _parser.ResultsReady += (sender, args) => OnDocumentParseComplete(args);
- _parser.Start();
- }
-
- ///
- /// Event fired when a full reparse of the document completes.
- ///
- public event EventHandler DocumentParseComplete;
-
- public RazorTemplateEngine TemplateEngine
- {
- get => _templateEngine;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- _templateEngine = value;
- }
- }
-
- public string FilePath { get; }
-
- // Internal for testing.
- internal RazorSyntaxTree CurrentSyntaxTree { get; private set; }
-
- internal RazorCodeDocument CodeDocument { get; private set; }
-
- // Internal for testing.
- internal bool LastResultProvisional { get; private set; }
-
- public virtual string GetAutoCompleteString()
- {
- if (_lastAutoCompleteSpan?.EditHandler is AutoCompleteEditHandler editHandler)
- {
- return editHandler.AutoCompleteString;
- }
-
- return null;
- }
-
- public virtual PartialParseResult CheckForStructureChanges(SourceChange change, ITextSnapshot snapshot)
- {
- if (snapshot == null)
- {
- throw new ArgumentNullException(nameof(snapshot));
- }
-
- var result = PartialParseResultInternal.Rejected;
-
- using (_parser.SynchronizeMainThreadState())
- {
- // Check if we can partial-parse
- if (CurrentSyntaxTree != null && _parser.IsIdle)
- {
- result = TryPartialParse(change);
- }
- }
-
- // If partial parsing failed or there were outstanding parser tasks, start a full reparse
- if ((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected)
- {
- _parser.QueueChange(change, snapshot);
- }
-
- // Otherwise, remember if this was provisionally accepted for next partial parse
- LastResultProvisional = (result & PartialParseResultInternal.Provisional) == PartialParseResultInternal.Provisional;
- VerifyFlagsAreValid(result);
-
- return (PartialParseResult)result;
- }
-
- ///
- /// Disposes of this parser. Should be called when the editor window is closed and the document is unloaded.
- ///
- public void Dispose()
- {
- _parser.Dispose();
- GC.SuppressFinalize(this);
- }
-
- private PartialParseResultInternal TryPartialParse(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 = CurrentSyntaxTree.Root.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);
- }
- if ((result & PartialParseResultInternal.AutoCompleteBlock) == PartialParseResultInternal.AutoCompleteBlock)
- {
- _lastAutoCompleteSpan = _lastChangeOwner;
- }
- else
- {
- _lastAutoCompleteSpan = null;
- }
- }
-
- return result;
- }
-
- private void OnDocumentParseComplete(DocumentParseCompleteEventArgs args)
- {
- using (_parser.SynchronizeMainThreadState())
- {
- CurrentSyntaxTree = args.CodeDocument.GetSyntaxTree();
- CodeDocument = args.CodeDocument;
- _lastChangeOwner = null;
- }
-
- Debug.Assert(args != null, "Event arguments cannot be null");
- EventHandler handler = DocumentParseComplete;
- if (handler != null)
- {
- try
- {
- handler(this, args);
- }
- catch (Exception ex)
- {
- Debug.WriteLine("[RzEd] Document Parse Complete Handler Threw: " + ex.ToString());
- }
- }
- }
-
- [Conditional("DEBUG")]
- private static void VerifyFlagsAreValid(PartialParseResultInternal result)
- {
- Debug.Assert(((result & PartialParseResultInternal.Accepted) == PartialParseResultInternal.Accepted) ||
- ((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected),
- "Partial Parse result does not have either of Accepted or Rejected flags set");
- Debug.Assert(((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected) ||
- ((result & PartialParseResultInternal.SpanContextChanged) != PartialParseResultInternal.SpanContextChanged),
- "Partial Parse result was Accepted AND had SpanContextChanged flag set");
- Debug.Assert(((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected) ||
- ((result & PartialParseResultInternal.AutoCompleteBlock) != PartialParseResultInternal.AutoCompleteBlock),
- "Partial Parse result was Accepted AND had AutoCompleteBlock flag set");
- Debug.Assert(((result & PartialParseResultInternal.Accepted) == PartialParseResultInternal.Accepted) ||
- ((result & PartialParseResultInternal.Provisional) != PartialParseResultInternal.Provisional),
- "Partial Parse result was Rejected AND had Provisional flag set");
- }
-
- internal class BackgroundParser : IDisposable
- {
- private MainThreadState _main;
- private BackgroundThread _bg;
-
- public BackgroundParser(RazorEditorParser parser, string filePath)
- {
- _main = new MainThreadState(filePath);
- _bg = new BackgroundThread(_main, parser, filePath);
-
- _main.ResultsReady += (sender, args) => OnResultsReady(args);
- }
-
- ///
- /// Fired on the main thread.
- ///
- public event EventHandler ResultsReady;
-
- public bool IsIdle
- {
- get { return _main.IsIdle; }
- }
-
- public void Start()
- {
- _bg.Start();
- }
-
- public void Cancel()
- {
- _main.Cancel();
- }
-
- public void QueueChange(SourceChange change, ITextSnapshot snapshot)
- {
- var edit = new Edit(change, snapshot);
- _main.QueueChange(edit);
- }
-
- public void Dispose()
- {
- _main.Cancel();
- }
-
- public IDisposable SynchronizeMainThreadState()
- {
- return _main.Lock();
- }
-
- protected virtual void OnResultsReady(DocumentParseCompleteEventArgs args)
- {
- var handler = ResultsReady;
- if (handler != null)
- {
- handler(this, args);
- }
- }
-
- private static bool TreesAreDifferent(RazorSyntaxTree leftTree, RazorSyntaxTree rightTree, IEnumerable edits, CancellationToken cancelToken)
- {
- return TreesAreDifferent(leftTree.Root, rightTree.Root, edits.Select(edit => edit.Change), cancelToken);
- }
-
- internal static bool TreesAreDifferent(Block leftTree, Block rightTree, IEnumerable changes, CancellationToken cancelToken)
- {
- // Apply all the pending changes to the original tree
- // PERF: If this becomes a bottleneck, we can probably do it the other way around,
- // i.e. visit the tree and find applicable changes for each node.
- foreach (var change in changes)
- {
- cancelToken.ThrowIfCancellationRequested();
-
- var changeOwner = leftTree.LocateOwner(change);
-
- // Apply the change to the tree
- if (changeOwner == null)
- {
- return true;
- }
-
- var result = changeOwner.EditHandler.ApplyChange(changeOwner, change, force: true);
- changeOwner.ReplaceWith(result.EditedSpan);
- }
-
- // Now compare the trees
- var treesDifferent = !leftTree.EquivalentTo(rightTree);
- return treesDifferent;
- }
-
- private abstract class ThreadStateBase
- {
-#if DEBUG
- private int _id = -1;
-#endif
- protected ThreadStateBase()
- {
- }
-
- [Conditional("DEBUG")]
- protected void SetThreadId(int id)
- {
-#if DEBUG
- _id = id;
-#endif
- }
-
- [Conditional("DEBUG")]
- protected void EnsureOnThread()
- {
-#if DEBUG
- Debug.Assert(_id != -1, "SetThreadId was never called!");
- Debug.Assert(Thread.CurrentThread.ManagedThreadId == _id, "Called from an unexpected thread!");
-#endif
- }
-
- [Conditional("DEBUG")]
- protected void EnsureNotOnThread()
- {
-#if DEBUG
- Debug.Assert(_id != -1, "SetThreadId was never called!");
- Debug.Assert(Thread.CurrentThread.ManagedThreadId != _id, "Called from an unexpected thread!");
-#endif
- }
- }
-
- private class MainThreadState : ThreadStateBase, IDisposable
- {
- private readonly CancellationTokenSource _cancelSource = new CancellationTokenSource();
- private readonly ManualResetEventSlim _hasParcel = new ManualResetEventSlim(false);
- private CancellationTokenSource _currentParcelCancelSource;
-
- private string _fileName;
- private readonly object _stateLock = new object();
- private IList _changes = new List();
-
- public MainThreadState(string fileName)
- {
- _fileName = fileName;
-
- SetThreadId(Thread.CurrentThread.ManagedThreadId);
- }
-
- public event EventHandler ResultsReady;
-
- public CancellationToken CancelToken
- {
- get { return _cancelSource.Token; }
- }
-
- public bool IsIdle
- {
- get
- {
- lock (_stateLock)
- {
- return _currentParcelCancelSource == null;
- }
- }
- }
-
- public void Cancel()
- {
- EnsureOnThread();
- _cancelSource.Cancel();
- }
-
- public IDisposable Lock()
- {
- Monitor.Enter(_stateLock);
- return new DisposableAction(() => Monitor.Exit(_stateLock));
- }
-
- public void QueueChange(Edit edit)
- {
- EnsureOnThread();
- lock (_stateLock)
- {
- // CurrentParcel token source is not null ==> There's a parse underway
- if (_currentParcelCancelSource != null)
- {
- _currentParcelCancelSource.Cancel();
- }
-
- _changes.Add(edit);
- _hasParcel.Set();
- }
- }
-
- public WorkParcel GetParcel()
- {
- EnsureNotOnThread(); // Only the background thread can get a parcel
- _hasParcel.Wait(_cancelSource.Token);
- _hasParcel.Reset();
- lock (_stateLock)
- {
- // Create a cancellation source for this parcel
- _currentParcelCancelSource = new CancellationTokenSource();
-
- var changes = _changes;
- _changes = new List();
- return new WorkParcel(changes, _currentParcelCancelSource.Token);
- }
- }
-
- public void ReturnParcel(DocumentParseCompleteEventArgs args)
- {
- lock (_stateLock)
- {
- // Clear the current parcel cancellation source
- if (_currentParcelCancelSource != null)
- {
- _currentParcelCancelSource.Dispose();
- _currentParcelCancelSource = null;
- }
-
- // If there are things waiting to be parsed, just don't fire the event because we're already out of date
- if (_changes.Any())
- {
- return;
- }
- }
- var handler = ResultsReady;
- if (handler != null)
- {
- handler(this, args);
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_currentParcelCancelSource != null)
- {
- _currentParcelCancelSource.Dispose();
- _currentParcelCancelSource = null;
- }
- _cancelSource.Dispose();
- _hasParcel.Dispose();
- }
- }
- }
-
- private class BackgroundThread : ThreadStateBase
- {
- private MainThreadState _main;
- private Thread _backgroundThread;
- private CancellationToken _shutdownToken;
- private RazorEditorParser _parser;
- private string _filePath;
- private RazorSyntaxTree _currentSyntaxTree;
- private IList _previouslyDiscarded = new List();
-
- public BackgroundThread(MainThreadState main, RazorEditorParser parser, string fileName)
- {
- // Run on MAIN thread!
- _main = main;
- _shutdownToken = _main.CancelToken;
- _parser = parser;
- _filePath = fileName;
-
- _backgroundThread = new Thread(WorkerLoop);
- SetThreadId(_backgroundThread.ManagedThreadId);
- }
-
- // **** ANY THREAD ****
- public void Start()
- {
- _backgroundThread.Start();
- }
-
- // **** BACKGROUND THREAD ****
- private void WorkerLoop()
- {
- var fileNameOnly = Path.GetFileName(_filePath);
-
- try
- {
- EnsureOnThread();
-
- while (!_shutdownToken.IsCancellationRequested)
- {
- // Grab the parcel of work to do
- var parcel = _main.GetParcel();
- if (parcel.Edits.Any())
- {
- try
- {
- DocumentParseCompleteEventArgs args = null;
- using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken))
- {
- if (!linkedCancel.IsCancellationRequested)
- {
- // Collect ALL changes
- List allEdits;
-
- if (_previouslyDiscarded != null)
- {
- allEdits = Enumerable.Concat(_previouslyDiscarded, parcel.Edits).ToList();
- }
- else
- {
- allEdits = parcel.Edits.ToList();
- }
-
- var finalEdit = allEdits.Last();
-
- var results = ParseChange(finalEdit.Snapshot, linkedCancel.Token);
-
- if (results != null && !linkedCancel.IsCancellationRequested)
- {
- // Clear discarded changes list
- _previouslyDiscarded = null;
-
- var treeStructureChanged = _currentSyntaxTree == null || TreesAreDifferent(_currentSyntaxTree, results.GetSyntaxTree(), allEdits, parcel.CancelToken);
- _currentSyntaxTree = results.GetSyntaxTree();
-
- // Build Arguments
- args = new DocumentParseCompleteEventArgs(
- finalEdit.Change,
- finalEdit.Snapshot,
- treeStructureChanged,
- results);
- }
- else
- {
- // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set
- _previouslyDiscarded = allEdits;
- }
- }
- }
- if (args != null)
- {
- _main.ReturnParcel(args);
- }
- }
- catch (OperationCanceledException)
- {
- }
- }
- else
- {
- Thread.Yield();
- }
- }
- }
- catch (OperationCanceledException)
- {
- // Do nothing. Just shut down.
- }
- finally
- {
- // Clean up main thread resources
- _main.Dispose();
- }
- }
-
- private RazorCodeDocument ParseChange(ITextSnapshot snapshot, CancellationToken token)
- {
- EnsureOnThread();
-
- var templateEngine = _parser.TemplateEngine;
- var sourceDocument = new TextSnapshotSourceDocument(snapshot, _filePath);
- var imports = templateEngine.GetImports(_filePath);
-
- var codeDocument = RazorCodeDocument.Create(sourceDocument, imports);
-
- templateEngine.GenerateCode(codeDocument);
- return codeDocument;
- }
- }
-
- private class WorkParcel
- {
- public WorkParcel(IList changes, CancellationToken cancelToken)
- {
- Edits = changes;
- CancelToken = cancelToken;
- }
-
- public CancellationToken CancelToken { get; }
-
- public IList Edits { get; }
- }
-
- private class Edit
- {
- public Edit(SourceChange change, ITextSnapshot snapshot)
- {
- Change = change;
- Snapshot = snapshot;
- }
-
- public SourceChange Change { get; }
-
- public ITextSnapshot Snapshot { get; set; }
- }
- }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorSyntaxFactsService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorSyntaxFactsService.cs
deleted file mode 100644
index 6b187680e9..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorSyntaxFactsService.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.VisualStudio.Text;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class RazorSyntaxFactsService
- {
- public abstract IReadOnlyList GetClassifiedSpans(RazorSyntaxTree syntaxTree);
-
- public abstract IReadOnlyList GetTagHelperSpans(RazorSyntaxTree syntaxTree);
-
- public abstract int? GetDesiredIndentation(RazorSyntaxTree syntaxTree, ITextSnapshot syntaxTreeSnapshot, ITextSnapshotLine line, int indentSize, int tabSize);
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorTemplateEngineFactoryService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorTemplateEngineFactoryService.cs
deleted file mode 100644
index 784437df22..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/RazorTemplateEngineFactoryService.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class RazorTemplateEngineFactoryService
- {
- public abstract RazorTemplateEngine Create(string projectPath, Action configure);
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/SpanKind.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/SpanKind.cs
deleted file mode 100644
index d557849f6d..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/SpanKind.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public enum SpanKind
- {
- Transition,
- MetaCode,
- Comment,
- Code,
- Markup
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperCompletionService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperCompletionService.cs
deleted file mode 100644
index 78f3e4b821..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperCompletionService.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class TagHelperCompletionService
- {
- public abstract AttributeCompletionResult GetAttributeCompletions(AttributeCompletionContext completionContext);
-
- public abstract ElementCompletionResult GetElementCompletions(ElementCompletionContext completionContext);
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperFactsService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperFactsService.cs
deleted file mode 100644
index 5fca65c218..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperFactsService.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public abstract class TagHelperFactsService
- {
- public abstract TagHelperBinding GetTagHelperBinding(TagHelperDocumentContext documentContext, string tagName, IEnumerable> attributes, string parentTag);
-
- public abstract IEnumerable GetBoundTagHelperAttributes(TagHelperDocumentContext documentContext, string attributeName, TagHelperBinding binding);
-
- public abstract IReadOnlyList GetTagHelpersGivenTag(TagHelperDocumentContext documentContext, string tagName, string parentTag);
-
- public abstract IReadOnlyList GetTagHelpersGivenParent(TagHelperDocumentContext documentContext, string parentTag);
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperSpan.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperSpan.cs
deleted file mode 100644
index 337234f3d0..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Legacy/TagHelperSpan.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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 System.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- // ----------------------------------------------------------------------------------------------------
- // NOTE: This is only here for VisualStudio binary compatibility. This type should not be used; instead
- // use the Microsoft.CodeAnalysis.Razor variant from Microsoft.CodeAnalysis.Razor.Workspaces
- // ----------------------------------------------------------------------------------------------------
- public struct TagHelperSpan
- {
- public TagHelperSpan(SourceSpan span, TagHelperBinding binding)
- {
- if (binding == null)
- {
- throw new ArgumentNullException(nameof(binding));
- }
-
- Span = span;
- Binding = binding;
- }
-
- public TagHelperBinding Binding { get; }
-
- public IEnumerable TagHelpers => Binding.Descriptors;
-
- public SourceSpan Span { get; }
- }
-}
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorDiagnosticJsonConverter.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorDiagnosticJsonConverter.cs
index 96db50dc92..d9d4d966e1 100644
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorDiagnosticJsonConverter.cs
+++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorDiagnosticJsonConverter.cs
@@ -9,7 +9,7 @@ using Newtonsoft.Json.Linq;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
- public class RazorDiagnosticJsonConverter : JsonConverter
+ internal class RazorDiagnosticJsonConverter : JsonConverter
{
public static readonly RazorDiagnosticJsonConverter Instance = new RazorDiagnosticJsonConverter();
private const string RazorDiagnosticMessageKey = "Message";
diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLanguageServiceException.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLanguageServiceException.cs
deleted file mode 100644
index 80c5d88a61..0000000000
--- a/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLanguageServiceException.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- public sealed class RazorLanguageServiceException : Exception
- {
- internal RazorLanguageServiceException(string callerClass, string callerMethod, Exception innerException)
- : base(Resources.FormatUnexpectedException(callerClass, callerMethod), innerException)
- {
- }
- }
-}
diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/LegacyTextBufferCodeDocumentProviderTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/LegacyTextBufferCodeDocumentProviderTest.cs
deleted file mode 100644
index 4127851928..0000000000
--- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/LegacyTextBufferCodeDocumentProviderTest.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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 Microsoft.AspNetCore.Razor.Language;
-using Microsoft.VisualStudio.Editor.Razor;
-using Microsoft.VisualStudio.Text;
-using Microsoft.VisualStudio.Utilities;
-using Moq;
-using Xunit;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
-{
- public class LegacyTextBufferCodeDocumentProviderTest
- {
- [Fact]
- public void TryGetFromBuffer_UsesVisualStudioRazorParserIfAvailable()
- {
- // Arrange
- var expectedCodeDocument = TestRazorCodeDocument.Create("Hello World");
- var parser = new DefaultVisualStudioRazorParser(expectedCodeDocument);
- var properties = new PropertyCollection();
- properties.AddProperty(typeof(VisualStudioRazorParser), parser);
- var textBuffer = new Mock();
- textBuffer.Setup(buffer => buffer.Properties)
- .Returns(properties);
- var provider = new LegacyTextBufferCodeDocumentProvider();
-
- // Act
- var result = provider.TryGetFromBuffer(textBuffer.Object, out var codeDocument);
-
- // Assert
- Assert.True(result);
- Assert.Same(expectedCodeDocument, codeDocument);
- }
-
- [Fact]
- public void TryGetFromBuffer_UsesRazorEditorParserIfAvailable()
- {
- // Arrange
- var expectedCodeDocument = TestRazorCodeDocument.Create("Hello World");
- var parser = new RazorEditorParser(expectedCodeDocument);
- var properties = new PropertyCollection();
- properties.AddProperty(typeof(RazorEditorParser), parser);
- var textBuffer = new Mock();
- textBuffer.Setup(buffer => buffer.Properties)
- .Returns(properties);
- var provider = new LegacyTextBufferCodeDocumentProvider();
-
- // Act
- var result = provider.TryGetFromBuffer(textBuffer.Object, out var codeDocument);
-
- // Assert
- Assert.True(result);
- Assert.Same(expectedCodeDocument, codeDocument);
- }
-
- [Fact]
- public void TryGetFromBuffer_PrefersVisualStudioRazorParserIfRazorEditorParserIsAvailable()
- {
- // Arrange
- var properties = new PropertyCollection();
- var expectedCodeDocument = TestRazorCodeDocument.Create("Hello World");
- var parser = new DefaultVisualStudioRazorParser(expectedCodeDocument);
- properties.AddProperty(typeof(VisualStudioRazorParser), parser);
- var unexpectedCodeDocument = TestRazorCodeDocument.Create("Unexpected");
- var legacyParser = new RazorEditorParser(unexpectedCodeDocument);
- properties.AddProperty(typeof(RazorEditorParser), legacyParser);
- var textBuffer = new Mock();
- textBuffer.Setup(buffer => buffer.Properties)
- .Returns(properties);
- var provider = new LegacyTextBufferCodeDocumentProvider();
-
- // Act
- var result = provider.TryGetFromBuffer(textBuffer.Object, out var codeDocument);
-
- // Assert
- Assert.True(result);
- Assert.Same(expectedCodeDocument, codeDocument);
- }
-
- [Fact]
- public void TryGetFromBuffer_FailsIfNoParserIsAvailable()
- {
- // Arrange
- var properties = new PropertyCollection();
- var textBuffer = new Mock();
- textBuffer.Setup(buffer => buffer.Properties)
- .Returns(properties);
- var provider = new LegacyTextBufferCodeDocumentProvider();
-
- // Act
- var result = provider.TryGetFromBuffer(textBuffer.Object, out var codeDocument);
-
- // Assert
- Assert.False(result);
- Assert.Null(codeDocument);
- }
- }
-}
diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperCompletionServiceTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperCompletionServiceTest.cs
deleted file mode 100644
index 5d6ad363bc..0000000000
--- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperCompletionServiceTest.cs
+++ /dev/null
@@ -1,964 +0,0 @@
-// 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 Microsoft.AspNetCore.Razor.Language;
-using System.Collections.Generic;
-using System.Linq;
-using Xunit;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- public class DefaultTagHelperCompletionServiceTest
- {
- [Fact]
- public void GetAttributeCompletions_DoesNotReturnCompletionsForAlreadySuppliedAttributes()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("div")
- .RequireAttributeDescriptor(attribute => attribute.Name("repeat")))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("visible")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Visible"))
- .Build(),
- TagHelperDescriptorBuilder.Create("StyleTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("class")
- .TypeName(typeof(string).FullName)
- .PropertyName("Class"))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["onclick"] = new HashSet(),
- ["visible"] = new HashSet()
- {
- documentDescriptors[0].BoundAttributes.Last()
- }
- });
-
- var existingCompletions = new[] { "onclick" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- attributes: new Dictionary()
- {
- ["class"] = "something",
- ["repeat"] = "4"
- },
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_PossibleDescriptorsReturnUnboundRequiredAttributesWithExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("div")
- .RequireAttributeDescriptor(attribute => attribute.Name("repeat")))
- .Build(),
- TagHelperDescriptorBuilder.Create("StyleTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("*")
- .RequireAttributeDescriptor(attribute => attribute.Name("class")))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- ["onclick"] = new HashSet(),
- ["repeat"] = new HashSet()
- });
-
- var existingCompletions = new[] { "onclick", "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_PossibleDescriptorsReturnBoundRequiredAttributesWithExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("div")
- .RequireAttributeDescriptor(attribute => attribute.Name("repeat")))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("repeat")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Repeat"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("visible")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Visible"))
- .Build(),
- TagHelperDescriptorBuilder.Create("StyleTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("*")
- .RequireAttributeDescriptor(attribute => attribute.Name("class")))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("class")
- .TypeName(typeof(string).FullName)
- .PropertyName("Class"))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(documentDescriptors[1].BoundAttributes),
- ["onclick"] = new HashSet(),
- ["repeat"] = new HashSet()
- {
- documentDescriptors[0].BoundAttributes.First()
- }
- });
-
- var existingCompletions = new[] { "onclick" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_AppliedDescriptorsReturnAllBoundAttributesWithExistingCompletionsForSchemaTags()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("repeat")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Repeat"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("visible")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Visible"))
- .Build(),
- TagHelperDescriptorBuilder.Create("StyleTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("*")
- .RequireAttributeDescriptor(attribute => attribute.Name("class")))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("class")
- .TypeName(typeof(string).FullName)
- .PropertyName("Class"))
- .Build(),
- TagHelperDescriptorBuilder.Create("StyleTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("visible")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Visible"))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["onclick"] = new HashSet(),
- ["class"] = new HashSet(documentDescriptors[1].BoundAttributes),
- ["repeat"] = new HashSet()
- {
- documentDescriptors[0].BoundAttributes.First()
- },
- ["visible"] = new HashSet()
- {
- documentDescriptors[0].BoundAttributes.Last(),
- documentDescriptors[2].BoundAttributes.First(),
- }
- });
-
- var existingCompletions = new[] { "class", "onclick" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_AppliedTagOutputHintDescriptorsReturnBoundAttributesWithExistingCompletionsForNonSchemaTags()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("CustomTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("custom"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("repeat")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Repeat"))
- .TagOutputHint("div")
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- ["repeat"] = new HashSet(documentDescriptors[0].BoundAttributes)
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "custom");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_AppliedDescriptorsReturnBoundAttributesCompletionsForNonSchemaTags()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("CustomTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("custom"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("repeat")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Repeat"))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["repeat"] = new HashSet(documentDescriptors[0].BoundAttributes)
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "custom");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_AppliedDescriptorsReturnBoundAttributesWithExistingCompletionsForSchemaTags()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .BoundAttributeDescriptor(attribute => attribute
- .Name("repeat")
- .TypeName(typeof(bool).FullName)
- .PropertyName("Repeat"))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- ["repeat"] = new HashSet(documentDescriptors[0].BoundAttributes)
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_NoDescriptorsReturnsExistingCompletions()
- {
- // Arrange
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- Enumerable.Empty(),
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_NoDescriptorsForUnprefixedTagReturnsExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("div")
- .RequireAttributeDescriptor(attribute => attribute.Name("special")))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div",
- tagHelperPrefix: "th:");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetAttributeCompletions_NoDescriptorsForTagReturnsExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("MyTableTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("table")
- .RequireAttributeDescriptor(attribute => attribute.Name("special")))
- .Build(),
- };
- var expectedCompletions = AttributeCompletionResult.Create(new Dictionary>()
- {
- ["class"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "class" };
- var completionContext = BuildAttributeCompletionContext(
- documentDescriptors,
- existingCompletions,
- currentTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetAttributeCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_TagOutputHintDoesNotFallThroughToSchemaCheck()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("MyTableTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("my-table"))
- .TagOutputHint("table")
- .Build(),
- TagHelperDescriptorBuilder.Create("MyTrTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("my-tr"))
- .TagOutputHint("tr")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["my-table"] = new HashSet { documentDescriptors[0] },
- ["table"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "table" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "body",
- containingParentTagName: null);
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CatchAllsOnlyApplyToCompletionsStartingWithPrefix()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("CatchAllTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["th:li"] = new HashSet { documentDescriptors[1], documentDescriptors[0] },
- ["li"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "ul",
- tagHelperPrefix: "th:");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_TagHelperPrefixIsPrependedToTagHelperCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("SuperLiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("superli"))
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["th:superli"] = new HashSet { documentDescriptors[0] },
- ["th:li"] = new HashSet { documentDescriptors[1] },
- ["li"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "ul",
- tagHelperPrefix: "th:");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CatchAllsApplyToOnlyTagHelperCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("SuperLiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("superli"))
- .Build(),
- TagHelperDescriptorBuilder.Create("CatchAll", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["superli"] = new HashSet() { documentDescriptors[0], documentDescriptors[1] },
- ["li"] = new HashSet(),
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CatchAllsApplyToNonTagHelperCompletionsIfStartsWithTagHelperPrefix()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("SuperLiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("superli"))
- .Build(),
- TagHelperDescriptorBuilder.Create("CatchAll", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["th:superli"] = new HashSet() { documentDescriptors[0], documentDescriptors[1] },
- ["th:li"] = new HashSet() { documentDescriptors[1] },
- });
-
- var existingCompletions = new[] { "th:li" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "ul",
- tagHelperPrefix: "th:");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_AllowsMultiTargetingTagHelpers()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("BoldTagHelper1", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("b"))
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("bold"))
- .Build(),
- TagHelperDescriptorBuilder.Create("BoldTagHelper2", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["strong"] = new HashSet { documentDescriptors[0], documentDescriptors[1] },
- ["b"] = new HashSet { documentDescriptors[0] },
- ["bold"] = new HashSet { documentDescriptors[0] },
- });
-
- var existingCompletions = new[] { "strong", "b", "bold" };
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CombinesDescriptorsOnExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("LiTagHelper1", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper2", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["li"] = new HashSet { documentDescriptors[0], documentDescriptors[1] },
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(documentDescriptors, existingCompletions, containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_NewCompletionsForSchemaTagsNotInExistingCompletionsAreIgnored()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("SuperLiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("superli"))
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .TagOutputHint("strong")
- .Build(),
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["li"] = new HashSet { documentDescriptors[1] },
- ["superli"] = new HashSet { documentDescriptors[0] },
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(documentDescriptors, existingCompletions, containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_OutputHintIsCrossReferencedWithExistingCompletions()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .TagOutputHint("li")
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .TagOutputHint("strong")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["div"] = new HashSet { documentDescriptors[0] },
- ["li"] = new HashSet { documentDescriptors[1] },
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(documentDescriptors, existingCompletions, containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_EnsuresDescriptorsHaveSatisfiedParent()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("LiTagHelper1", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li"))
- .Build(),
- TagHelperDescriptorBuilder.Create("LiTagHelper2", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("li").RequireParentTag("ol"))
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["li"] = new HashSet { documentDescriptors[0] },
- });
-
- var existingCompletions = new[] { "li" };
- var completionContext = BuildElementCompletionContext(documentDescriptors, existingCompletions, containingTagName: "ul");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_AllowedChildrenAreIgnoredWhenAtRoot()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("CatchAll", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .AllowChildTag("b")
- .AllowChildTag("bold")
- .AllowChildTag("div")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>());
-
- var existingCompletions = Enumerable.Empty();
- var completionContext = BuildElementCompletionContext(
- documentDescriptors,
- existingCompletions,
- containingTagName: null,
- containingParentTagName: null);
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_DoesNotReturnExistingCompletionsWhenAllowedChildren()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("BoldParent", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .AllowChildTag("b")
- .AllowChildTag("bold")
- .AllowChildTag("div")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["b"] = new HashSet(),
- ["bold"] = new HashSet(),
- ["div"] = new HashSet { documentDescriptors[0] }
- });
-
- var existingCompletions = new[] { "p", "em" };
- var completionContext = BuildElementCompletionContext(documentDescriptors, existingCompletions, containingTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CapturesAllAllowedChildTagsFromParentTagHelpers_NoneTagHelpers()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("BoldParent", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .AllowChildTag("b")
- .AllowChildTag("bold")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["b"] = new HashSet(),
- ["bold"] = new HashSet(),
- });
-
- var completionContext = BuildElementCompletionContext(documentDescriptors, Enumerable.Empty(), containingTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CapturesAllAllowedChildTagsFromParentTagHelpers_SomeTagHelpers()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("BoldParent", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .AllowChildTag("b")
- .AllowChildTag("bold")
- .AllowChildTag("div")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["b"] = new HashSet(),
- ["bold"] = new HashSet(),
- ["div"] = new HashSet { documentDescriptors[0] }
- });
-
- var completionContext = BuildElementCompletionContext(documentDescriptors, Enumerable.Empty(), containingTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- [Fact]
- public void GetElementCompletions_CapturesAllAllowedChildTagsFromParentTagHelpers_AllTagHelpers()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("BoldParentCatchAll", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .AllowChildTag("strong")
- .AllowChildTag("div")
- .AllowChildTag("b")
- .Build(),
- TagHelperDescriptorBuilder.Create("BoldParent", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .AllowChildTag("b")
- .AllowChildTag("bold")
- .Build(),
- };
- var expectedCompletions = ElementCompletionResult.Create(new Dictionary>()
- {
- ["strong"] = new HashSet { documentDescriptors[0] },
- ["b"] = new HashSet { documentDescriptors[0] },
- ["bold"] = new HashSet { documentDescriptors[0] },
- ["div"] = new HashSet { documentDescriptors[0], documentDescriptors[1] },
- });
-
- var completionContext = BuildElementCompletionContext(documentDescriptors, Enumerable.Empty(), containingTagName: "div");
- var service = CreateTagHelperCompletionFactsService();
-
- // Act
- var completions = service.GetElementCompletions(completionContext);
-
- // Assert
- AssertCompletionsAreEquivalent(expectedCompletions, completions);
- }
-
- private static DefaultTagHelperCompletionService CreateTagHelperCompletionFactsService()
- {
- var tagHelperFactService = new DefaultTagHelperFactsService();
- var completionFactService = new DefaultTagHelperCompletionService(tagHelperFactService);
-
- return completionFactService;
- }
-
- private static void AssertCompletionsAreEquivalent(ElementCompletionResult expected, ElementCompletionResult actual)
- {
- Assert.Equal(expected.Completions.Count, actual.Completions.Count);
-
- foreach (var expectedCompletion in expected.Completions)
- {
- var actualValue = actual.Completions[expectedCompletion.Key];
- Assert.NotNull(actualValue);
- Assert.Equal(expectedCompletion.Value, actualValue, TagHelperDescriptorComparer.CaseSensitive);
- }
- }
-
- private static void AssertCompletionsAreEquivalent(AttributeCompletionResult expected, AttributeCompletionResult actual)
- {
- Assert.Equal(expected.Completions.Count, actual.Completions.Count);
-
- foreach (var expectedCompletion in expected.Completions)
- {
- var actualValue = actual.Completions[expectedCompletion.Key];
- Assert.NotNull(actualValue);
- Assert.Equal(expectedCompletion.Value, actualValue, BoundAttributeDescriptorComparer.CaseSensitive);
- }
- }
-
- private static ElementCompletionContext BuildElementCompletionContext(
- IEnumerable descriptors,
- IEnumerable existingCompletions,
- string containingTagName,
- string containingParentTagName = "body",
- string tagHelperPrefix = "")
- {
- var documentContext = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
- var completionContext = new ElementCompletionContext(
- documentContext,
- existingCompletions,
- containingTagName,
- attributes: Enumerable.Empty>(),
- containingParentTagName: containingParentTagName,
- inHTMLSchema: (tag) => tag == "strong" || tag == "b" || tag == "bold" || tag == "li" || tag == "div");
-
- return completionContext;
- }
-
- private static AttributeCompletionContext BuildAttributeCompletionContext(
- IEnumerable descriptors,
- IEnumerable existingCompletions,
- string currentTagName,
- IEnumerable> attributes = null,
- string tagHelperPrefix = "")
- {
- attributes = attributes ?? Enumerable.Empty>();
- var documentContext = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
- var completionContext = new AttributeCompletionContext(
- documentContext,
- existingCompletions,
- currentTagName,
- attributes,
- currentParentTagName: "body",
- inHTMLSchema: (tag) => tag == "strong" || tag == "b" || tag == "bold" || tag == "li" || tag == "div");
-
- return completionContext;
- }
- }
-}
\ No newline at end of file
diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperFactsServiceTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperFactsServiceTest.cs
deleted file mode 100644
index f62597b32f..0000000000
--- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/DefaultTagHelperFactsServiceTest.cs
+++ /dev/null
@@ -1,388 +0,0 @@
-// 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 Microsoft.AspNetCore.Razor.Language;
-using System.Collections.Generic;
-using System.Linq;
-using Xunit;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- public class DefaultTagHelperFactsServiceTest
- {
- // Purposefully not thoroughly testing DefaultTagHelperFactsService.GetTagHelperBinding because it's a pass through
- // into TagHelperDescriptorProvider.GetTagHelperBinding.
-
- [Fact]
- public void GetTagHelperBinding_DoesNotAllowOptOutCharacterPrefix()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var binding = service.GetTagHelperBinding(documentContext, "!a", Enumerable.Empty>(), parentTag: null);
-
- // Assert
- Assert.Null(binding);
- }
-
- [Fact]
- public void GetTagHelperBinding_WorksAsExpected()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule =>
- rule
- .RequireTagName("a")
- .RequireAttributeDescriptor(attribute => attribute.Name("asp-for")))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-for")
- .TypeName(typeof(string).FullName)
- .PropertyName("AspFor"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-route")
- .TypeName(typeof(IDictionary).Namespace + "IDictionary")
- .PropertyName("AspRoute")
- .AsDictionaryAttribute("asp-route-", typeof(string).FullName))
- .Build(),
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("input"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-for")
- .TypeName(typeof(string).FullName)
- .PropertyName("AspFor"))
- .Build(),
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
- var attributes = new[]
- {
- new KeyValuePair("asp-for", "Name")
- };
-
- // Act
- var binding = service.GetTagHelperBinding(documentContext, "a", attributes, parentTag: "p");
-
- // Assert
- var descriptor = Assert.Single(binding.Descriptors);
- Assert.Equal(documentDescriptors[0], descriptor, TagHelperDescriptorComparer.CaseSensitive);
- var boundRule = Assert.Single(binding.GetBoundRules(descriptor));
- Assert.Equal(documentDescriptors[0].TagMatchingRules.First(), boundRule, TagMatchingRuleDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetBoundTagHelperAttributes_MatchesPrefixedAttributeName()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("a"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-for")
- .TypeName(typeof(string).FullName)
- .PropertyName("AspFor"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-route")
- .TypeName(typeof(IDictionary).Namespace + "IDictionary")
- .PropertyName("AspRoute")
- .AsDictionaryAttribute("asp-route-", typeof(string).FullName))
- .Build()
- };
- var expectedAttributeDescriptors = new[]
- {
- documentDescriptors[0].BoundAttributes.Last()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
- var binding = service.GetTagHelperBinding(documentContext, "a", Enumerable.Empty>(), parentTag: null);
-
- // Act
- var descriptors = service.GetBoundTagHelperAttributes(documentContext, "asp-route-something", binding);
-
- // Assert
- Assert.Equal(expectedAttributeDescriptors, descriptors, BoundAttributeDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetBoundTagHelperAttributes_MatchesAttributeName()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("input"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-for")
- .TypeName(typeof(string).FullName)
- .PropertyName("AspFor"))
- .BoundAttributeDescriptor(attribute =>
- attribute
- .Name("asp-extra")
- .TypeName(typeof(string).FullName)
- .PropertyName("AspExtra"))
- .Build()
- };
- var expectedAttributeDescriptors = new[]
- {
- documentDescriptors[0].BoundAttributes.First()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
- var binding = service.GetTagHelperBinding(documentContext, "input", Enumerable.Empty>(), parentTag: null);
-
- // Act
- var descriptors = service.GetBoundTagHelperAttributes(documentContext, "asp-for", binding);
-
- // Assert
- Assert.Equal(expectedAttributeDescriptors, descriptors, BoundAttributeDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenTag_DoesNotAllowOptOutCharacterPrefix()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("*"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenTag(documentContext, "!strong", parentTag: null);
-
- // Assert
- Assert.Empty(descriptors);
- }
-
- [Fact]
- public void GetTagHelpersGivenTag_RequiresTagName()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenTag(documentContext, "strong", "p");
-
- // Assert
- Assert.Equal(documentDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenTag_RestrictsTagHelpersBasedOnTagName()
- {
- // Arrange
- var expectedDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("a")
- .RequireParentTag("div"))
- .Build()
- };
- var documentDescriptors = new[]
- {
- expectedDescriptors[0],
- TagHelperDescriptorBuilder.Create("TestType2", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("strong")
- .RequireParentTag("div"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenTag(documentContext, "a", "div");
-
- // Assert
- Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenTag_RestrictsTagHelpersBasedOnTagHelperPrefix()
- {
- // Arrange
- var expectedDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("strong"))
- .Build()
- };
- var documentDescriptors = new[]
- {
- expectedDescriptors[0],
- TagHelperDescriptorBuilder.Create("TestType2", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("thstrong"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create("th", documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenTag(documentContext, "thstrong", "div");
-
- // Assert
- Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenTag_RestrictsTagHelpersBasedOnParent()
- {
- // Arrange
- var expectedDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("strong")
- .RequireParentTag("div"))
- .Build()
- };
- var documentDescriptors = new[]
- {
- expectedDescriptors[0],
- TagHelperDescriptorBuilder.Create("TestType2", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("strong")
- .RequireParentTag("p"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenTag(documentContext, "strong", "div");
-
- // Assert
- Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenParent_AllowsRootParentTag()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenParent(documentContext, parentTag: null /* root */);
-
- // Assert
- Assert.Equal(documentDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenParent_AllowsRootParentTagForParentRestrictedTagHelperDescriptors()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("DivTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .Build(),
- TagHelperDescriptorBuilder.Create("PTagHelper", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule
- .RequireTagName("p")
- .RequireParentTag("body"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenParent(documentContext, parentTag: null /* root */);
-
- // Assert
- var descriptor = Assert.Single(descriptors);
- Assert.Equal(documentDescriptors[0], descriptor, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenParent_AllowsUnspecifiedParentTagHelpers()
- {
- // Arrange
- var documentDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenParent(documentContext, "p");
-
- // Assert
- Assert.Equal(documentDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
-
- [Fact]
- public void GetTagHelpersGivenParent_RestrictsTagHelpersBasedOnParent()
- {
- // Arrange
- var expectedDescriptors = new[]
- {
- TagHelperDescriptorBuilder.Create("TestType", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("p")
- .RequireParentTag("div"))
- .Build()
- };
- var documentDescriptors = new[]
- {
- expectedDescriptors[0],
- TagHelperDescriptorBuilder.Create("TestType2", "TestAssembly")
- .TagMatchingRuleDescriptor(
- rule => rule
- .RequireTagName("strong")
- .RequireParentTag("p"))
- .Build()
- };
- var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors);
- var service = new DefaultTagHelperFactsService();
-
- // Act
- var descriptors = service.GetTagHelpersGivenParent(documentContext, "div");
-
- // Assert
- Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.CaseSensitive);
- }
- }
-}
\ No newline at end of file
diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/RazorEditorParserTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/RazorEditorParserTest.cs
deleted file mode 100644
index 0f6e3e32e9..0000000000
--- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Legacy/RazorEditorParserTest.cs
+++ /dev/null
@@ -1,1345 +0,0 @@
-// 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 System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using Microsoft.AspNetCore.Mvc.Razor.Extensions;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Legacy;
-using Microsoft.VisualStudio.Text;
-using Xunit;
-
-namespace Microsoft.VisualStudio.LanguageServices.Razor
-{
- public class RazorEditorParserTest
- {
- private static readonly TestFile SimpleCSHTMLDocument = TestFile.Create("TestFiles/DesignTime/Simple.cshtml", typeof(RazorEditorParserTest));
- private static readonly TestFile SimpleCSHTMLDocumentGenerated = TestFile.Create("TestFiles/DesignTime/Simple.txt", typeof(RazorEditorParserTest));
- private const string TestLinePragmaFileName = "C:\\This\\Path\\Is\\Just\\For\\Line\\Pragmas.cshtml";
-
- public static TheoryData TagHelperPartialParseRejectData
- {
- get
- {
- return new TheoryData
- {
- CreateInsertionChange("", 2, " "),
- CreateInsertionChange("", 6, " "),
- CreateInsertionChange("", 12, " "),
- CreateInsertionChange("", 12, "ibute"),
- CreateInsertionChange("", 2, " before"),
- };
- }
- }
-
- [Theory]
- [MemberData(nameof(TagHelperPartialParseRejectData))]
- public void TagHelperTagBodiesRejectPartialChanges(object editObject)
- {
- // Arrange
- var edit = (TestEdit)editObject;
- var builder = TagHelperDescriptorBuilder.Create("PTagHelper", "TestAssembly");
- builder.SetTypeName("PTagHelper");
- builder.TagMatchingRule(rule => rule.TagName = "p");
- var descriptors = new[]
- {
- builder.Build()
- };
-
- var parser = new RazorEditorParser(CreateTemplateEngine(@"C:\This\Is\A\Test\Path"), @"C:\This\Is\A\Test\Path");
-
- using (var manager = new TestParserManager(parser))
- {
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected, result);
- Assert.Equal(2, manager.ParseCount);
- }
- }
-
- public static TheoryData TagHelperAttributeAcceptData
- {
- get
- {
- var factory = new SpanFactory();
-
- // change, (Block)expectedDocument, partialParseResult
- return new TheoryData
- {
- {
- CreateInsertionChange("", 22, "."),
- PartialParseResult.Accepted | PartialParseResult.Provisional
- },
- {
- CreateInsertionChange("", 21, "."),
- PartialParseResult.Accepted
- },
- {
- CreateInsertionChange("", 25, "."),
- PartialParseResult.Accepted
- },
- {
- CreateInsertionChange("", 34, "."),
- PartialParseResult.Accepted | PartialParseResult.Provisional
- },
- {
- CreateInsertionChange("", 29, "."),
- PartialParseResult.Accepted | PartialParseResult.Provisional
- },
- };
- }
- }
-
- [Theory]
- [MemberData(nameof(TagHelperAttributeAcceptData))]
- public void TagHelperAttributesAreLocatedAndAcceptChangesCorrectly(object editObject, PartialParseResult partialParseResult)
- {
- // Arrange
- var edit = (TestEdit)editObject;
- var builder = TagHelperDescriptorBuilder.Create("PTagHelper", "Test");
- builder.SetTypeName("PTagHelper");
- builder.TagMatchingRule(rule => rule.TagName = "p");
- builder.BindAttribute(attribute =>
- {
- attribute.Name = "obj-attr";
- attribute.TypeName = typeof(object).FullName;
- attribute.SetPropertyName("ObjectAttribute");
- });
- builder.BindAttribute(attribute =>
- {
- attribute.Name = "str-attr";
- attribute.TypeName = typeof(string).FullName;
- attribute.SetPropertyName("StringAttribute");
- });
- var descriptors = new[] { builder.Build() };
-
- var parser = new RazorEditorParser(CreateTemplateEngine(@"C:\This\Is\A\Test\Path", descriptors), @"C:\This\Is\A\Test\Path");
-
- using (var manager = new TestParserManager(parser))
- {
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(partialParseResult, result);
- Assert.Equal(1, manager.ParseCount);
- }
- }
-
- [Fact]
- public void ConstructorRequiresNonNullPhysicalPath()
- {
- Assert.Throws("filePath", () => new RazorEditorParser(CreateTemplateEngine(), null));
- }
-
- [Fact]
- public void ConstructorRequiresNonEmptyPhysicalPath()
- {
- Assert.Throws("filePath", () => new RazorEditorParser(CreateTemplateEngine(), string.Empty));
- }
-
- [Theory]
- [InlineData(" ")]
- [InlineData("\r\n")]
- [InlineData("abcdefg")]
- [InlineData("\f\r\n abcd \t")]
- public void TreesAreDifferentReturnsFalseForAddedContent(string content)
- {
- // Arrange
- var factory = new SpanFactory();
- var blockFactory = new BlockFactory(factory);
- var original = new MarkupBlock(
- blockFactory.MarkupTagBlock(""),
- blockFactory.TagHelperBlock(
- tagName: "div",
- tagMode: TagMode.StartTagAndEndTag,
- start: new SourceLocation(3, 0, 3),
- startTag: blockFactory.MarkupTagBlock("
"),
- children: new SyntaxTreeNode[]
- {
- factory.Markup($"{Environment.NewLine}{Environment.NewLine}")
- },
- endTag: blockFactory.MarkupTagBlock("
")),
- blockFactory.MarkupTagBlock("
"));
-
- factory.Reset();
-
- var modified = new MarkupBlock(
- blockFactory.MarkupTagBlock(""),
- blockFactory.TagHelperBlock(
- tagName: "div",
- tagMode: TagMode.StartTagAndEndTag,
- start: new SourceLocation(3, 0, 3),
- startTag: blockFactory.MarkupTagBlock("
"),
- children: new SyntaxTreeNode[]
- {
- factory.Markup($"{Environment.NewLine}{content}{Environment.NewLine}")
- },
- endTag: blockFactory.MarkupTagBlock("
")),
- blockFactory.MarkupTagBlock(""));
- original.LinkNodes();
- modified.LinkNodes();
-
- // Act
- var treesAreDifferent = RazorEditorParser.BackgroundParser.TreesAreDifferent(
- original,
- modified,
- new[]
- {
- new SourceChange(
- absoluteIndex: 8 + Environment.NewLine.Length,
- length: 0,
- newText: content)
- },
- CancellationToken.None);
-
- // Assert
- Assert.False(treesAreDifferent);
- }
-
- [Fact]
- public void TreesAreDifferentReturnsTrueIfTreeStructureIsDifferent()
- {
- var factory = new SpanFactory();
- var original = new MarkupBlock(
- factory.Markup(""),
- new ExpressionBlock(
- factory.CodeTransition()),
- factory.Markup("
"));
- var modified = new MarkupBlock(
- factory.Markup(""),
- new ExpressionBlock(
- factory.CodeTransition("@"),
- factory.Code("f")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
- factory.Markup("
"));
- Assert.True(RazorEditorParser.BackgroundParser.TreesAreDifferent(
- original,
- modified,
- new[]
- {
- new SourceChange(absoluteIndex: 4, length: 0, newText: "f")
- },
- CancellationToken.None));
- }
-
- [Fact]
- public void TreesAreDifferentReturnsFalseIfTreeStructureIsSame()
- {
- var factory = new SpanFactory();
- var original = new MarkupBlock(
- factory.Markup(""),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("f")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
- factory.Markup("
"));
- factory.Reset();
- var modified = new MarkupBlock(
- factory.Markup(""),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
- factory.Markup("
"));
- original.LinkNodes();
- modified.LinkNodes();
- Assert.False(RazorEditorParser.BackgroundParser.TreesAreDifferent(
- original,
- modified,
- new[]
- {
- new SourceChange(absoluteIndex: 5, length: 0, newText: "oo")
- },
- CancellationToken.None));
- }
-
- [Fact]
- public void CheckForStructureChangesStartsFullReparseIfChangeOverlapsMultipleSpans()
- {
- // Arrange
- using (var parser = new RazorEditorParser(CreateTemplateEngine(), TestLinePragmaFileName))
- {
- var original = new StringTextSnapshot("Foo @bar Baz");
- var changed = new StringTextSnapshot("Foo @bap Daz");
- var change = new SourceChange(7, 3, "p D");
-
- var parseComplete = new ManualResetEventSlim();
- var parseCount = 0;
- parser.DocumentParseComplete += (sender, args) =>
- {
- Interlocked.Increment(ref parseCount);
- parseComplete.Set();
- };
-
- Assert.Equal(PartialParseResult.Rejected, parser.CheckForStructureChanges(change, original));
- DoWithTimeoutIfNotDebugging(parseComplete.Wait); // Wait for the parse to finish
- parseComplete.Reset();
-
- // Act
- var result = parser.CheckForStructureChanges(change, original);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected, result);
- DoWithTimeoutIfNotDebugging(parseComplete.Wait);
- Assert.Equal(2, parseCount);
- }
- }
-
- [Fact]
- public void AwaitPeriodInsertionAcceptedProvisionally()
- {
- // Arrange
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @await Html. baz");
- var old = new StringTextSnapshot("foo @await Html baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(15, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("await Html.").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.WhiteSpace | AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")), additionalFlags: PartialParseResult.Provisional);
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsInnerInsertionsInStatementBlock()
- {
- // Arrange
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime..Now" + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime.Now" + Environment.NewLine
- + "}");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(17, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime..Now")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsInnerInsertions()
- {
- // Arrange
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @DateTime..Now baz");
- var old = new StringTextSnapshot("foo @DateTime.Now baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(13, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime..Now").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")), additionalFlags: PartialParseResult.Provisional);
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsWholeIdentifierReplacement()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @date baz");
- var changed = new StringTextSnapshot("foo @DateTime baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(5, 4, old, 8, changed, "DateTime"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionRejectsWholeIdentifierReplacementToKeyword()
- {
- // Arrange
- var parser = new RazorEditorParser(CreateTemplateEngine(@"C:\This\Is\A\Test\Path"), @"C:\This\Is\A\Test\Path");
-
- using (var manager = new TestParserManager(parser))
- {
- var old = new StringTextSnapshot("foo @date baz");
- var changed = new StringTextSnapshot("foo @if baz");
- var edit = new TestEdit(5, 4, old, 2, changed, "if");
- manager.InitializeWithDocument(old);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected, result);
- Assert.Equal(2, manager.ParseCount);
- }
- }
-
- [Fact]
- public void ImplicitExpressionRejectsWholeIdentifierReplacementToDirective()
- {
- // Arrange
- var parser = new RazorEditorParser(CreateTemplateEngine(@"C:\This\Is\A\Test\Path"), @"C:\This\Is\A\Test\Path");
-
- using (var manager = new TestParserManager(parser))
- {
- var old = new StringTextSnapshot("foo @date baz");
- var changed = new StringTextSnapshot("foo @inherits baz");
- var SourceChange = new TestEdit(5, 4, old, 8, changed, "inherits");
- manager.InitializeWithDocument(old);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(SourceChange);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected | PartialParseResult.SpanContextChanged, result);
- Assert.Equal(2, manager.ParseCount);
- }
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsPrefixIdentifierReplacements_SingleSymbol()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @dTime baz");
- var changed = new StringTextSnapshot("foo @DateTime baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(5, 1, old, 4, changed, "Date"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsPrefixIdentifierReplacements_MultipleSymbols()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @dTime.Now baz");
- var changed = new StringTextSnapshot("foo @DateTime.Now baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(5, 1, old, 4, changed, "Date"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime.Now").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsSuffixIdentifierReplacements_SingleSymbol()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @Datet baz");
- var changed = new StringTextSnapshot("foo @DateTime baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(9, 1, old, 4, changed, "Time"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsSuffixIdentifierReplacements_MultipleSymbols()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @DateTime.n baz");
- var changed = new StringTextSnapshot("foo @DateTime.Now baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(14, 1, old, 3, changed, "Now"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime.Now").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsSurroundedIdentifierReplacements()
- {
- // Arrange
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @DateTime.n.ToString() baz");
- var changed = new StringTextSnapshot("foo @DateTime.Now.ToString() baz");
-
- // Act and Assert
- RunPartialParseTest(new TestEdit(14, 1, old, 3, changed, "Now"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("DateTime.Now.ToString()").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsDotlessCommitInsertionsInStatementBlockAfterIdentifiers()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime." + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime" + Environment.NewLine
- + "}");
-
- var edit = new TestEdit(15 + Environment.NewLine.Length, 0, old, 1, changed, ".");
- using (var manager = CreateParserManager())
- {
- Action applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
- {
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(expectedResult, result);
- Assert.Equal(1, manager.ParseCount);
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(expectedCode)
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- };
-
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateTime.");
-
- old = changed;
- changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime.." + Environment.NewLine
- + "}");
- edit = new TestEdit(16 + Environment.NewLine.Length, 0, old, 1, changed, ".");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateTime..");
-
- old = changed;
- changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime.Now." + Environment.NewLine
- + "}");
- edit = new TestEdit(16 + Environment.NewLine.Length, 0, old, 3, changed, "Now");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateTime.Now.");
- }
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsDotlessCommitInsertionsInStatementBlock()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateT." + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateT" + Environment.NewLine
- + "}");
-
- var edit = new TestEdit(12 + Environment.NewLine.Length, 0, old, 1, changed, ".");
- using (var manager = CreateParserManager())
- {
- Action applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
- {
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(expectedResult, result);
- Assert.Equal(1, manager.ParseCount);
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(expectedCode)
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- };
-
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateT.");
-
- old = changed;
- changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @DateTime." + Environment.NewLine
- + "}");
- edit = new TestEdit(12 + Environment.NewLine.Length, 0, old, 3, changed, "ime");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateTime.");
- }
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsDotlessCommitInsertions()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @DateT. baz");
- var old = new StringTextSnapshot("foo @DateT baz");
- var edit = new TestEdit(10, 0, old, 1, changed, ".");
- using (var manager = CreateParserManager())
- {
- Action applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
- {
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(expectedResult, result);
- Assert.Equal(1, manager.ParseCount);
-
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- };
-
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateT.");
-
- old = changed;
- changed = new StringTextSnapshot("foo @DateTime. baz");
- edit = new TestEdit(10, 0, old, 3, changed, "ime");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.");
- }
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsDotlessCommitInsertionsAfterIdentifiers()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @DateTime. baz");
- var old = new StringTextSnapshot("foo @DateTime baz");
- var edit = new TestEdit(13, 0, old, 1, changed, ".");
- using (var manager = CreateParserManager())
- {
- Action applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
- {
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(expectedResult, result);
- Assert.Equal(1, manager.ParseCount);
-
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- };
-
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.");
-
- old = changed;
- changed = new StringTextSnapshot("foo @DateTime.. baz");
- edit = new TestEdit(14, 0, old, 1, changed, ".");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime..");
-
- old = changed;
- changed = new StringTextSnapshot("foo @DateTime.Now. baz");
- edit = new TestEdit(14, 0, old, 3, changed, "Now");
-
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.Now.");
- }
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsCaseInsensitiveDotlessCommitInsertions_NewRoslynIntegration()
- {
- var factory = new SpanFactory();
- var old = new StringTextSnapshot("foo @date baz");
- var changed = new StringTextSnapshot("foo @date. baz");
- var edit = new TestEdit(9, 0, old, 1, changed, ".");
- using (var manager = CreateParserManager())
- {
- Action applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
- {
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(expectedResult, result);
- Assert.Equal(1, manager.ParseCount);
-
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- };
-
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
-
- // @date => @date.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "date.");
-
- old = changed;
- changed = new StringTextSnapshot("foo @date baz");
- edit = new TestEdit(9, 1, old, 0, changed, "");
-
- // @date. => @date
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "date");
-
- old = changed;
- changed = new StringTextSnapshot("foo @DateTime baz");
- edit = new TestEdit(5, 4, old, 8, changed, "DateTime");
-
- // @date => @DateTime
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted, "DateTime");
-
- old = changed;
- changed = new StringTextSnapshot("foo @DateTime. baz");
- edit = new TestEdit(13, 0, old, 1, changed, ".");
-
- // @DateTime => @DateTime.
- applyAndVerifyPartialChange(edit, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.");
- }
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsDeleteOfIdentifierPartsIfDotRemains()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @User. baz");
- var old = new StringTextSnapshot("foo @User.Name baz");
- RunPartialParseTest(new TestEdit(10, 4, old, 0, changed, string.Empty),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("User.").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")),
- additionalFlags: PartialParseResult.Provisional);
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsDeleteOfIdentifierPartsIfSomeOfIdentifierRemains()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @Us baz");
- var old = new StringTextSnapshot("foo @User baz");
- RunPartialParseTest(new TestEdit(7, 2, old, 0, changed, string.Empty),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("Us").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsMultipleInsertionIfItCausesIdentifierExpansionAndTrailingDot()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @User. baz");
- var old = new StringTextSnapshot("foo @U baz");
- RunPartialParseTest(new TestEdit(6, 0, old, 4, changed, "ser."),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("User.").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")),
- additionalFlags: PartialParseResult.Provisional);
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsMultipleInsertionIfItOnlyCausesIdentifierExpansion()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @barbiz baz");
- var old = new StringTextSnapshot("foo @bar baz");
- RunPartialParseTest(new TestEdit(8, 0, old, 3, changed, "biz"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("barbiz").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" baz")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsIdentifierExpansionAtEndOfNonWhitespaceCharacters()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @food" + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @foo" + Environment.NewLine
- + "}");
- RunPartialParseTest(new TestEdit(10 + Environment.NewLine.Length, 0, old, 1, changed, "d"),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("food")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsIdentifierAfterDotAtEndOfNonWhitespaceCharacters()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @foo.d" + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @foo." + Environment.NewLine
- + "}");
- RunPartialParseTest(new TestEdit(11 + Environment.NewLine.Length, 0, old, 1, changed, "d"),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo.d")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsDotAtEndOfNonWhitespaceCharacters()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{" + Environment.NewLine
- + " @foo." + Environment.NewLine
- + "}");
- var old = new StringTextSnapshot("@{" + Environment.NewLine
- + " @foo" + Environment.NewLine
- + "}");
- RunPartialParseTest(new TestEdit(10 + Environment.NewLine.Length, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.Code(Environment.NewLine + " ")
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code(@"foo.")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Code(Environment.NewLine).AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionRejectsChangeWhichWouldHaveBeenAcceptedIfLastChangeWasProvisionallyAcceptedOnDifferentSpan()
- {
- var factory = new SpanFactory();
-
- // Arrange
- var dotTyped = new TestEdit(8, 0, new StringTextSnapshot("foo @foo @bar"), 1, new StringTextSnapshot("foo @foo. @bar"), ".");
- var charTyped = new TestEdit(14, 0, new StringTextSnapshot("foo @foo. @bar"), 1, new StringTextSnapshot("foo @foo. @barb"), "b");
- using (var manager = CreateParserManager())
- {
- manager.InitializeWithDocument(dotTyped.OldSnapshot);
-
- // Apply the dot change
- Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
-
- // Act (apply the identifier start char change)
- var result = manager.CheckForStructureChangesAndWait(charTyped);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected, result);
- Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not");
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root,
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(". "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("barb")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.EmptyHtml()));
- }
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsIdentifierTypedAfterDotIfLastChangeWasProvisionalAcceptanceOfDot()
- {
- var factory = new SpanFactory();
-
- // Arrange
- var dotTyped = new TestEdit(8, 0, new StringTextSnapshot("foo @foo bar"), 1, new StringTextSnapshot("foo @foo. bar"), ".");
- var charTyped = new TestEdit(9, 0, new StringTextSnapshot("foo @foo. bar"), 1, new StringTextSnapshot("foo @foo.b bar"), "b");
- using (var manager = CreateParserManager())
- {
- manager.InitializeWithDocument(dotTyped.OldSnapshot);
-
- // Apply the dot change
- Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
-
- // Act (apply the identifier start char change)
- var 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.CurrentSyntaxTree.Root,
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo.b")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" bar")));
- }
- }
-
- [Fact]
- public void ImplicitExpressionProvisionallyAcceptsDotAfterIdentifierInMarkup()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @foo. bar");
- var old = new StringTextSnapshot("foo @foo bar");
- RunPartialParseTest(new TestEdit(8, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo.")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" bar")),
- additionalFlags: PartialParseResult.Provisional);
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsAdditionalIdentifierCharactersIfEndOfSpanIsIdentifier()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("foo @foob bar");
- var old = new StringTextSnapshot("foo @foo bar");
- RunPartialParseTest(new TestEdit(8, 0, old, 1, changed, "b"),
- new MarkupBlock(
- factory.Markup("foo "),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foob")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.Markup(" bar")));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsAdditionalIdentifierStartCharactersIfEndOfSpanIsDot()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{@foo.b}");
- var old = new StringTextSnapshot("@{@foo.}");
- RunPartialParseTest(new TestEdit(7, 0, old, 1, changed, "b"),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.EmptyCSharp()
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo.b")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.EmptyCSharp().AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionAcceptsDotIfTrailingDotsAreAllowed()
- {
- var factory = new SpanFactory();
- var changed = new StringTextSnapshot("@{@foo.}");
- var old = new StringTextSnapshot("@{@foo}");
- RunPartialParseTest(new TestEdit(6, 0, old, 1, changed, "."),
- new MarkupBlock(
- factory.EmptyHtml(),
- new StatementBlock(
- factory.CodeTransition(),
- factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
- factory.EmptyCSharp()
- .AsStatement()
- .AutoCompleteWith(autoCompleteString: null),
- new ExpressionBlock(
- factory.CodeTransition(),
- factory.Code("foo.")
- .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
- .Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
- factory.EmptyCSharp().AsStatement(),
- factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
- factory.EmptyHtml()));
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfIfKeywordTyped()
- {
- RunTypeKeywordTest("if");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfDoKeywordTyped()
- {
- RunTypeKeywordTest("do");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfTryKeywordTyped()
- {
- RunTypeKeywordTest("try");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfForKeywordTyped()
- {
- RunTypeKeywordTest("for");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfForEachKeywordTyped()
- {
- RunTypeKeywordTest("foreach");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfWhileKeywordTyped()
- {
- RunTypeKeywordTest("while");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfSwitchKeywordTyped()
- {
- RunTypeKeywordTest("switch");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfLockKeywordTyped()
- {
- RunTypeKeywordTest("lock");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfUsingKeywordTyped()
- {
- RunTypeKeywordTest("using");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfSectionKeywordTyped()
- {
- RunTypeKeywordTest("section");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfInheritsKeywordTyped()
- {
- RunTypeKeywordTest("inherits");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfFunctionsKeywordTyped()
- {
- RunTypeKeywordTest("functions");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfNamespaceKeywordTyped()
- {
- RunTypeKeywordTest("namespace");
- }
-
- [Fact]
- public void ImplicitExpressionCorrectlyTriggersReparseIfClassKeywordTyped()
- {
- RunTypeKeywordTest("class");
- }
-
- private static TestEdit CreateInsertionChange(string initialText, int insertionLocation, string insertionText)
- {
- var changedText = initialText.Insert(insertionLocation, insertionText);
- var sourceChange = new SourceChange(insertionLocation, 0, insertionText);
- var oldSnapshot = new StringTextSnapshot(initialText);
- var changedSnapshot = new StringTextSnapshot(changedText);
- return new TestEdit
- {
- Change = sourceChange,
- OldSnapshot = oldSnapshot,
- NewSnapshot = changedSnapshot,
- };
- }
-
- private static void RunFullReparseTest(TestEdit edit, PartialParseResult additionalFlags = (PartialParseResult)0)
- {
- // Arrange
- using (var manager = CreateParserManager())
- {
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(PartialParseResult.Rejected | additionalFlags, result);
- Assert.Equal(2, manager.ParseCount);
- }
- }
-
- private static void RunPartialParseTest(TestEdit edit, Block newTreeRoot, PartialParseResult additionalFlags = (PartialParseResult)0)
- {
- // Arrange
- using (var manager = CreateParserManager())
- {
- manager.InitializeWithDocument(edit.OldSnapshot);
-
- // Act
- var result = manager.CheckForStructureChangesAndWait(edit);
-
- // Assert
- Assert.Equal(PartialParseResult.Accepted | additionalFlags, result);
- Assert.Equal(1, manager.ParseCount);
- ParserTestBase.EvaluateParseTree(manager.Parser.CurrentSyntaxTree.Root, newTreeRoot);
- }
- }
-
- private static TestParserManager CreateParserManager()
- {
- var parser = new RazorEditorParser(CreateTemplateEngine(), TestLinePragmaFileName);
- return new TestParserManager(parser);
- }
-
- private static RazorTemplateEngine CreateTemplateEngine(
- string path = TestLinePragmaFileName,
- IEnumerable tagHelpers = null)
- {
- var engine = RazorEngine.CreateDesignTime(builder =>
- {
- RazorExtensions.Register(builder);
-
- if (tagHelpers != null)
- {
- builder.AddTagHelpers(tagHelpers);
- }
- });
-
- // GetImports on RazorTemplateEngine will at least check that the item exists, so we need to pretend
- // that it does.
- var items = new List();
- items.Add(new TestRazorProjectItem(path));
-
- var project = new TestRazorProject(items);
-
- var templateEngine = new RazorTemplateEngine(engine, project);
- templateEngine.Options.DefaultImports = RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml");
- return templateEngine;
- }
-
- private static void RunTypeKeywordTest(string keyword)
- {
- var before = "@" + keyword.Substring(0, keyword.Length - 1);
- var after = "@" + keyword;
- var changed = new StringTextSnapshot(after);
- var old = new StringTextSnapshot(before);
- var change = new SourceChange(keyword.Length, 0, keyword[keyword.Length - 1].ToString());
- var edit = new TestEdit
- {
- Change = change,
- NewSnapshot = changed,
- OldSnapshot = old
- };
- RunFullReparseTest(edit, additionalFlags: PartialParseResult.SpanContextChanged);
- }
-
- private static void DoWithTimeoutIfNotDebugging(Func withTimeout)
- {
-#if DEBUG
- if (Debugger.IsAttached)
- {
- withTimeout(Timeout.Infinite);
- }
- else
- {
-#endif
- Assert.True(withTimeout((int)TimeSpan.FromSeconds(1).TotalMilliseconds), "Timeout expired!");
-#if DEBUG
- }
-#endif
- }
-
- private class TestParserManager : IDisposable
- {
- public int ParseCount;
-
- private readonly ManualResetEventSlim _parserComplete;
-
- public TestParserManager(RazorEditorParser parser)
- {
- _parserComplete = new ManualResetEventSlim();
- ParseCount = 0;
- Parser = parser;
- parser.DocumentParseComplete += (sender, args) =>
- {
- Interlocked.Increment(ref ParseCount);
- _parserComplete.Set();
- };
- }
-
- public RazorEditorParser Parser { get; }
-
- public void InitializeWithDocument(ITextSnapshot snapshot)
- {
- var initialChange = new SourceChange(0, 0, string.Empty);
- var edit = new TestEdit
- {
- Change = initialChange,
- OldSnapshot = snapshot,
- NewSnapshot = snapshot
- };
- CheckForStructureChangesAndWait(edit);
- }
-
- public PartialParseResult CheckForStructureChangesAndWait(TestEdit edit)
- {
- var result = Parser.CheckForStructureChanges(edit.Change, edit.NewSnapshot);
- if (result.HasFlag(PartialParseResult.Rejected))
- {
- WaitForParse();
- }
- return result;
- }
-
- public void WaitForParse()
- {
- DoWithTimeoutIfNotDebugging(_parserComplete.Wait); // Wait for the parse to finish
- _parserComplete.Reset();
- }
-
- public void Dispose()
- {
- Parser.Dispose();
- }
- }
-
- private class TestEdit
- {
- public TestEdit()
- {
- }
-
- public TestEdit(int position, int oldLength, ITextSnapshot oldSnapshot, int newLength, ITextSnapshot newSnapshot, string newText)
- {
- Change = new SourceChange(position, oldLength, newText);
- OldSnapshot = oldSnapshot;
- NewSnapshot = newSnapshot;
- }
-
- public SourceChange Change { get; set; }
-
- public ITextSnapshot OldSnapshot { get; set; }
-
- public ITextSnapshot NewSnapshot { get; set; }
- }
- }
-}
\ No newline at end of file