private bool IsMethodVisible(RubyMemberInfo/*!*/ method, RubyModule/*!*/ owner, VisibilityContext visibility, bool foundCallerSelf) { // Visibility not constrained by a class: // - call with implicit self => all methods are visible. // - interop call => only public methods are visible. if (visibility.Class == null) { return visibility.IsVisible(method.Visibility); } if (method.Visibility == RubyMethodVisibility.Protected) { // A protected method is visible if the caller's self immediate class is a descendant of the method owner. if (foundCallerSelf) { return true; } // walk ancestors from caller's self class (visibilityContext) // until the method owner is found or this module is found (this module is a descendant of the owner): return visibility.Class.ForEachAncestor((module) => module == owner || module == this); } return method.Visibility == RubyMethodVisibility.Public; }
public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, VisibilityContext visibility, MethodLookup options) { Context.RequiresClassHierarchyLock(); Assert.NotNull(name); InitializeMethodsNoLock(); RubyMemberInfo info = null; RubyModule owner = null; bool skipHidden = false; bool foundCallerSelf = false; MethodResolutionResult result; if (ForEachAncestor((module) => { owner = module; foundCallerSelf |= module == visibility.Class; return module.TryGetMethod(name, ref skipHidden, (options & MethodLookup.Virtual) != 0, out info); })) { if (info == null || info.IsUndefined) { result = MethodResolutionResult.NotFound; } else if (!IsMethodVisible(info, owner, visibility, foundCallerSelf)) { result = new MethodResolutionResult(info, owner, false); } else if (info.IsSuperForwarder) { if ((options & MethodLookup.ReturnForwarder) != 0) { result = new MethodResolutionResult(info, owner, true); } else { // start again with owner's super ancestor and ignore visibility: result = owner.ResolveSuperMethodNoLock(((SuperForwarderInfo)info).SuperName, owner); } } else { result = new MethodResolutionResult(info, owner, true); } } else { result = MethodResolutionResult.NotFound; } // Note: all classes include Object in ancestors, so we don't need to search it again: if (!result.Found && (options & MethodLookup.FallbackToObject) != 0 && !IsClass) { return _context.ObjectClass.ResolveMethodNoLock(name, visibility, options & ~MethodLookup.FallbackToObject); } return result; }
internal MethodResolutionResult ResolveMethodForSiteNoLock(string/*!*/ name, VisibilityContext visibility, MethodLookup options) { return ResolveMethodNoLock(name, visibility, options).InvalidateSitesOnOverride(); }
public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, VisibilityContext visibility) { return ResolveMethodNoLock(name, visibility, MethodLookup.Default); }
// thread-safe: public MethodResolutionResult ResolveMethod(string/*!*/ name, VisibilityContext visibility) { using (Context.ClassHierarchyLocker()) { return ResolveMethodNoLock(name, visibility); } }