diff options
author | Mike Krüger <mkrueger@xamarin.com> | 2015-12-04 18:18:31 +0300 |
---|---|---|
committer | Mike Krüger <mkrueger@xamarin.com> | 2015-12-04 18:18:31 +0300 |
commit | 02d1120783c184fa95f9d82e5a7c984a9892e4fb (patch) | |
tree | 0e68f893aebf5870bd99f351c68fde555c508ada /main/src/addins/MonoDevelop.RegexToolkit | |
parent | 5d61bd9cb00996f1ac81734458327cc67069ece3 (diff) |
[RegexToolkit] Add regex validation utility code action.
Diffstat (limited to 'main/src/addins/MonoDevelop.RegexToolkit')
4 files changed, 154 insertions, 4 deletions
diff --git a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit.csproj b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit.csproj index 785be8556a..1338983d0f 100644 --- a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit.csproj +++ b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit.csproj @@ -62,6 +62,25 @@ <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> <SpecificVersion>False</SpecificVersion> </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp"> + <HintPath>..\..\..\external\roslyn\Binaries\Release\Microsoft.CodeAnalysis.CSharp.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"> + <HintPath>..\..\..\external\roslyn\Binaries\Release\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis"> + <HintPath>..\..\..\build\bin\Microsoft.CodeAnalysis.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Workspaces"> + <HintPath>..\..\..\external\roslyn\Binaries\Release\Microsoft.CodeAnalysis.Workspaces.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.AttributedModel"> + <HintPath>..\..\..\external\roslyn\Binaries\Release\System.Composition.AttributedModel.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> @@ -94,6 +113,7 @@ <Compile Include="MonoDevelop.RegexToolkit\ElementHelpWidget.cs" /> <Compile Include="gtk-gui\MonoDevelop.RegexToolkit.ElementHelpWidget.cs" /> <Compile Include="AddinInfo.cs" /> + <Compile Include="MonoDevelop.RegexToolkit\ValidateActionCodeRefactoringProvider.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="gtk-gui\gui.stetic"> diff --git a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/Commands.cs b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/Commands.cs index 482dbcaded..9de1aa2131 100644 --- a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/Commands.cs +++ b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/Commands.cs @@ -91,18 +91,24 @@ namespace MonoDevelop.RegexToolkit { protected override void Run () { + RunRegexWindow (); + } + + public static RegexToolkitWidget RunRegexWindow () + {
foreach (var document in IdeApp.Workbench.Documents) { if (document.Window.ViewContent.Control is RegexToolkitWidget) { document.Window.SelectWindow (); - return; + return (RegexToolkitWidget)document.Window.ViewContent.Control; } } var regexToolkit = new RegexToolkitWidget (); var newDocument = IdeApp.Workbench.OpenDocument (new ViewOnlyContent (regexToolkit, GettextCatalog.GetString ("Regex Toolkit")), true); - + var elementHelp = new ElementHelpWidget (newDocument.Window, regexToolkit); - + newDocument.Window.AttachViewContent (new DefaultAttachableViewContent (elementHelp, GettextCatalog.GetString ("Elements"))); + return regexToolkit; } } diff --git a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/RegexToolkitWidget.cs b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/RegexToolkitWidget.cs index ecd1defcba..475f81888b 100644 --- a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/RegexToolkitWidget.cs +++ b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/RegexToolkitWidget.cs @@ -42,7 +42,14 @@ namespace MonoDevelop.RegexToolkit TreeStore resultStore; Thread regexThread; - + public string Regex { + get { + return entryRegEx.Text; + } + set { + entryRegEx.Text = value; + } + } public RegexToolkitWidget () { this.Build (); diff --git a/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/ValidateActionCodeRefactoringProvider.cs b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/ValidateActionCodeRefactoringProvider.cs new file mode 100644 index 0000000000..347febabf8 --- /dev/null +++ b/main/src/addins/MonoDevelop.RegexToolkit/MonoDevelop.RegexToolkit/ValidateActionCodeRefactoringProvider.cs @@ -0,0 +1,117 @@ +// +// ValidateActionCodeRefactoringProvider.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Threading; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Formatting; +using MonoDevelop.Core; +using MonoDevelop.RegexToolkit; + +namespace RefactoringEssentials.CSharp.CodeRefactorings +{ + [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = "Validate regular expression")] + public class ValidateActionCodeRefactoringProvider : CodeRefactoringProvider + { + public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) + { + var document = context.Document; + if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) + return; + var span = context.Span; + if (!span.IsEmpty) + return; + var cancellationToken = context.CancellationToken; + if (cancellationToken.IsCancellationRequested) + return; + + var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + //if (model.IsFromGeneratedCode(cancellationToken)) + // return; + var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + if (!root.Span.Contains (span)) + return; + var node = root.FindNode(span, false, true); + if (!node.IsKind(SyntaxKind.StringLiteralExpression)) + return; + var argument = node.Parent as ArgumentSyntax; + if (argument == null) + return; + var list = argument.Parent as ArgumentListSyntax; + + var invocation = argument.Parent?.Parent as InvocationExpressionSyntax; + if (invocation != null) { + var info = model.GetSymbolInfo (invocation); + if (!IsRegexMatchMethod (info) || list.Arguments [1] != argument) + return; + } + + var oce = argument.Parent?.Parent as ObjectCreationExpressionSyntax; + if (oce != null) { + var info = model.GetSymbolInfo (oce); + if (!IsRegexType (info.Symbol.ContainingType) || list.Arguments [0] != argument) + return; + } + + var regex = model.GetConstantValue (node); + if (!regex.HasValue) + return; + + context.RegisterRefactoring (CodeAction.Create( + GettextCatalog.GetString("Validate regular expression"), + t2 => { + ShowRegexToolkitHandler.RunRegexWindow ().Regex = regex.Value.ToString (); + return Task.FromResult(document); + } + )); + } + + internal static bool IsRegexMatchMethod (SymbolInfo symbolInfo) + { + var symbol = symbolInfo.Symbol; + if (symbol == null) + return false; + return IsRegexType (symbol.ContainingType) && symbol.IsStatic && (symbol.Name == "IsMatch" || symbol.Name == "Match" || symbol.Name == "Matches"); + } + + internal static bool IsRegexConstructor (SymbolInfo symbolInfo) + { + return symbolInfo.Symbol?.ContainingType is INamedTypeSymbol && IsRegexType (symbolInfo.Symbol.ContainingType); + } + + internal static bool IsRegexType (INamedTypeSymbol containingType) + { + return containingType != null && containingType.Name == "Regex" && containingType.ContainingNamespace.ToDisplayString () == "System.Text.RegularExpressions"; + } + } +} |