public void SyntaxTreeRequest_Complete_CanBeCalledMultipleTimes() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create()); var request = new DefaultVisualStudioRazorParser.SyntaxTreeRequest(StringTextSnapshot.Empty, CancellationToken.None); // Act & Assert request.Complete(syntaxTree); request.Complete(syntaxTree); request.Complete(syntaxTree); }
public override IReadOnlyList <ClassifiedSpan> GetClassifiedSpans(RazorSyntaxTree syntaxTree) { var result = syntaxTree.GetClassifiedSpans(); return(result.Select(item => new ClassifiedSpan( item.Span, item.BlockSpan, (SpanKind)item.SpanKind, (BlockKind)item.BlockKind, (AcceptedCharacters)item.AcceptedCharacters)).ToArray()); }
private static TextBufferCodeDocumentProvider CreateCodeDocumentProvider(string content) { var sourceDocument = TestRazorSourceDocument.Create(content); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument, RazorParserOptions.Create(opt => opt.Directives.Add(FunctionsDirective.Directive))); var codeDocument = TestRazorCodeDocument.Create(content); codeDocument.SetSyntaxTree(syntaxTree); var codeDocumentProvider = Mock.Of <TextBufferCodeDocumentProvider>(provider => provider.TryGetFromBuffer(It.IsAny <ITextBuffer>(), out codeDocument), MockBehavior.Strict); return(codeDocumentProvider); }
private void TextBuffer_OnChanged(object sender, TextContentChangedEventArgs args) { _dispatcher.AssertForegroundThread(); if (args.Changes.Count > 0) { // Idle timers are used to track provisional changes. Provisional changes only last for a single text change. After that normal // partial parsing rules apply (stop the timer). StopIdleTimer(); } var snapshot = args.After; if (!args.TextChangeOccurred(out var changeInformation)) { // Ensure we get a parse for latest snapshot. QueueChange(null, snapshot); return; } var change = new SourceChange(changeInformation.firstChange.OldPosition, changeInformation.oldText.Length, changeInformation.newText); var result = PartialParseResultInternal.Rejected; RazorSyntaxTree partialParseSyntaxTree = null; using (_parser.SynchronizeMainThreadState()) { // Check if we can partial-parse if (_partialParser != null && _parser.IsIdle) { (result, partialParseSyntaxTree) = _partialParser.Parse(change); } } // If partial parsing failed or there were outstanding parser tasks, start a full reparse if ((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected) { QueueChange(change, snapshot); } else { var currentCodeDocument = CodeDocument; var codeDocument = RazorCodeDocument.Create(currentCodeDocument.Source, currentCodeDocument.Imports); foreach (var item in currentCodeDocument.Items) { codeDocument.Items[item.Key] = item.Value; } codeDocument.SetSyntaxTree(partialParseSyntaxTree); TryUpdateLatestParsedSyntaxTreeSnapshot(codeDocument, snapshot); } if ((result & PartialParseResultInternal.Provisional) == PartialParseResultInternal.Provisional) { StartIdleTimer(); } }
internal static IReadOnlyList <TagHelperSpanInternal> GetTagHelperSpans(Block root, string filePath) { // We don't care about the options and diagnostic here. var syntaxTree = RazorSyntaxTree.Create( root, TestRazorSourceDocument.Create(filePath: filePath), Array.Empty <RazorDiagnostic>(), RazorParserOptions.CreateDefault()); return(syntaxTree.GetTagHelperSpans()); }
private static RazorSyntaxTree GetSyntaxTree(string content) { var syntaxTree = RazorSyntaxTree.Parse( TestRazorSourceDocument.Create(content), RazorParserOptions.Create(options => { options.Directives.Add(FunctionsDirective.Directive); options.Directives.Add(SectionDirective.Directive); })); return(syntaxTree); }
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) { if (FileKinds.IsComponent(codeDocument.GetFileKind())) { // Nothing to do here. return(syntaxTree); } var sectionVerifier = new NestedSectionVerifier(syntaxTree); return(sectionVerifier.Verify()); }
public static IReadOnlyList <CSharpStatementSyntax> GetCSharpStatements(this RazorSyntaxTree syntaxTree) { if (syntaxTree is null) { throw new ArgumentNullException(nameof(syntaxTree)); } // We want all nodes that represent Razor C# statements, @{ ... }. var statements = syntaxTree.Root.DescendantNodes().OfType <CSharpStatementSyntax>().ToList(); return(statements); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, SourceSpan location) { var completionItems = new List <RazorCompletionItem>(); if (AtDirectiveCompletionPoint(syntaxTree, location)) { var directiveCompletions = GetDirectiveCompletionItems(syntaxTree); completionItems.AddRange(directiveCompletions); } return(completionItems); }
private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider) { var sourceDocument = RazorSourceDocument.Create(documentContent, RazorSourceDocumentProperties.Default); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument); var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, DefaultTagHelpers); var completionQueryLocation = new SourceSpan(queryIndex, length: 0); var razorCompletionItems = componentCompletionProvider.GetCompletionItems(syntaxTree, tagHelperDocumentContext, completionQueryLocation); var completionList = RazorCompletionEndpoint.CreateLSPCompletionList(razorCompletionItems, new CompletionListCache(), new[] { ExtendedCompletionItemKinds.TagHelper }); return(completionList); }
private static RazorCodeDocument CreateCodeDocument(string text) { var codeDocument = TestRazorCodeDocument.CreateEmpty(); var sourceDocument = TestRazorSourceDocument.Create(text); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(syntaxTree); var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, Enumerable.Empty <TagHelperDescriptor>()); codeDocument.SetTagHelperContext(tagHelperDocumentContext); return(codeDocument); }
public void AtValidContentKind_ReturnsFalseAtMarkup() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("<p></p>")); var changePosition = 2; // Act var result = BraceSmartIndenter.AtValidContentKind(changePosition, syntaxTree); // Assert Assert.False(result); }
public void AtApplicableRazorBlock_AtExplicitCodeBlocksCode_ReturnsTrue() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@{}")); var changePosition = 2; // Act var result = BraceSmartIndenter.AtApplicableRazorBlock(changePosition, syntaxTree); // Assert Assert.True(result); }
public void AtApplicableRazorBlock_WhenNoOwner_ReturnsFalse() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@DateTime.Now")); var changePosition = 14; // 1 after the end of the content // Act var result = BraceSmartIndenter.AtApplicableRazorBlock(changePosition, syntaxTree); // Assert Assert.False(result); }
public void AtApplicableRazorBlock_AtMarkup_ReturnsFalse() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("<p></p>")); var changePosition = 2; // Act var result = BraceSmartIndenter.AtApplicableRazorBlock(changePosition, syntaxTree); // Assert Assert.False(result); }
public void AtValidContentKind_ReturnsTrueAtCode() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@{}")); var changePosition = 2; // Act var result = BraceSmartIndenter.AtValidContentKind(changePosition, syntaxTree); // Assert Assert.True(result); }
public void Parse_CanParseEmptyDocument() { // Arrange var source = TestRazorSourceDocument.Create(string.Empty); // Act var syntaxTree = RazorSyntaxTree.Parse(source); // Assert Assert.NotNull(syntaxTree); Assert.Empty(syntaxTree.Diagnostics); }
public static void Verify(RazorSyntaxTree syntaxTree, bool ensureFullFidelity = true) { var verifier = new Verifier(syntaxTree.Source); verifier.Visit(syntaxTree.Root); if (ensureFullFidelity) { var syntaxTreeString = syntaxTree.Root.ToFullString(); var builder = new StringBuilder(syntaxTree.Source.Length); for (var i = 0; i < syntaxTree.Source.Length; i++) { builder.Append(syntaxTree.Source[i]); } var sourceString = builder.ToString(); // Make sure the syntax tree contains all of the text in the document. Assert.Equal(sourceString, syntaxTreeString); // Ensure all source is locatable for (var i = 0; i < syntaxTree.Source.Length; i++) { var span = new SourceSpan(i, 0); var location = new SourceChange(span, string.Empty); var owner = syntaxTree.Root.LocateOwner(location); if (owner == null) { var snippetStartIndex = Math.Max(0, i - 10); var snippetStartLength = i - snippetStartIndex; var snippetStart = new char[snippetStartLength]; syntaxTree.Source.CopyTo(snippetStartIndex, snippetStart, 0, snippetStartLength); var snippetEndIndex = Math.Min(syntaxTree.Source.Length - 1, i + 10); var snippetEndLength = snippetEndIndex - i; var snippetEnd = new char[snippetEndLength]; syntaxTree.Source.CopyTo(i, snippetEnd, 0, snippetEndLength); var snippet = new char[snippetStart.Length + snippetEnd.Length + 1]; snippetStart.CopyTo(snippet, 0); snippet[snippetStart.Length] = '|'; snippetEnd.CopyTo(snippet, snippetStart.Length + 1); var snippetString = new string(snippet); throw new XunitException( $@"Could not locate Syntax Node owner at position '{i}': {snippetString}"); } } } }
public static IReadOnlyList <TagHelperSpanInternal> GetTagHelperSpans(this RazorSyntaxTree syntaxTree) { if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } var visitor = new TagHelperSpanVisitor(syntaxTree.Source); visitor.Visit(syntaxTree.Root); return(visitor.TagHelperSpans); }
public static IReadOnlyList <FormattingSpan> GetFormattingSpans(this RazorSyntaxTree syntaxTree) { if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } var visitor = new FormattingVisitor(syntaxTree.Source); visitor.Visit(syntaxTree.Root); return(visitor.FormattingSpans); }
public void AtApplicableRazorBlock_AtMetacode_ReturnsTrue() { // Arrange var parseOptions = RazorParserOptions.Create(options => options.Directives.Add(FunctionsDirective.Directive)); var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@functions {}"), parseOptions); var changePosition = 12; // Act var result = BraceSmartIndenter.AtApplicableRazorBlock(changePosition, syntaxTree); // Assert Assert.True(result); }
public void SetRazorSyntaxTree_SetsSyntaxTree() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); var expected = RazorSyntaxTree.Parse(codeDocument.Source); // Act codeDocument.SetSyntaxTree(expected); // Assert Assert.Same(expected, codeDocument.Items[typeof(RazorSyntaxTree)]); }
private static RazorSyntaxTree CreateSyntaxTree(string text, params DirectiveDescriptor[] directives) { var sourceDocument = TestRazorSourceDocument.Create(text); var options = RazorParserOptions.Create(builder => { foreach (var directive in directives) { builder.Directives.Add(directive); } }); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument, options); return(syntaxTree); }
private void VerifyPartialParseTree(TestParserManager manager, string content, string expectedCode = null) { if (expectedCode != null) { // Verify if the syntax tree represents the expected input. var syntaxTreeContent = manager.PartialParsingSyntaxTreeRoot.ToFullString(); Assert.Contains(expectedCode, syntaxTreeContent, StringComparison.Ordinal); } var sourceDocument = TestRazorSourceDocument.Create(content); var syntaxTree = RazorSyntaxTree.Create(manager.PartialParsingSyntaxTreeRoot, sourceDocument, manager.CurrentSyntaxTree.Diagnostics, manager.CurrentSyntaxTree.Options); BaselineTest(syntaxTree); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, TagHelperDocumentContext tagHelperDocumentContext, SourceSpan location) { if (syntaxTree is null) { throw new ArgumentNullException(nameof(syntaxTree)); } if (tagHelperDocumentContext is null) { throw new ArgumentNullException(nameof(tagHelperDocumentContext)); } var change = new SourceChange(location, string.Empty); var owner = syntaxTree.Root.LocateOwner(change); if (owner == null) { Debug.Fail("Owner should never be null."); return(Array.Empty <RazorCompletionItem>()); } var parent = owner.Parent; if (_htmlFactsService.TryGetElementInfo(parent, out var containingTagNameToken, out var attributes) && containingTagNameToken.Span.IntersectsWith(location.AbsoluteIndex)) { var stringifiedAttributes = _tagHelperFactsService.StringifyAttributes(attributes); var elementCompletions = GetElementCompletions(parent, containingTagNameToken.Content, stringifiedAttributes, tagHelperDocumentContext); return(elementCompletions); } if (_htmlFactsService.TryGetAttributeInfo( parent, out containingTagNameToken, out var prefixLocation, out var selectedAttributeName, out var selectedAttributeNameLocation, out attributes) && (selectedAttributeName == null || selectedAttributeNameLocation?.IntersectsWith(location.AbsoluteIndex) == true || (prefixLocation?.IntersectsWith(location.AbsoluteIndex) ?? false))) { var stringifiedAttributes = _tagHelperFactsService.StringifyAttributes(attributes); var attributeCompletions = GetAttributeCompletions(parent, containingTagNameToken.Content, selectedAttributeName, stringifiedAttributes, tagHelperDocumentContext); return(attributeCompletions); } // Invalid location for TagHelper completions. return(Array.Empty <RazorCompletionItem>()); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, TagHelperDocumentContext tagHelperDocumentContext, SourceSpan location) { if (syntaxTree is null) { throw new ArgumentNullException(nameof(syntaxTree)); } if (tagHelperDocumentContext is null) { throw new ArgumentNullException(nameof(tagHelperDocumentContext)); } if (!FileKinds.IsComponent(syntaxTree.Options.FileKind)) { // Directive attributes are only supported in components return(Array.Empty <RazorCompletionItem>()); } var change = new SourceChange(location, string.Empty); var owner = syntaxTree.Root.LocateOwner(change); if (owner == null) { return(Array.Empty <RazorCompletionItem>()); } if (!TryGetAttributeInfo(owner, out var attributeName, out var attributeNameLocation, out _, out _)) { // Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions. return(Array.Empty <RazorCompletionItem>()); } if (!attributeNameLocation.IntersectsWith(location.AbsoluteIndex)) { // We're trying to retrieve completions on a portion of the name that is not supported (such as a parameter). return(Array.Empty <RazorCompletionItem>()); } if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes)) { // This should never be the case, it means that we're operating on an attribute that doesn't have a tag. return(Array.Empty <RazorCompletionItem>()); } // At this point we've determined that completions have been requested for the name portion of the selected attribute. var completionItems = GetAttributeCompletions(attributeName, containingTagName, attributes, tagHelperDocumentContext); return(completionItems); }
public override IReadOnlyList <TagHelperSpan> GetTagHelperSpans(RazorSyntaxTree syntaxTree) { if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } var results = new List <TagHelperSpan>(); List <Block> toProcess = new List <Block>(); List <Block> blockChildren = new List <Block>(); 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); }
private IEnumerable <TextEdit> FormatRazor(FormattingContext context, RazorSyntaxTree syntaxTree) { var edits = new List <TextEdit>(); var source = syntaxTree.Source; foreach (var node in syntaxTree.Root.DescendantNodes()) { // Disclaimer: CSharpCodeBlockSyntax is used a _lot_ in razor so these methods are probably // being overly careful to only try to format syntax forms they care about. TryFormatCSharpCodeBlock(context, edits, source, node); TryFormatSingleLineDirective(context, edits, source, node); } return(edits); }
protected override void ExecuteCore(RazorCodeDocument codeDocument) { var options = codeDocument.GetParserOptions() ?? _optionsFeature.GetOptions(); var syntaxTree = RazorSyntaxTree.Parse(codeDocument.Source, options); codeDocument.SetSyntaxTree(syntaxTree); var importSyntaxTrees = new RazorSyntaxTree[codeDocument.Imports.Count]; for (var i = 0; i < codeDocument.Imports.Count; i++) { importSyntaxTrees[i] = RazorSyntaxTree.Parse(codeDocument.Imports[i], options); } codeDocument.SetImportSyntaxTrees(importSyntaxTrees); }
public void GetAndSetImportSyntaxTrees_ReturnsSyntaxTrees() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); var expected = new[] { RazorSyntaxTree.Parse(codeDocument.Source), }; codeDocument.SetImportSyntaxTrees(expected); // Act var actual = codeDocument.GetImportSyntaxTrees(); // Assert Assert.Same(expected, actual); }