Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoCommon: check visibility of one method (or type or field) from another. #226

Open
tbroyer opened this issue Apr 12, 2015 · 2 comments · May be fixed by #227
Open

AutoCommon: check visibility of one method (or type or field) from another. #226

tbroyer opened this issue Apr 12, 2015 · 2 comments · May be fixed by #227

Comments

@tbroyer
Copy link
Contributor

tbroyer commented Apr 12, 2015

A useful addition to MoreElements or Visibility could be a way to check whether a given Element can see another one; the expected most-common use-case being to check whether some method can be called from another class (particularly when enumerating methods of a class including inherited methods from class hierarchy). The method would return false if the target element is private, true if it's public (and all enclosing elements are also visible to the source element; i.e. if the effective visibility of the element is public), and would check whether the source and target elements are in the same package otherwise.

For example, in Bullet•, the generated class will call methods from the processed Dagger‡ component. Components can be abstract classes and therefore inherit methods from a base class. The Bullet• processor thus needs to check which methods the generated class will be able to call without causing a compilation error, and similarly for types for member injections (either to avoid generating such code, or to possibly generate helper code in the appropriate package, to get access to the type or method).

The API could look like:

static boolean isVisibleFrom(Element target, Element from);

or

static boolean isAccessibleFrom(Element target, Element from);

In the case of Bullet•, the from will likely be the package (as a PackageElement) where the class is being generated.

When generating a subclass, one could want to know which methods from the parent class are callable from the subclass, so there could be an option to get a true when the target field or method (or nested type) is protected, even if not in the same package. Not sure what the API would look like though.

FWIW, GWT's JClassType has getInheritableMethods for methods a subclass could call, and getOverridableMethods for those you can override in a subclass (that would be the subset of inheritable methods that's not final). And there actually is a TODO in the code to add an isCallable: https://github.com/gwtproject/gwt/blob/a6da588fadc17f9ae5b77204d25bad70f3846e4f/user/src/com/google/gwt/place/rebind/PlaceHistoryGeneratorContext.java#L288-L290 But while GWT limits it to methods, this is applicable to fields, nested types, and types in general (e.g. when looking at return types or parameter types of methods, or types of fields: not only the method or field needs to be accessible, but also the referenced type(s)).

@gk5885
Copy link
Contributor

gk5885 commented Apr 12, 2015

Absolutely. The only problem is that that is a large and somewhat complicated part of the JLS to implement. :\ It's certainly on the TODO list, but like GWT, we've just been limping along until a sufficiently tricky issue forces us into solving this problem.

@tbroyer
Copy link
Contributor Author

tbroyer commented Apr 12, 2015

Actually, I believe use-cases in auto-common would always have a source of type PackageElement, which makes things much easier: https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.1
Something like:

  public static boolean isVisibleFrom(Element target, PackageElement from) {
    switch (Visibility.effectiveVisibilityOfElement(target)) {
      case PUBLIC:
        return true;
      case PROTECTED:
      case DEFAULT:
        return MoreElements.getPackage(target).equals(from);
      case PRIVATE:
        return false;
      default:
        throw new AssertionError();
    }
  }

  public static boolean isVisibleFromSubclass(Element target, PackageElement from) {
    switch (Visibility.effectiveVisibilityOfElement(target)) {
      case PUBLIC:
      case PROTECTED:
        return true;
      case DEFAULT:
        return MoreElements.getPackage(target).equals(from);
      case PRIVATE:
        return false;
      default:
        throw new AssertionError();
    }
  }

Then the special cases for protected qualified access would be left to the caller of these APIs (to choose the appropriate one): https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2

@raghsriniv raghsriniv added the P3 label Jun 24, 2019
@kluever kluever added type=addition A new feature type=enhancement Make an existing feature better and removed type=enhancement Make an existing feature better labels Aug 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants