maenu / method-nullability-plugin

0 stars 0 forks source link

Warnings: Precision #8

Open maenu opened 7 years ago

maenu commented 7 years ago

Show warning only if:

maenu commented 7 years ago

Try to use JDT null analysis, plug in annotation in AST.

lukaszbinden commented 7 years ago

first attempt of AST rewriting:

package test1; public class X { public void foo() { String s = "sdf"; IntStream @Nullable, chars = s.chars(); } }

lukaszbinden commented 7 years ago

AST rewrite works. But document remains unsaved. Need to figure out a way to do the rewrite before the save operation.

possible solution: A save action is a special clean up that perform the requested modifications on save automatically. http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Fguide%2Fjdt_api_contributing_a_cleanup.htm

lukaszbinden commented 7 years ago

changes in commit:

lukaszbinden commented 7 years ago

https://www.eclipse.org/forums/index.php/t/202641/

org.eclipse.jdt.internal.compiler.classfmt.MethodInfoWithTypeAnnotations

lukaszbinden commented 7 years ago

evtl. OSGI Hook Configurator to hook into the class loading process and then supplement API classes with Nullable information: osgi.hook.configurators.include

https://wiki.eclipse.org/Adaptor_Hooks

lukaszbinden commented 7 years ago

ok does not seem to work easily, especially with a plugin based attempt:

java.lang.ClassNotFoundException: ch.unibe.scg.methodnullabilityplugin.MyClassLoaderHookConfigurator at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at org.eclipse.osgi.internal.hookregistry.HookRegistry.loadConfigurators(HookRegistry.java:185) at org.eclipse.osgi.internal.hookregistry.HookRegistry.initialize(HookRegistry.java:106) at org.eclipse.osgi.internal.framework.EquinoxContainer.(EquinoxContainer.java:64) at org.eclipse.osgi.launch.Equinox.(Equinox.java:31) at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:303) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:239) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:673) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:610) at org.eclipse.equinox.launcher.Main.run(Main.java:1519) at org.eclipse.equinox.launcher.Main.main(Main.java:1492)

lukaszbinden commented 7 years ago

it seems that OSGi HookRegistry is too global to serve for our plugin

lukaszbinden commented 7 years ago

cannot find hook/listener in org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment

extension point: CompilationParticipant. reconcile hook delivers a jdt.core.ICompilationUnit.

Potential approach: AnnotationUtils of org.eclipse.jst.ws.annotations.core.utils (only provisional API)

lukaszbinden commented 7 years ago

manually inserting an annotation into IMethod/BinaryMethod/ResolvedBinaryMethod or MethodBinding. Could potentially work but have not found a way to hook into creation of those objects.

lukaszbinden commented 7 years ago

NB: Bean Validation API (e.g. @Null) is part of Java EE (since v6) and not SE

lukaszbinden commented 7 years ago

another approach: use javassist to dynamically add Nullable annotation to e.g. IMethod instances

http://stackoverflow.com/questions/2944896/dynamically-add-annotation-to-an-existing-class

lukaszbinden commented 7 years ago

Managed to "inject" a Nullable annotation in the form of AnnotationBinding into a BinaryTypeBinding (return type of respective nullable method), but it would not show the warning.

This stackoverflow post suggests that the idea is practically infeasible (no extension points or alike available for such a kind of thing):

http://stackoverflow.com/questions/14867657/custom-compile-time-class-loading-in-eclipse

lukaszbinden commented 7 years ago

Idea below of @Nullable injection via reflection does not work as the underlying models are different between methods that have this annotation in the class file (cf. MethodInfoWithTypeAnnotations) and methods that don't (cf. MethodInfo, and MethodInfo.createMethod)

`

                           IMethodBinding methodBinding = node.resolveMethodBinding();
            IJavaElement javaElement = methodBinding.getJavaElement();
            ITypeBinding tb = methodBinding.getReturnType();                             
                            Field binding = tb.getClass().getDeclaredField("binding");
            binding.setAccessible(true);
            BinaryTypeBinding compilerMethodBinding = (BinaryTypeBinding) binding.get(tb);
            AnnotationBinding[] typeAnnotations = compilerMethodBinding.getTypeAnnotations();
            if (methodBinding.getName().equals("yesIAmNullable")) {
                boolean containsIt = false;
                for (AnnotationBinding ab : typeAnnotations) {
                    nullableAnnotation = ab;
                }
                yesIAmNullable = methodBinding;

            } else if (methodBinding.getName().equals("noIAmNotNullable")) {
                if (nullableAnnotation != null) {
                    AnnotationBinding[] newAb = new AnnotationBinding[1];
                    newAb[0] = nullableAnnotation;
                    compilerMethodBinding.setTypeAnnotations(newAb, true);
                    noIAmNotNullable = methodBinding;

                }
            }`
lukaszbinden commented 7 years ago

Last attempt: byte code injection via AspectJ or Javassist

maenu commented 7 years ago

Insert nullable annotation into sources, IR does not work. Assignments missing.

maenu commented 7 years ago

Annotate types in declarations for local variables (prio 1), fields (prio 2), parameters (prio 2)