IEnumerable <IMethod> CollectMethods(AstNode resolvedNode, MethodGroupResolveResult resolveResult) { var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); bool onlyStatic = false; if (resolvedNode is IdentifierExpression && currentMember != null && currentMember.IsStatic || resolveResult.TargetResult is TypeResolveResult) { onlyStatic = true; } foreach (var method in resolveResult.Methods) { if (method.IsConstructor) { continue; } if (!lookup.IsAccessible(method, true)) { continue; } if (onlyStatic && !method.IsStatic) { continue; } yield return(method); } foreach (var extMethods in resolveResult.GetEligibleExtensionMethods(true)) { foreach (var method in extMethods) { yield return(method); } } }
public override void VisitTypeDeclaration(TypeDeclaration declaration) { base.VisitTypeDeclaration(declaration); var result = ctx.Resolve(declaration) as TypeResolveResult; if (result == null || result.IsError) { return; } var baseType = result.Type.DirectBaseTypes.FirstOrDefault(t => !t.IsKnownType(KnownTypeCode.Object) && t.Kind != TypeKind.Interface); if (baseType != null) { var baseConstructor = baseType.GetConstructors(c => c.Parameters.Count == 0).FirstOrDefault(); var memberLookup = new MemberLookup(result.Type.GetDefinition(), ctx.Compilation.MainAssembly, false); if (baseConstructor == null || !memberLookup.IsAccessible(baseConstructor, true)) { var constructor = result.Type.GetConstructors(f => !f.IsSynthetic).FirstOrDefault(); if (constructor == null) { // If there are no constructors declared then the base constructor isn't being invoked this.AddIssue(declaration, baseType); } } } }
public ConstructorParameterDataProvider(int startOffset, CSharpCompletionTextEditorExtension ext, IType type, AstNode skipInitializer = null) : base(startOffset, ext) { this.type = type; var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext(ext.UnresolvedFileCompilation, ext.Document.Editor.Caret.Location) as CSharpTypeResolveContext; var lookup = new MemberLookup(ctx.CurrentTypeDefinition, ext.Compilation.MainAssembly); bool isProtectedAllowed = false; var typeDefinition = type.GetDefinition(); if (ctx.CurrentTypeDefinition != null && typeDefinition != null) { isProtectedAllowed = ctx.CurrentTypeDefinition.IsDerivedFrom(ctx.CurrentTypeDefinition.Compilation.Import(typeDefinition)); } foreach (var method in type.GetConstructors()) { if (!lookup.IsAccessible(method, isProtectedAllowed)) { continue; } if (!method.IsBrowsable()) { continue; } if (skipInitializer != null && skipInitializer.Parent.StartLocation == method.Region.Begin) { continue; } methods.Add(method); } methods.Sort(MethodComparer); }
OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method, TranslatedExpression target, IType[] typeArguments, IList <TranslatedExpression> arguments) { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments); if (expectedTargetDetails.CallOpCode == OpCode.NewObj) { foreach (IMethod ctor in method.DeclaringType.GetConstructors()) { if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) { or.AddCandidate(ctor); } } } else { var result = lookup.Lookup(target.ResolveResult, method.Name, EmptyList <IType> .Instance, true) as MethodGroupResolveResult; if (result == null) { return(OverloadResolutionErrors.AmbiguousMatch); } or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); } if (or.BestCandidateErrors != OverloadResolutionErrors.None) { return(or.BestCandidateErrors); } if (!IsAppropriateCallTarget(expectedTargetDetails, method, or.GetBestCandidateWithSubstitutedTypeArguments())) { return(OverloadResolutionErrors.AmbiguousMatch); } return(OverloadResolutionErrors.None); }
public override void VisitConstructorDeclaration(ConstructorDeclaration declaration) { var result = ctx.Resolve(declaration) as MemberResolveResult; if (result == null || result.IsError) { return; } var baseType = result.Member.DeclaringType.DirectBaseTypes.FirstOrDefault(t => !t.IsKnownType(KnownTypeCode.Object) && t.Kind != TypeKind.Interface); if (baseType != null) { var baseConstructor = baseType.GetConstructors(c => c.Parameters.Count == 0).FirstOrDefault(); var memberLookup = new MemberLookup(result.Member.DeclaringType.GetDefinition(), ctx.Compilation.MainAssembly, false); if (baseConstructor == null || !memberLookup.IsAccessible(baseConstructor, true)) { this.initializerInvoked = false; this.initializer = null; base.VisitConstructorDeclaration(declaration); if (!this.initializerInvoked) { int argumentCount = initializer != null ? initializer.Arguments.Count : 0; this.AddIssue(declaration, baseType, argumentCount); } } } }
IEnumerable <IProperty> GetAccessibleIndexers(IType type) { var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); var properties = new List <IProperty>(); foreach (var property in type.GetProperties()) { if (!property.IsIndexer) { continue; } if (!lookup.IsAccessible(property, true)) { continue; } if (property.IsShadowing) { for (int j = 0; j < properties.Count; j++) { if (ParameterListComparer.Instance.Equals(properties[j].Parameters, property.Parameters)) { properties.RemoveAt(j); j--; } } } properties.Add(property); } return(properties); }
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); }
private IEnumerable <IMethod> FilterMethodsForAccessibility(IType type, IEnumerable <IMethod> methods) { var typeResolveContext = context.TypeResolveContextAtCaret; var lookup = new MemberLookup(typeResolveContext.CurrentTypeDefinition, typeResolveContext.Compilation.MainAssembly); bool protectedAccessAllowed = lookup.IsProtectedAccessAllowed(type); return(protectedAccessAllowed ? methods : methods.Where(x => !x.IsProtected)); }
TranslatedExpression HandleDelegateConstruction(CallInstruction inst) { ILInstruction func = inst.Arguments[1]; IMethod method; switch (func.OpCode) { case OpCode.LdFtn: method = ((LdFtn)func).Method; break; case OpCode.LdVirtFtn: method = ((LdVirtFtn)func).Method; break; default: method = (IMethod)typeSystem.Resolve(((ILFunction)func).Method); break; } var target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn); var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, true) as MethodGroupResolveResult; if (result == null) { target = target.ConvertTo(method.DeclaringType, expressionBuilder); } else { or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); if (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn)) { target = target.ConvertTo(method.DeclaringType, expressionBuilder); } } var mre = new MemberReferenceExpression(target, method.Name); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre) // .WithAnnotation(new DelegateConstruction.Annotation(func.OpCode == OpCode.LdVirtFtn, target, method.Name)) .WithILInstruction(inst) .WithRR(new ConversionResolveResult( inst.Method.DeclaringType, new MemberResolveResult(target.ResolveResult, method), // TODO handle extension methods capturing the first argument Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false))); if (func is ILFunction) { return(expressionBuilder.TranslateFunction(oce, target, (ILFunction)func)); } else { return(oce); } }
IEnumerable <IMethod> CollectMethods(AstNode resolvedNode, MethodGroupResolveResult resolveResult) { var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); bool onlyStatic = false; if (resolvedNode is IdentifierExpression && currentMember != null && currentMember.IsStatic || resolveResult.TargetResult is TypeResolveResult) { onlyStatic = true; } var methods = new List <IMethod>(); foreach (var method in resolveResult.Methods) { if (method.IsConstructor) { continue; } if (!lookup.IsAccessible(method, true)) { continue; } if (onlyStatic && !method.IsStatic) { continue; } if (method.IsShadowing) { for (int j = 0; j < methods.Count; j++) { if (ParameterListComparer.Instance.Equals(methods[j].Parameters, method.Parameters)) { methods.RemoveAt(j); j--; } } } methods.Add(method); } foreach (var m in methods) { yield return(m); } foreach (var extMethods in resolveResult.GetEligibleExtensionMethods(true)) { foreach (var method in extMethods) { if (methods.Contains(method)) { continue; } yield return(new ReducedExtensionMethod(method)); } } }
ExpressionWithResolveResult HandleAccessorCall(ExpectedTargetDetails expectedTargetDetails, IMethod method, TranslatedExpression target, IList <TranslatedExpression> arguments) { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var result = lookup.Lookup(target.ResolveResult, method.AccessorOwner.Name, EmptyList <IType> .Instance, isInvocation: false); if (result.IsError || (result is MemberResolveResult && !IsAppropriateCallTarget(expectedTargetDetails, method.AccessorOwner, ((MemberResolveResult)result).Member))) { target = target.ConvertTo(method.AccessorOwner.DeclaringType, expressionBuilder); } var rr = new MemberResolveResult(target.ResolveResult, method.AccessorOwner); if (method.ReturnType.IsKnownType(KnownTypeCode.Void)) { var value = arguments.Last(); arguments.Remove(value); TranslatedExpression expr; if (arguments.Count == 0) { expr = new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name) .WithoutILInstruction().WithRR(rr); } else { expr = new IndexerExpression(target.Expression, arguments.Select(a => a.Expression)) .WithoutILInstruction().WithRR(rr); } var op = AssignmentOperatorType.Assign; var parentEvent = method.AccessorOwner as IEvent; if (parentEvent != null) { if (method.Equals(parentEvent.AddAccessor)) { op = AssignmentOperatorType.Add; } if (method.Equals(parentEvent.RemoveAccessor)) { op = AssignmentOperatorType.Subtract; } } return(new AssignmentExpression(expr, op, value.Expression).WithRR(new TypeResolveResult(method.AccessorOwner.ReturnType))); } else { if (arguments.Count == 0) { return(new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name).WithRR(rr)); } else { return(new IndexerExpression(target.Expression, arguments.Select(a => a.Expression)).WithRR(rr)); } } }
string GetCountProperty(ITypeDefinition currentTypeDefinition, ResolveResult targetResolveResult) { var memberLookup = new MemberLookup(currentTypeDefinition, ctx.Compilation.MainAssembly); string countProperty = TryProperty(memberLookup, targetResolveResult, "Count"); if (countProperty != null) { return(countProperty); } return(TryProperty(memberLookup, targetResolveResult, "Length")); }
bool CanIndex(ITypeDefinition currentTypeDefinition, ResolveResult targetResolveResult) { if (targetResolveResult.Type is ArrayType) { return(true); } var memberLookup = new MemberLookup(currentTypeDefinition, ctx.Compilation.MainAssembly); var indexers = memberLookup.LookupIndexers(targetResolveResult).ToList(); return(indexers.SelectMany(methodList => methodList).Any( member => ((IProperty)member).CanGet && ((IProperty)member).Getter.Parameters.Count == 1)); }
/// <summary> /// Resolves an object creation. /// </summary> /// <param name="type">Type of the object to create.</param> /// <param name="arguments"> /// Arguments passed to the constructor. /// The resolver may mutate this array to wrap elements in <see cref="CastExpression"/>s! /// </param> /// <param name="argumentNames"> /// The argument names. Pass the null string for positional arguments. /// </param> /// <param name="allowProtectedAccess"> /// Whether to allow calling protected constructors. /// This should be false except when resolving constructor initializers. /// </param> /// <param name="initializerStatements"> /// Statements for Objects/Collections initializer. /// <see cref="InvocationExpression.InitializerStatements"/> /// </param> /// <returns>InvocationResolveResult or ErrorResolveResult</returns> public static Expression ResolveObjectCreation(ResolveContext rc, Location l, IType type, Expression[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false, IList <Expression> initializerStatements = null) { if (type.Kind == TypeKind.Delegate) { if (arguments == null || arguments.Length != 1) { rc.Report.Error(0, l, "Method name expected"); return(null); } Expression input = arguments[0]; IMethod invoke = input.Type.GetDelegateInvokeMethod(); if (invoke != null) { input = new MethodGroupExpression( input, invoke.Name, methods: new[] { new MethodListWithDeclaringType(input.Type) { invoke } }, typeArguments: EmptyList <IType> .Instance ); } return(rc.Convert(input, type)); } OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames); MemberLookup lookup = rc.CreateMemberLookup(); List <IMethod> allApplicable = null; foreach (IMethod ctor in type.GetConstructors()) { if (lookup.IsAccessible(ctor, allowProtectedAccess)) { or.AddCandidate(ctor); } else { or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible); } } if (or.BestCandidate != null) { return(or.CreateInvocation(null, initializerStatements)); } else { rc.Report.Error(0, l, "The type `{0}' does not contain a constructor that takes `{1}' arguments", type.ToString(), arguments != null ? arguments.Length.ToString() : "0"); return(ErrorResult); } }
public void AddNamespace(MemberLookup lookup, INamespace ns) { if (usedNamespaces.Contains(ns.Name)) { return; } if (!IsAccessible(lookup, ns)) { usedNamespaces.Add(ns.Name); return; } usedNamespaces.Add(ns.Name); result.Add(Factory.CreateNamespaceCompletionData(ns)); }
bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method) { if (target == null) { var result = resolver.ResolveSimpleName(method.AccessorOwner.Name, EmptyList <IType> .Instance, isInvocationTarget: false) as MemberResolveResult; return(!(result == null || result.IsError || !IsAppropriateCallTarget(expectedTargetDetails, method.AccessorOwner, result.Member))); } else { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var result = lookup.Lookup(target, method.AccessorOwner.Name, EmptyList <IType> .Instance, isInvocation: false) as MemberResolveResult; return(!(result == null || result.IsError || !IsAppropriateCallTarget(expectedTargetDetails, method.AccessorOwner, result.Member))); } }
bool IsAccessible(MemberLookup lookup, INamespace ns) { if (ns.Types.Any(t => lookup.IsAccessible(t, false))) { return(true); } foreach (var child in ns.ChildNamespaces) { if (IsAccessible(lookup, child)) { return(true); } } return(false); }
Expression LookInCurrentType(ResolveContext rc, string identifier, IList <IType> typeArguments, NameLookupMode lookupMode, bool parameterizeResultType) { int k = typeArguments.Count; MemberLookup lookup = rc.CreateMemberLookup(lookupMode); // look in current type definitions for (ITypeDefinition t = rc.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { if (k == 0) { // Look for type parameter with that name var typeParameters = t.TypeParameters; // Look at all type parameters, including those copied from outer classes, // so that we can fetch the version with the correct owner. for (int i = 0; i < typeParameters.Count; i++) { if (typeParameters[i].Name == identifier) { return(new TypeExpression(typeParameters[i], Location)); } } } if (lookupMode == NameLookupMode.BaseTypeReference && t == rc.CurrentTypeDefinition) { // don't look in current type when resolving a base type reference continue; } Expression r; if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) { Expression targetResolveResult = (t == rc.CurrentTypeDefinition ? (Expression) new SelfReference(t, Location) : new TypeExpression(t, Location)); r = lookup.Lookup(targetResolveResult, identifier, typeArguments, lookupMode == NameLookupMode.InvocationTarget); } else { r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType); } if (!(r is UnknownMemberExpression)) // but do return AmbiguousMemberResolveResult { return(r); } } return(null); }
bool BaseTypeHasUsableParameterlessConstructor() { var memberLookup = new MemberLookup(currentType.GetDefinition(), ctx.Compilation.MainAssembly); OverloadResolution or = new OverloadResolution(ctx.Compilation, new ResolveResult[0]); foreach (var ctor in baseType.GetConstructors()) { if (memberLookup.IsAccessible(ctor, allowProtectedAccess: true)) { if (or.AddCandidate(ctor) == OverloadResolutionErrors.None) { return(true); } } } return(false); }
protected override void Run() { var doc = IdeApp.Workbench.ActiveDocument; if (doc == null || doc.FileName == FilePath.Null || doc.ParsedDocument == null) { return; } ITextEditorExtension ext = doc.EditorExtension; while (ext != null && !(ext is CompletionTextEditorExtension)) { ext = ext.Next; } if (ext == null) { return; } var dom = doc.Compilation; ImportSymbolCache cache = new ImportSymbolCache(); var lookup = new MemberLookup(null, doc.Compilation.MainAssembly); List <ImportSymbolCompletionData> typeList = new List <ImportSymbolCompletionData> (); foreach (var type in dom.GetAllTypeDefinitions()) { if (!lookup.IsAccessible(type, false)) { continue; } typeList.Add(new ImportSymbolCompletionData(doc, cache, type)); } typeList.Sort(delegate(ImportSymbolCompletionData left, ImportSymbolCompletionData right) { return(left.Type.Name.CompareTo(right.Type.Name)); }); CompletionDataList completionList = new CompletionDataList(); completionList.IsSorted = true; typeList.ForEach(cd => completionList.Add(cd)); ((CompletionTextEditorExtension)ext).ShowCompletion(completionList); }
string TryProperty(MemberLookup memberLookup, ResolveResult targetResolveResult, string name) { var countResolveResult = memberLookup.Lookup(targetResolveResult, name, EmptyList <IType> .Instance, false); var countPropertyResolveResult = countResolveResult as MemberResolveResult; if (countPropertyResolveResult == null) { return(null); } var property = countPropertyResolveResult.Member as IProperty; if (property == null || !property.CanGet) { return(null); } return(name); }
/// <summary> /// Resolves an indexer access. /// </summary> /// <param name="target">Target expression.</param> /// <param name="arguments"> /// Arguments passed to the indexer. /// The resolver may mutate this array to wrap elements in <see cref="CastExpression"/>s! /// </param> /// <param name="argumentNames"> /// The argument names. Pass the null string for positional arguments. /// </param> /// <returns>ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult</returns> public Expression ResolveIndexer(ResolveContext rc, Expression target, Expression[] arguments, string[] argumentNames = null) { switch (target.Type.Kind) { case TypeKind.Array: // �6.6.1 Array access if (argumentNames != null && argumentNames.Length > 0) { rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument"); } return(new ArrayAccessExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments)); case TypeKind.Pointer: // �.5.3 Pointer element access if (argumentNames != null && argumentNames.Length > 0) { rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument"); } return(new PointerArithmeticExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments)); } // �6.6.2 Indexer access MemberLookup lookup = rc.CreateMemberLookup(); var indexers = lookup.LookupIndexers(target); OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames); or.AddMethodLists(indexers); if (or.BestCandidate != null) { return(or.CreateInvocation(target)); } else { rc.Report.Error(0, loc, "Cannot apply indexing with [] to an expression of type `{0}'", target.Type.ToString()); return(null); } }
IEnumerable <CodeAction> GetActionsForType(RefactoringContext context, AstNode node) { var rr = context.Resolve(node) as UnknownIdentifierResolveResult; if (rr == null) { return(EmptyList <CodeAction> .Instance); } string identifier = rr.Identifier; int tc = rr.TypeArgumentCount; string attributeIdentifier = null; if (node.Parent is Attribute) { attributeIdentifier = identifier + "Attribute"; } var lookup = new MemberLookup(null, context.Compilation.MainAssembly); List <CodeAction> actions = new List <CodeAction>(); foreach (var typeDefinition in context.Compilation.GetAllTypeDefinitions()) { if ((typeDefinition.Name == identifier || typeDefinition.Name == attributeIdentifier) && typeDefinition.TypeParameterCount == tc && lookup.IsAccessible(typeDefinition, false)) { if (typeDefinition.DeclaringTypeDefinition == null) { actions.Add(NewUsingAction(context, node, typeDefinition.Namespace)); } actions.Add(ReplaceWithFullTypeNameAction(context, node, typeDefinition)); } } return(actions); }
bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method, out IMember foundMember) { foundMember = null; MemberResolveResult result; if (target == null) { result = resolver.ResolveSimpleName(method.AccessorOwner.Name, EmptyList <IType> .Instance, isInvocationTarget: false) as MemberResolveResult; } else { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); if (method.AccessorOwner.SymbolKind == SymbolKind.Indexer) { // TODO: use OR here, etc. result = null; foreach (var methodList in lookup.LookupIndexers(target)) { foreach (var indexer in methodList) { if (IsAppropriateCallTarget(expectedTargetDetails, method.AccessorOwner, indexer)) { foundMember = indexer; return(true); } } } } else { result = lookup.Lookup(target, method.AccessorOwner.Name, EmptyList <IType> .Instance, isInvocation: false) as MemberResolveResult; } } foundMember = result?.Member; return(!(result == null || result.IsError || !IsAppropriateCallTarget(expectedTargetDetails, method.AccessorOwner, result.Member))); }
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; } }
public Expression ResolveMemberAccess(ResolveContext rc, VSC.AST.Expression target, string identifier, IList <IType> typeArguments, NameLookupMode lookupMode = NameLookupMode.Expression) { // V# 4.0 spec: §7.6.4 bool parameterizeResultType = !(typeArguments.Count != 0 && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)); AliasNamespace nrr = target as AliasNamespace; if (nrr != null) { return(ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, parameterizeResultType)); } // TODO:Dynamic Resolution //if (target.Type.Kind == TypeKind.Dynamic) // return new DynamicMemberResolveResult(target, identifier); MemberLookup lookup = rc.CreateMemberLookup(lookupMode); Expression result; switch (lookupMode) { case NameLookupMode.Expression: result = lookup.Lookup(target, identifier, typeArguments, isInvocation: false); break; case NameLookupMode.InvocationTarget: result = lookup.Lookup(target, identifier, typeArguments, isInvocation: true); break; case NameLookupMode.Type: case NameLookupMode.TypeInUsingDeclaration: case NameLookupMode.BaseTypeReference: // Don't do the UnknownMemberResolveResult/MethodGroupResolveResult processing, // it's only relevant for expressions. return(lookup.LookupType(target.Type, identifier, typeArguments, parameterizeResultType)); default: throw new NotSupportedException("Invalid value for NameLookupMode"); } if (result is UnknownMemberExpression) { // We intentionally use all extension methods here, not just the eligible ones. // Proper eligibility checking is only possible for the full invocation // (after we know the remaining arguments). // The eligibility check in GetExtensionMethods is only intended for code completion. var extensionMethods = rc.GetExtensionMethods(identifier, typeArguments); if (extensionMethods.Count > 0) { return(new MethodGroupExpression(target, identifier, EmptyList <MethodListWithDeclaringType> .Instance, typeArguments) { extensionMethods = extensionMethods }); } } else { MethodGroupExpression mgrr = result as MethodGroupExpression; if (mgrr != null) { Debug.Assert(mgrr.extensionMethods == null); // set the values that are necessary to make MethodGroupResolveResult.GetExtensionMethods() work mgrr.resolver = rc; } } return(result); }
TranslatedExpression HandleDelegateConstruction(CallInstruction inst) { ILInstruction func = inst.Arguments[1]; IMethod method; switch (func.OpCode) { case OpCode.LdFtn: method = ((LdFtn)func).Method; break; case OpCode.LdVirtFtn: method = ((LdVirtFtn)func).Method; break; default: throw new ArgumentException($"Unknown instruction type: {func.OpCode}"); } var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod(); TranslatedExpression target; IType targetType; bool requireTarget; if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { targetType = method.Parameters[0].Type; target = expressionBuilder.Translate(inst.Arguments[0], targetType); target = ExpressionBuilder.UnwrapBoxingConversion(target); requireTarget = true; } else { targetType = method.DeclaringType; target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn); target = ExpressionBuilder.UnwrapBoxingConversion(target); requireTarget = expressionBuilder.HidesVariableWithName(method.Name) || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression)); } var expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = inst.OpCode }; bool needsCast = false; ResolveResult result = null; var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); if (!requireTarget) { result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false); if (result is MethodGroupResolveResult mgrr) { or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate)); } else { requireTarget = true; } } MemberLookup lookup = null; if (requireTarget) { lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); needsCast = true; result = rr; if (rr is MethodGroupResolveResult mgrr) { or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate)); } } if (needsCast) { Debug.Assert(requireTarget); target = target.ConvertTo(targetType, expressionBuilder); result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); } Expression targetExpression; if (requireTarget) { var mre = new MemberReferenceExpression(target, method.Name); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); mre.WithRR(result); targetExpression = mre; } else { var ide = new IdentifierExpression(method.Name) .WithRR(result); targetExpression = ide; } var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), targetExpression) .WithILInstruction(inst) .WithRR(new ConversionResolveResult( inst.Method.DeclaringType, new MemberResolveResult(target.ResolveResult, method), Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false))); return(oce); }
public IList <ICompletionItem> CreateElementList(XamlCompletionContext context, bool includeAbstract) { if (context.ParseInformation == null) { return(EmptyList <ICompletionItem> .Instance); } List <ICompletionItem> result = new List <ICompletionItem>(); AXmlElement last = context.ParentElement; ITextEditor editor = context.Editor; compilation = SD.ParserService.GetCompilationForFile(editor.FileName); IUnresolvedFile file = context.ParseInformation.UnresolvedFile; foreach (string item in XamlConst.GetAllowedItems(context)) { result.Add(new XamlCompletionItem(item)); } IType rt = null; if (last != null) { if (string.Equals(last.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase)) { if (string.Equals(last.LocalName, "Members", StringComparison.OrdinalIgnoreCase)) { return(result); } if (string.Equals(last.LocalName, "Code", StringComparison.OrdinalIgnoreCase)) { return(result); } } // If we have an element that is not a property or an incomplete // definition => interpret element as a type. XamlResolver resolver = new XamlResolver(compilation); int dotIndex = last.LocalName.IndexOf(".", StringComparison.Ordinal) + 1; if (dotIndex < 1 || dotIndex == last.LocalName.Length) { rt = resolver.ResolveType(last.Namespace, last.LocalName.Trim('.')); string contentPropertyName = GetContentPropertyName(rt.GetDefinition()); // If the type has a content property specified, use its type for completion. if (!string.IsNullOrEmpty(contentPropertyName)) { IProperty p = rt.GetProperties(m => m.Name == contentPropertyName).FirstOrDefault(); if (p != null) { rt = p.ReturnType; } } } else { string typeName = last.LocalName.Substring(0, dotIndex - 1); string memberName = last.LocalName.Substring(dotIndex); rt = resolver.ResolveType(last.Namespace, typeName); IMember member = rt.GetMembers(m => m.Name == memberName).FirstOrDefault(); if (member != null) { rt = member.ReturnType; } } } bool parentAdded = false; var utd = file.GetInnermostTypeDefinition(editor.Caret.Location); ITypeDefinition currentTypeDef = null; if (utd != null) { currentTypeDef = utd.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); } MemberLookup memberLookup = new MemberLookup(currentTypeDef, compilation.MainAssembly); IList <ITypeDefinition> possibleTypesInCollection = EmptyList <ITypeDefinition> .Instance; if (rt != null && Extensions.IsListType(rt)) { possibleTypesInCollection = rt.GetMethods(m => m.Parameters.Count == 1 && "Add".Equals(m.Name, StringComparison.Ordinal)) .Select(m => m.Parameters[0].Type.GetDefinition()) .Where(t => t != null) .ToList(); } var items = GetClassesFromContext(context); foreach (var ns in items) { foreach (ITypeDefinition td in ns.Value) { if (td.Kind != TypeKind.Class && (!includeAbstract || td.Kind != TypeKind.Interface)) { continue; } if (td.IsStatic || (!includeAbstract && td.IsAbstract) || td.IsDerivedFrom(KnownTypeCode.Attribute)) { continue; } if (td.Kind == TypeKind.Class && !td.GetConstructors().Any(m => memberLookup.IsAccessible(m, false))) { continue; } if (possibleTypesInCollection.Count > 0 && !possibleTypesInCollection.Any(td.IsDerivedFrom)) { continue; } string fullName = td.Name; if (!string.IsNullOrEmpty(ns.Key)) { fullName = ns.Key + ":" + fullName; } XamlCompletionItem item = new XamlCompletionItem(fullName, td); parentAdded = parentAdded || (last != null && item.Text == last.Name); result.Add(item); } } // TODO reimplement this if it is really necessary. // if (!parentAdded && last != null && !last.Name.Contains(".")) { // IClass itemClass = cu.CreateType(last.Namespace, last.LocalName.Trim('.')).GetUnderlyingClass(); // if (itemClass != null) // result.Add(new XamlCodeCompletionItem(itemClass, last.Prefix)); // } return(result); }
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))); } } }
TranslatedExpression HandleDelegateConstruction(CallInstruction inst) { ILInstruction func = inst.Arguments[1]; IMethod method; switch (func.OpCode) { case OpCode.LdFtn: method = ((LdFtn)func).Method; break; case OpCode.LdVirtFtn: method = ((LdVirtFtn)func).Method; break; default: throw new ArgumentException($"Unknown instruction type: {func.OpCode}"); } var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod(); TranslatedExpression target; IType targetType; if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { target = expressionBuilder.Translate(inst.Arguments[0]); targetType = method.Parameters[0].Type; } else { target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn); targetType = method.DeclaringType; } var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); bool needsCast = true; if (result is MethodGroupResolveResult mgrr) { or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); var expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = inst.OpCode }; needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate)); } if (needsCast) { target = target.ConvertTo(targetType, expressionBuilder); result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); } var mre = new MemberReferenceExpression(target, method.Name); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); mre.WithRR(result); var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre) .WithILInstruction(inst) .WithRR(new ConversionResolveResult( inst.Method.DeclaringType, new MemberResolveResult(target.ResolveResult, method), Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false))); return(oce); }