diff --git a/Rider/README.md b/Rider/README.md index 645de57a..26235b56 100644 --- a/Rider/README.md +++ b/Rider/README.md @@ -1,4 +1,6 @@ -# RapidXaml for Rider and ReSharper +# RapidXaml for Rider [![Rider](https://img.shields.io/jetbrains/plugin/v/RIDER_PLUGIN_ID.svg?label=Rider&colorB=0A7BBB&style=for-the-badge&logo=rider)](https://plugins.jetbrains.com/plugin/RIDER_PLUGIN_ID) -[![ReSharper](https://img.shields.io/jetbrains/plugin/v/RESHARPER_PLUGIN_ID.svg?label=ReSharper&colorB=0A7BBB&style=for-the-badge&logo=resharper)](https://plugins.jetbrains.com/plugin/RESHARPER_PLUGIN_ID) + + + diff --git a/Rider/src/dotnet/ReSharperPlugin.RapidXaml/IRapidXamlZone.cs b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/IRapidXamlZone.cs index 0cfbe233..2ff6d351 100644 --- a/Rider/src/dotnet/ReSharperPlugin.RapidXaml/IRapidXamlZone.cs +++ b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/IRapidXamlZone.cs @@ -1,13 +1,14 @@ using JetBrains.Application.BuildScript.Application.Zones; using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp; +using JetBrains.ReSharper.Psi.Xaml; -namespace ReSharperPlugin.RapidXaml +namespace ReSharperPlugin.RapidXaml; + +[ZoneDefinition] +// [ZoneDefinitionConfigurableFeature("Title", "Description", IsInProductSection: false)] +public interface IRapidXamlZone : IZone, + IRequire, + IRequire { - [ZoneDefinition] - // [ZoneDefinitionConfigurableFeature("Title", "Description", IsInProductSection: false)] - public interface IRapidXamlZone : IZone - { - } -} +} \ No newline at end of file diff --git a/Rider/src/dotnet/ReSharperPlugin.RapidXaml/OutlineZoneMarker.cs b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/OutlineZoneMarker.cs new file mode 100644 index 00000000..8bb1f533 --- /dev/null +++ b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/OutlineZoneMarker.cs @@ -0,0 +1,8 @@ +using JetBrains.Application.BuildScript.Application.Zones; + +namespace ReSharperPlugin.RapidXaml; + +[ZoneMarker] +public class OutlineZoneMarker : IRequire +{ +} \ No newline at end of file diff --git a/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessor.cs b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessor.cs new file mode 100644 index 00000000..2647b740 --- /dev/null +++ b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessor.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Daemon.CodeFolding; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.ReSharper.Psi.Xml.Impl; +using JetBrains.ReSharper.Psi.Xml.Tree; + +namespace ReSharperPlugin.RapidXaml; + +public sealed class XamlNamespaceCodeFoldingProcessor : + XmlTreeVisitor, + ICodeFoldingProcessor +{ + private readonly Stack<(DocumentOffset offset, string regionText)> _regionStarts = + new Stack<(DocumentOffset offset, string regionText)>(); + + public bool InteriorShouldBeProcessed(ITreeNode element, FoldingHighlightingConsumer context) => true; + public bool IsProcessingFinished(FoldingHighlightingConsumer context) => false; + + public void ProcessBeforeInterior(ITreeNode element, FoldingHighlightingConsumer context) + { + if (!(element is IXmlTreeNode xamlElement)) + { + return; + } + + xamlElement.AcceptVisitor(this, context); + } + + public void ProcessAfterInterior(ITreeNode element, FoldingHighlightingConsumer context) + { + } + + public override bool Visit(IXmlTag tag, FoldingHighlightingConsumer context) + { + System.Diagnostics.Debug.WriteLine(tag); + + // If is IXamlTypeDeclaration + // If has multiple NamespaceAliases + // place fold start at the start position of the first + // place fold end at the end of the last one + + // TODO: use tag.GetDocumentRange() to review lines that shouldn't be included + // ((JetBrains.ReSharper.Psi.Xaml.Impl.Tree.XamlTypeDeclaration) tag).NamespaceAliases.myNodes[1].GetDocumentRange() + // TODO: review siblings to check that there's nothing else between aliases + + return base.Visit(tag, context); + } + + public override bool Visit(IXmlDocumentNode document, FoldingHighlightingConsumer context) + { + System.Diagnostics.Debug.WriteLine(document); + return base.Visit(document, context); + } + + public override bool Visit(IXmlCommentNode xmlComment, FoldingHighlightingConsumer context) + { + var commentText = xmlComment.CommentText.Trim(); + if (IsRegionStart(commentText, out var regionText)) + { + _regionStarts.Push((xmlComment.GetDocumentRange().StartOffset, regionText)); + return true; + } + + if (IsRegionEnd(commentText)) + { + if (_regionStarts.Count > 0) + { + var (regionStartOffset, placeholder) = _regionStarts.Pop(); + var regionEndRange = xmlComment.GetDocumentRange(); + var regionRange = regionEndRange.SetStartTo(regionStartOffset); + context.AddLowerPriorityFolding("XAML Region Regions Folding", regionRange, regionRange, + placeholder); + return true; + } + + // endregion without start + return false; + } + + return false; + } + + private const string RegionStartTag = "#region"; + private const string RegionEndTag = "#endregion"; + + private static bool IsRegionEnd(string commentText) + { + return (commentText.Contains(RegionEndTag)); + } + + private static bool IsRegionStart(string commentText, out string regionText) + { + if (commentText.StartsWith(RegionStartTag)) + { + regionText = commentText + .Substring(Math.Min(commentText.Length, RegionStartTag.Length + 1)) + .Trim(); + if (string.IsNullOrWhiteSpace(regionText)) + { + regionText = "#region"; + } + + return true; + } + + regionText = null; + return false; + } +} \ No newline at end of file diff --git a/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessorFactory.cs b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessorFactory.cs new file mode 100644 index 00000000..a0817870 --- /dev/null +++ b/Rider/src/dotnet/ReSharperPlugin.RapidXaml/XamlNamespaceCodeFoldingProcessorFactory.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JetBrains.ReSharper.Daemon.CodeFolding; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Xaml; + +namespace ReSharperPlugin.RapidXaml; + +[Language(typeof(XamlLanguage))] +public sealed class XamlNamespaceCodeFoldingProcessorFactory : ICodeFoldingProcessorFactory +{ + [NotNull] + public ICodeFoldingProcessor CreateProcessor() => new XamlNamespaceCodeFoldingProcessor(); +}