Commits

Artem Melentyev committed c78ecee

Extension Methods for Java! fast and dirty way for now. wip

  • Participants
  • Parent commits ee56b92
  • Branches extMeth

Comments (0)

Files changed (6)

sample/Extension.java

+import java.util.Iterator;
+
+public class Extension {
+	//@Extension
+	public static boolean extension(String s) {
+		return true;
+	}
+	public static boolean test() {
+		String s = "qwe";
+		return extension(s) && s.extension();
+	}
+	public static void main(String[] args) {
+		System.out.println(Extension.test());
+	}
+}

src/share/classes/com/sun/tools/javac/comp/Attr.java

 package com.sun.tools.javac.comp;
 
 import java.util.*;
-import java.util.Set;
 import javax.lang.model.element.ElementKind;
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 
 import com.sun.source.tree.IdentifierTree;
 import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
 import com.sun.source.tree.TreeVisitor;
 import com.sun.source.util.SimpleTreeVisitor;
 
     public Type checkMethod(Type site,
                             Symbol sym,
                             Env<AttrContext> env,
-                            final List<JCExpression> argtrees,
+                            List<JCExpression> argtrees,
                             List<Type> argtypes,
                             List<Type> typeargtypes,
                             boolean useVarargs) {
                                       true,
                                       useVarargs,
                                       noteWarner);
+        if (owntype == null) { // extension method?
+        	owntype = sym.type;
+        	MethodInvocationTree mit = (MethodInvocationTree) env.tree;
+        	JCFieldAccess fa = (JCFieldAccess) mit.getMethodSelect();
+        	argtrees = argtrees.prepend(fa.getExpression());
+        }
         boolean warned = noteWarner.hasNonSilentLint(LintCategory.UNCHECKED);
 
         // If this fails, something went wrong; we should not have

src/share/classes/com/sun/tools/javac/comp/Resolve.java

                         site, name, null, argtypes);
             }
             else {
+            	// TODO: extension methods
+            	sym = this.resolveMethod(pos, env, name, argtypes.prepend(site), typeargtypes);
+            	if (sym.kind == MTH)
+            		; // todo: extension method mark
                 //if nothing is found return the 'first' error
-                MethodResolutionPhase errPhase =
-                        firstErroneousResolutionPhase();
-                sym = access(methodResolutionCache.get(errPhase),
-                        pos, location, site, name, true, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired;
+            	if (sym.kind >= AMBIGUOUS) {
+	                MethodResolutionPhase errPhase =
+	                        firstErroneousResolutionPhase();
+	                sym = access(methodResolutionCache.get(errPhase),
+	                        pos, location, site, name, true, argtypes, typeargtypes);
+	                env.info.varArgs = errPhase.isVarargsRequired;
+            	}
             }
         } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
             //non-instantiated polymorphic signature - synthesize new method symbol

src/share/classes/com/sun/tools/javac/comp/TransTypes.java

     public void visitApply(JCMethodInvocation tree) {
         tree.meth = translate(tree.meth, null);
         Symbol meth = TreeInfo.symbol(tree.meth);
+        if (tree.args.length() + 1 == meth.type.getParameterTypes().length()) { // extension method?
+        	JCIdent emeth = make.Ident(((JCFieldAccess) tree.meth).name);
+    		emeth.pos = tree.meth.pos;
+    		emeth.sym = meth;
+    		emeth.type = tree.meth.type;
+    		tree.args = tree.args.prepend(((JCFieldAccess) tree.meth).selected);
+    		tree.meth = emeth;
+        }
         Type mt = meth.erasure(types);
         List<Type> argtypes = mt.getParameterTypes();
         if (allowEnums &&
         if (tree.varargsElement != null)
             tree.varargsElement = types.erasure(tree.varargsElement);
         else
-            Assert.check(tree.args.length() == argtypes.length());
+    		Assert.check(tree.args.length() == argtypes.length());
         tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
 
         // Insert casts of method invocation results as needed.

src/test/ExtensionTest.java

+import com.sun.tools.javac.Main;
+
+public class ExtensionTest {
+    public static void main(String[] args) throws Exception {
+    	String clas = "Extension";
+    	String file = "sample/"+clas+".java";
+		System.out.print("Compiling " + file + ": ");
+		boolean res = Main.compile(new String[]{file, "-d", "build/classes"})==0;
+		res &= (Boolean)Class.forName(clas).getDeclaredMethod("test").invoke(null);
+		System.out.println(res ? "ok" : "fail");
+    }
+}

src/test/JCOOTest.java

 
 public class JCOOTest {
     public static void main(String[] args) throws Exception {
-        compile("Math");
+    	compile("Math");
         compile("Cmp");
         compile("ListIndexGet");
         compile("ListIndexSet");
     	String file = "../examples/"+clas+".java";
 		System.out.print("Compiling " + file + ": ");
 		boolean res = Main.compile(new String[]{file, "-d", "build/classes"})==0;
-		res &= (boolean)Class.forName(clas).getDeclaredMethod("test").invoke(null);
+		res &= (Boolean)Class.forName(clas).getDeclaredMethod("test").invoke(null);
 		System.out.println(res ? "ok" : "fail");
 	}
 }