/// <summary> /// Gets the eligible extension methods. /// </summary> /// <param name="substituteInferredTypes"> /// Specifies whether to produce a <see cref="SpecializedMethod"/> /// when type arguments could be inferred from <see cref="TargetType"/>. /// This setting is only used for inferred types and has no effect if the type parameters are /// specified explicitly. /// </param> /// <remarks> /// The results are stored in nested lists because they are grouped by using scope. /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }", /// the return value will be /// new List { /// new List { all extensions from MoreExtensions }, /// new List { all extensions from SomeExtensions } /// } /// </remarks> public IEnumerable <IEnumerable <IMethod> > GetEligibleExtensionMethods(bool substituteInferredTypes) { var result = new List <List <IMethod> >(); foreach (var methodGroup in GetExtensionMethods()) { var outputGroup = new List <IMethod>(); foreach (var method in methodGroup) { IType[] inferredTypes; if (CSharpResolver.IsEligibleExtensionMethod(this.TargetType, method, true, out inferredTypes)) { if (substituteInferredTypes && inferredTypes != null) { outputGroup.Add(method.Specialize(new TypeParameterSubstitution(null, inferredTypes))); } else { outputGroup.Add(method); } } } if (outputGroup.Count > 0) { result.Add(outputGroup); } } return(result); }
static IEnumerable <IType> GetAllValidTypesFromInvocation(CSharpAstResolver resolver, InvocationExpression invoke, AstNode parameter) { int index = GetArgumentIndex(invoke.Arguments, parameter); if (index < 0) { yield break; } var targetResult = resolver.Resolve(invoke.Target) as MethodGroupResolveResult; if (targetResult != null) { foreach (var method in targetResult.Methods) { if (index < method.Parameters.Count) { if (method.Parameters [index].IsParams) { var arrayType = method.Parameters [index].Type as ArrayType; if (arrayType != null) { yield return(arrayType.ElementType); } } yield return(method.Parameters [index].Type); } } foreach (var extMethods in targetResult.GetExtensionMethods()) { foreach (var extMethod in extMethods) { IType[] inferredTypes; var m = extMethod; if (CSharpResolver.IsEligibleExtensionMethod(targetResult.TargetType, extMethod, true, out inferredTypes)) { if (inferredTypes != null) { m = extMethod.Specialize(new TypeParameterSubstitution(null, inferredTypes)); } } int correctedIndex = index + 1; if (correctedIndex < m.Parameters.Count) { if (m.Parameters [correctedIndex].IsParams) { var arrayType = m.Parameters [correctedIndex].Type as ArrayType; if (arrayType != null) { yield return(arrayType.ElementType); } } yield return(m.Parameters [correctedIndex].Type); } } } } }
IEnumerable <CodeAction> GetActionsForExtensionMethodInvocation(RefactoringContext context, InvocationExpression invocation) { var rr = context.Resolve(invocation) as UnknownMethodResolveResult; if (rr == null) { return(EmptyList <CodeAction> .Instance); } var lookup = new MemberLookup(null, context.Compilation.MainAssembly); HashSet <string> namespaces = new HashSet <string>(); List <CodeAction> result = new List <CodeAction>(); foreach (var typeDefinition in context.Compilation.GetAllTypeDefinitions()) { if (!(typeDefinition.HasExtensionMethods && lookup.IsAccessible(typeDefinition, false))) { continue; } foreach (var method in typeDefinition.Methods.Where(m => m.IsExtensionMethod && m.Name == rr.MemberName)) { IType[] inferredTypes; if (CSharpResolver.IsEligibleExtensionMethod(rr.TargetType, method, true, out inferredTypes)) { // avoid offering the same namespace twice if (namespaces.Add(typeDefinition.Namespace)) { result.Add(NewUsingAction(context, invocation, typeDefinition.Namespace)); } break; // continue with the next type } } } return(result); }
/// <summary> /// Gets the eligible extension methods. /// </summary> /// <param name="substituteInferredTypes"> /// Specifies whether to produce a <c>SpecializedMethod</c> /// when type arguments could be inferred from <see cref="TargetType"/>. /// This setting is only used for inferred types and has no effect if the type parameters are /// specified explicitly. /// </param> /// <remarks> /// The results are stored in nested lists because they are grouped by using scope. /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }", /// the return value will be /// new List { /// new List { all extensions from MoreExtensions }, /// new List { all extensions from SomeExtensions } /// } /// </remarks> public IEnumerable <IEnumerable <IMethod> > GetEligibleExtensionMethods(bool substituteInferredTypes) { var result = new List <List <IMethod> >(); foreach (var methodGroup in GetExtensionMethods()) { var outputGroup = new List <IMethod>(); foreach (var method in methodGroup) { if (CSharpResolver.IsEligibleExtensionMethod(this.TargetType, method, true, out IType[] inferredTypes))
public void Run() { using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor(true, true)) { foreach (var project in IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects()) { var comp = TypeSystemService.GetCompilation(project); foreach (var type in comp.MainAssembly.GetAllTypeDefinitions()) { if (!type.IsStatic) { continue; } foreach (var method in type.GetMethods(m => m.IsStatic)) { if (!method.IsExtensionMethod) { continue; } IType[] ifTypes; var typeDef = comp.Import(entity); if (typeDef == null) { continue; } if (!CSharpResolver.IsEligibleExtensionMethod(typeDef, method, true, out ifTypes)) { continue; } var tf = TextFileProvider.Instance.GetReadOnlyTextEditorData(method.Region.FileName); var start = tf.LocationToOffset(method.Region.Begin); tf.SearchRequest.SearchPattern = method.Name; var sr = tf.SearchForward(start); if (sr != null) { start = sr.Offset; } monitor.ReportResult(new MemberReference(method, method.Region, start, method.Name.Length)); } } } } }
public static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, IMethod method, IReadOnlyList <IType> typeArguments, ResolveResult target, ResolveResult[] arguments, string[] argumentNames) { if (target is LambdaResolveResult) { return(false); } var rr = resolver.ResolveMemberAccess(target, method.Name, typeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult; if (rr == null) { return(false); } var or = rr.PerformOverloadResolution(resolver.CurrentTypeResolveContext.Compilation, arguments, argumentNames, allowExtensionMethods: true); if (or == null || or.IsAmbiguous) { return(false); } return(method.Equals(or.GetBestCandidateWithSubstitutedTypeArguments()) && CSharpResolver.IsEligibleExtensionMethod(target.Type, method, useTypeInference: false, out _)); }
static IEnumerable <PossibleNamespace> GetPossibleNamespaces(Document doc, AstNode node, ResolveResult resolveResult, DocumentLocation location) { var unit = doc.ParsedDocument.GetAst <SyntaxTree> (); if (unit == null) { yield break; } var project = doc.Project; if (project == null) { yield break; } int tc = GetTypeParameterCount(node); var attribute = unit.GetNodeAt <ICSharpCode.NRefactory.CSharp.Attribute> (location); bool isInsideAttributeType = attribute != null && attribute.Type.Contains(location); var compilations = new List <Tuple <ICompilation, MonoDevelop.Projects.ProjectReference> > (); compilations.Add(Tuple.Create(doc.Compilation, (MonoDevelop.Projects.ProjectReference)null)); var referencedItems = IdeApp.Workspace != null?project.GetReferencedItems(IdeApp.Workspace.ActiveConfiguration).ToList() : (IEnumerable <SolutionItem>) new SolutionItem[0]; var solution = project != null ? project.ParentSolution : null; if (solution != null) { foreach (var curProject in solution.GetAllProjects()) { if (curProject == project || referencedItems.Contains(curProject)) { continue; } var comp = TypeSystemService.GetCompilation(curProject); if (comp == null) { continue; } compilations.Add(Tuple.Create(comp, new MonoDevelop.Projects.ProjectReference(curProject))); } } var netProject = project as DotNetProject; if (netProject == null) { yield break; } var frameworkLookup = TypeSystemService.GetFrameworkLookup(netProject); if (resolveResult is UnknownMemberResolveResult) { var umResult = (UnknownMemberResolveResult)resolveResult; foreach (var r in frameworkLookup.LookupExtensionMethod(umResult.MemberName)) { var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName(r.FullName, r.Package, netProject.TargetFramework); if (systemAssembly == null) { continue; } compilations.Add(Tuple.Create(TypeSystemService.GetCompilation(systemAssembly, doc.Compilation), new MonoDevelop.Projects.ProjectReference(systemAssembly))); } } bool foundIdentifier = false; var lookup = new MemberLookup(null, doc.Compilation.MainAssembly); foreach (var comp in compilations) { var compilation = comp.Item1; var requiredReference = comp.Item2; if (resolveResult is AmbiguousTypeResolveResult) { if (compilation != doc.Compilation) { continue; } var aResult = resolveResult as AmbiguousTypeResolveResult; var file = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile; var scope = file.GetUsingScope(location).Resolve(compilation); while (scope != null) { foreach (var u in scope.Usings) { foreach (var typeDefinition in u.Types) { if (typeDefinition.Name == aResult.Type.Name && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { yield return(new PossibleNamespace(typeDefinition.Namespace, true, requiredReference)); } } } scope = scope.Parent; } } var allTypes = compilation == doc.Compilation ? compilation.GetAllTypeDefinitions() : compilation.MainAssembly.GetAllTypeDefinitions(); if (resolveResult is UnknownIdentifierResolveResult) { var uiResult = resolveResult as UnknownIdentifierResolveResult; string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : uiResult.Identifier; foreach (var typeDefinition in allTypes) { if (typeDefinition.Name == possibleAttributeName && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { if (typeDefinition.DeclaringTypeDefinition != null) { var builder = new TypeSystemAstBuilder(new CSharpResolver(doc.Compilation)); foundIdentifier = true; yield return(new PossibleNamespace(builder.ConvertType(typeDefinition.DeclaringTypeDefinition).ToString(), false, requiredReference)); } else { foundIdentifier = true; yield return(new PossibleNamespace(typeDefinition.Namespace, true, requiredReference)); } } } } if (resolveResult is UnknownMemberResolveResult) { var umResult = (UnknownMemberResolveResult)resolveResult; string possibleAttributeName = isInsideAttributeType ? umResult.MemberName + "Attribute" : umResult.MemberName; foreach (var typeDefinition in allTypes.Where(t => t.HasExtensionMethods)) { foreach (var method in typeDefinition.Methods.Where(m => m.IsExtensionMethod && m.Name == possibleAttributeName)) { IType[] inferredTypes; if (CSharpResolver.IsEligibleExtensionMethod( compilation.Import(umResult.TargetType), method, true, out inferredTypes )) { yield return(new PossibleNamespace(typeDefinition.Namespace, true, requiredReference)); goto skipType; } } skipType: ; } } if (resolveResult is ErrorResolveResult) { var identifier = unit != null?unit.GetNodeAt <Identifier> (location) : null; if (identifier != null) { var uiResult = resolveResult as UnknownIdentifierResolveResult; if (uiResult != null) { string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : uiResult.Identifier; foreach (var typeDefinition in allTypes) { if ((identifier.Name == possibleAttributeName) && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { yield return(new PossibleNamespace(typeDefinition.Namespace, true, requiredReference)); } } } } } } // Try to search framework types if (!foundIdentifier && resolveResult is UnknownIdentifierResolveResult) { var uiResult = resolveResult as UnknownIdentifierResolveResult; string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : uiResult.Identifier; foreach (var r in frameworkLookup.LookupIdentifier(possibleAttributeName, tc)) { var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName(r.FullName, r.Package, netProject.TargetFramework); if (systemAssembly == null) { continue; } yield return(new PossibleNamespace(r.Namespace, true, new MonoDevelop.Projects.ProjectReference(systemAssembly))); } } }
static IEnumerable <Tuple <string, bool> > GetPossibleNamespaces(Document doc, AstNode node, ResolveResult resolveResult, DocumentLocation location) { var unit = doc.ParsedDocument.GetAst <SyntaxTree> (); if (unit == null) { yield break; } int tc = GetTypeParameterCount(node); var attribute = unit.GetNodeAt <ICSharpCode.NRefactory.CSharp.Attribute> (location); bool isInsideAttributeType = attribute != null && attribute.Type.Contains(location); var compilation = doc.Compilation; var lookup = new MemberLookup(null, compilation.MainAssembly); if (resolveResult is AmbiguousTypeResolveResult) { var aResult = resolveResult as AmbiguousTypeResolveResult; var file = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile; var scope = file.GetUsingScope(location).Resolve(compilation); while (scope != null) { foreach (var u in scope.Usings) { foreach (var typeDefinition in u.Types) { if (typeDefinition.Name == aResult.Type.Name && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { yield return(Tuple.Create(typeDefinition.Namespace, true)); } } } scope = scope.Parent; } yield break; } if (resolveResult is UnknownIdentifierResolveResult) { var uiResult = resolveResult as UnknownIdentifierResolveResult; string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : null; foreach (var typeDefinition in compilation.GetAllTypeDefinitions()) { if ((typeDefinition.Name == uiResult.Identifier || typeDefinition.Name == possibleAttributeName) && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { if (typeDefinition.DeclaringTypeDefinition != null) { var builder = new TypeSystemAstBuilder(new CSharpResolver(doc.Compilation)); yield return(Tuple.Create(builder.ConvertType(typeDefinition.DeclaringTypeDefinition).ToString(), false)); } else { yield return(Tuple.Create(typeDefinition.Namespace, true)); } } } yield break; } if (resolveResult is UnknownMemberResolveResult) { var umResult = (UnknownMemberResolveResult)resolveResult; string possibleAttributeName = isInsideAttributeType ? umResult.MemberName + "Attribute" : null; foreach (var typeDefinition in compilation.GetAllTypeDefinitions().Where(t => t.HasExtensionMethods)) { foreach (var method in typeDefinition.Methods.Where(m => m.IsExtensionMethod && (m.Name == umResult.MemberName || m.Name == possibleAttributeName))) { IType[] inferredTypes; if (CSharpResolver.IsEligibleExtensionMethod( compilation.Import(umResult.TargetType), method, true, out inferredTypes )) { yield return(Tuple.Create(typeDefinition.Namespace, true)); goto skipType; } } skipType: ; } yield break; } if (resolveResult is ErrorResolveResult) { var identifier = unit != null?unit.GetNodeAt <Identifier> (location) : null; if (identifier != null) { var uiResult = resolveResult as UnknownIdentifierResolveResult; if (uiResult != null) { string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : null; foreach (var typeDefinition in compilation.GetAllTypeDefinitions()) { if ((identifier.Name == uiResult.Identifier || identifier.Name == possibleAttributeName) && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { yield return(Tuple.Create(typeDefinition.Namespace, true)); } } } } yield break; } }