diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Daemon/src/Analyzers/XmlDocAnalyzer.fs b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Daemon/src/Analyzers/XmlDocAnalyzer.fs index 6b5bc70c2c..2dbd8a3189 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Daemon/src/Analyzers/XmlDocAnalyzer.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Daemon/src/Analyzers/XmlDocAnalyzer.fs @@ -7,8 +7,8 @@ open JetBrains.ReSharper.Daemon.Xml.Stages.Analysis open JetBrains.ReSharper.Feature.Services.Daemon open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree -open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree +open JetBrains.ReSharper.Plugins.FSharp.Psi.Util open JetBrains.ReSharper.Plugins.FSharp.Util.XmlDocUtil open JetBrains.ReSharper.Psi.ExtensionsAPI open JetBrains.ReSharper.Psi.Tree diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Resolve/FSharpParameterUtil.cs b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Resolve/FSharpParameterUtil.cs index b7f94cc58f..7005775f09 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Resolve/FSharpParameterUtil.cs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Resolve/FSharpParameterUtil.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; using System.Linq; using FSharp.Compiler.Symbols; using JetBrains.Annotations; -using JetBrains.ReSharper.Plugins.FSharp.Psi.Impl; using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree; using JetBrains.ReSharper.Plugins.FSharp.Psi.Util; using JetBrains.ReSharper.Psi; -using JetBrains.ReSharper.Psi.ExtensionsAPI; using JetBrains.ReSharper.Psi.Resolve; -using JetBrains.ReSharper.Psi.Tree; -using JetBrains.Util; namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve { @@ -68,97 +63,5 @@ private static IDeclaredElement GetFieldDeclaredElement([NotNull] IReference ref var field = unionCase.Fields.FirstOrDefault(f => f.Name == reference.GetName()); return field?.GetDeclaredElement(referenceOwner.GetPsiModule(), referenceOwner); } - - public static IReadOnlyList> GetParametersGroupNames(ITreeNode node) => - (node switch - { - IBinding binding => binding.Expression is ILambdaExpr lambda - ? binding.ParameterPatterns.Select(GetParameterNames).Union(GetLambdaArgs(lambda)) - : binding.ParameterPatterns.Select(GetParameterNames), - - IBindingSignature bindingSignature => GetParameterNames(bindingSignature.ReturnTypeInfo.ReturnType), - IMemberDeclaration member => member.ParameterPatterns.Select(GetParameterNames), - // TODO: https://github.com/dotnet/fsharp/issues/13684 - //.Union(member.AccessorDeclarations.Select(t => t.ParameterPatterns.SelectMany(GetParameterNames))), - IConstructorSignature constructorSignature => GetParameterNames(constructorSignature.ReturnTypeInfo.ReturnType), - - IConstructorDeclaration constructorDeclaration => - new[] { GetParameterNames(constructorDeclaration.ParameterPatterns) }, - - IAbstractMemberDeclaration abstractMember => GetParameterNames(abstractMember.ReturnTypeInfo.ReturnType), - - IMemberSignature memberSignature => GetParameterNames(((IMemberSignatureOrDeclaration)memberSignature) - .ReturnTypeInfo.ReturnType), - - IUnionCaseDeclaration { TypeUsage: { } typeUsage } => GetParameterNames(typeUsage), - IUnionCaseDeclaration ucDecl => new[] { ucDecl.Fields.Select(t => (t.SourceName, (ITreeNode)t)) }, - - IFSharpTypeDeclaration { TypeRepresentation: IDelegateRepresentation repr } => - GetParameterNames(repr.TypeUsage), - - _ => EmptyList>.Enumerable - }) - .Select(t => t.ToIReadOnlyList()) - .ToIReadOnlyList(); - - private static bool IsSimplePattern(IFSharpPattern pattern, bool isTopLevel) => pattern.IgnoreInnerParens() switch - { - ILocalReferencePat or IAttribPat or ITypedPat or IWildPat => true, - IUnitPat => isTopLevel, - ITuplePat tuplePat => isTopLevel && tuplePat.PatternsEnumerable.All(t => IsSimplePattern(t, false)), - _ => false - }; - - private static IEnumerable> GetLambdaArgs(ILambdaExpr expr) - { - var lambdaParams = expr.Patterns; - var parameters = lambdaParams.Select(GetParameterNames); - if (expr.Expression is ILambdaExpr innerLambda && lambdaParams.All(pattern => IsSimplePattern(pattern, true))) - parameters = parameters.Union(GetLambdaArgs(innerLambda)); - return parameters; - } - - public static IEnumerable<(string, ITreeNode)> GetParameterNames(this IFSharpPattern pattern) - { - IEnumerable<(string, ITreeNode)> GetParameterNamesInternal(IFSharpPattern pat, bool isTopLevelParameter) - { - pat = pat.IgnoreInnerParens(true); - return pat switch - { - IParenPat { Pattern: { } innerPat } => GetParameterNamesInternal(innerPat, false), - ILocalReferencePat local => new[] { (local.SourceName, (ITreeNode)local) }, - IOptionalValPat opt => GetParameterNamesInternal(opt.Pattern, isTopLevelParameter), - ITypedPat typed => GetParameterNamesInternal(typed.Pattern, false), - IAttribPat attrib => GetParameterNamesInternal(attrib.Pattern, false), - IAsPat asPat => GetParameterNamesInternal(asPat.RightPattern, false), - ITuplePat tuplePat when isTopLevelParameter => - tuplePat.PatternsEnumerable.SelectMany(t => GetParameterNamesInternal(t, false)), - var x => new[] { (SharedImplUtil.MISSING_DECLARATION_NAME, (ITreeNode)x) } - }; - } - - return GetParameterNamesInternal(pattern, true); - } - - public static IEnumerable> GetParameterNames(this ITypeUsage pattern) => - pattern switch - { - IParenTypeUsage parenUsage => GetParameterNames(parenUsage.InnerTypeUsage), - IConstrainedTypeUsage constrained => GetParameterNames(constrained.TypeUsage), - IParameterSignatureTypeUsage local => - new[] - { - new[] - { - local.Identifier is { } identifier - ? (identifier.Name, (ITreeNode)identifier) - : (SharedImplUtil.MISSING_DECLARATION_NAME, null) - } - }, - IFunctionTypeUsage funPat => - GetParameterNames(funPat.ArgumentTypeUsage).Union(GetParameterNames(funPat.ReturnTypeUsage)), - ITupleTypeUsage tuplePat => tuplePat.Items.SelectMany(GetParameterNames), - _ => EmptyList>.Enumerable - }; } } diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/FSharpParametersUtil.cs b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/FSharpParametersUtil.cs new file mode 100644 index 0000000000..ccff74d58f --- /dev/null +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/FSharpParametersUtil.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Linq; +using JetBrains.ReSharper.Plugins.FSharp.Psi.Impl; +using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Util; + +public static class FSharpParameterUtil +{ + public static IReadOnlyList> GetParametersGroupNames(ITreeNode node) => + (node switch + { + IBinding binding => binding.Expression is ILambdaExpr lambda + ? binding.ParameterPatterns.Select(GetParameterNames).Union(GetLambdaArgs(lambda)) + : binding.ParameterPatterns.Select(GetParameterNames), + + IBindingSignature bindingSignature => GetParameterNames(bindingSignature.ReturnTypeInfo.ReturnType), + IMemberDeclaration member => member.ParameterPatterns.Select(GetParameterNames), + // TODO: https://github.com/dotnet/fsharp/issues/13684 + //.Union(member.AccessorDeclarations.Select(t => t.ParameterPatterns.SelectMany(GetParameterNames))), + IConstructorSignature constructorSignature => GetParameterNames(constructorSignature.ReturnTypeInfo.ReturnType), + + IConstructorDeclaration constructorDeclaration => + new[] { GetParameterNames(constructorDeclaration.ParameterPatterns) }, + + IAbstractMemberDeclaration abstractMember => GetParameterNames(abstractMember.ReturnTypeInfo.ReturnType), + + IMemberSignature memberSignature => GetParameterNames(((IMemberSignatureOrDeclaration)memberSignature) + .ReturnTypeInfo.ReturnType), + + IUnionCaseDeclaration { TypeUsage: { } typeUsage } => GetParameterNames(typeUsage), + IUnionCaseDeclaration ucDecl => new[] { ucDecl.Fields.Select(t => (t.SourceName, (ITreeNode)t)) }, + + IFSharpTypeDeclaration { TypeRepresentation: IDelegateRepresentation repr } => + GetParameterNames(repr.TypeUsage), + + _ => EmptyList>.Enumerable + }) + .Select(t => t.ToIReadOnlyList()) + .ToIReadOnlyList(); + + private static bool IsSimplePattern(IFSharpPattern pattern, bool isTopLevel) => pattern.IgnoreInnerParens() switch + { + ILocalReferencePat or IAttribPat or ITypedPat or IWildPat => true, + IUnitPat => isTopLevel, + ITuplePat tuplePat => isTopLevel && tuplePat.PatternsEnumerable.All(t => IsSimplePattern(t, false)), + _ => false + }; + + private static IEnumerable> GetLambdaArgs(ILambdaExpr expr) + { + var lambdaParams = expr.Patterns; + var parameters = lambdaParams.Select(GetParameterNames); + if (expr.Expression is ILambdaExpr innerLambda && lambdaParams.All(pattern => IsSimplePattern(pattern, true))) + parameters = parameters.Union(GetLambdaArgs(innerLambda)); + return parameters; + } + + public static IEnumerable<(string, ITreeNode)> GetParameterNames(this IFSharpPattern pattern) + { + IEnumerable<(string, ITreeNode)> GetParameterNamesInternal(IFSharpPattern pat, bool isTopLevelParameter) + { + pat = pat.IgnoreInnerParens(true); + return pat switch + { + IParenPat { Pattern: { } innerPat } => GetParameterNamesInternal(innerPat, false), + ILocalReferencePat local => new[] { (local.SourceName, (ITreeNode)local) }, + IOptionalValPat opt => GetParameterNamesInternal(opt.Pattern, isTopLevelParameter), + ITypedPat typed => GetParameterNamesInternal(typed.Pattern, false), + IAttribPat attrib => GetParameterNamesInternal(attrib.Pattern, false), + IAsPat asPat => GetParameterNamesInternal(asPat.RightPattern, false), + ITuplePat tuplePat when isTopLevelParameter => + tuplePat.PatternsEnumerable.SelectMany(t => GetParameterNamesInternal(t, false)), + var x => new[] { (SharedImplUtil.MISSING_DECLARATION_NAME, (ITreeNode)x) } + }; + } + + return GetParameterNamesInternal(pattern, true); + } + + public static IEnumerable> GetParameterNames(this ITypeUsage pattern) => + pattern switch + { + IParenTypeUsage parenUsage => GetParameterNames(parenUsage.InnerTypeUsage), + IConstrainedTypeUsage constrained => GetParameterNames(constrained.TypeUsage), + IParameterSignatureTypeUsage local => + new[] + { + new[] + { + local.Identifier is { } identifier + ? (identifier.Name, (ITreeNode)identifier) + : (SharedImplUtil.MISSING_DECLARATION_NAME, null) + } + }, + IFunctionTypeUsage funPat => + GetParameterNames(funPat.ArgumentTypeUsage).Union(GetParameterNames(funPat.ReturnTypeUsage)), + ITupleTypeUsage tuplePat => tuplePat.Items.SelectMany(GetParameterNames), + _ => EmptyList>.Enumerable + }; +} diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/XmlDocTemplateUtil.cs b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/XmlDocTemplateUtil.cs index 57c8b3aa02..97f27060db 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/XmlDocTemplateUtil.cs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Util/XmlDocTemplateUtil.cs @@ -1,6 +1,5 @@ using System.Linq; using System.Text; -using JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve; using JetBrains.ReSharper.Psi.ExtensionsAPI; using JetBrains.ReSharper.Psi.Tree;