Example #1
0
        /// <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);
        }
Example #2
0
        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);
                        }
                    }
                }
            }
        }
Example #3
0
        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);
        }
Example #4
0
        /// <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));
                        }
                    }
                }
            }
        }
Example #6
0
        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;
            }
        }