Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/PropertyTree.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/PropertyTree.java (revision 0)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/PropertyTree.java (revision 0)
@@ -0,0 +1,51 @@
+/*
+ * @(#)VariableTree.java 1.5 06/12/14
+ *
+ * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.source.tree;
+
+import javax.lang.model.element.Name;
+
+/**
+ * A tree node for a property declaration.
+ *
+ * For example:
+ *
+ * modifiers property type name initializer ;
+ *
+ *
+ * @see
+ *
+ * @author Peter von der Ahé
+ * @author Jonathan Gibbons
+ * @since 1.7
+ */
+public interface PropertyTree extends Tree {
+ ModifiersTree getModifiers();
+ Name getName();
+ Tree getType();
+ ExpressionTree getInitializer();
+}
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/Tree.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/Tree.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/Tree.java (working copy)
@@ -231,6 +231,11 @@
* Used for instances of {@link ParameterizedTypeTree}.
*/
PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
+
+ /**
+ * Used for instances of {@link PropertyTree}.
+ */
+ PROPERTY(PropertyTree.class),
/**
* Used for instances of {@link TypeCastTree}.
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/TreeVisitor.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/TreeVisitor.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/tree/TreeVisitor.java (working copy)
@@ -104,6 +104,12 @@
R visitInstanceOf(InstanceOfTree node, P p);
R visitUnary(UnaryTree node, P p);
R visitVariable(VariableTree node, P p);
+
+ /**
+ * @since 1.7
+ */
+ R visitProperty(PropertyTree node, P p);
+
R visitWhileLoop(WhileLoopTree node, P p);
R visitWildcard(WildcardTree node, P p);
R visitOther(Tree node, P p);
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java (working copy)
@@ -81,6 +81,10 @@
public R visitVariable(VariableTree node, P p) {
return defaultAction(node, p);
}
+
+ public R visitProperty(PropertyTree node, P p) {
+ return defaultAction(node, p);
+ }
public R visitEmptyStatement(EmptyStatementTree node, P p) {
return defaultAction(node, p);
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/TreeScanner.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/TreeScanner.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/source/util/TreeScanner.java (working copy)
@@ -151,6 +151,13 @@
r = scanAndReduce(node.getInitializer(), p, r);
return r;
}
+
+ public R visitProperty(PropertyTree node, P p) {
+ R r = scan(node.getModifiers(), p);
+ r = scanAndReduce(node.getType(), p, r);
+ r = scanAndReduce(node.getInitializer(), p, r);
+ return r;
+ }
public R visitEmptyStatement(EmptyStatementTree node, P p) {
return null;
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Flags.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Flags.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Flags.java (working copy)
@@ -220,6 +220,10 @@
* Flag that marks a Sun proprietary class.
*/
public static final long PROPRIETARY = 1L<<38;
+
+ /** Flag that maks a property field or a property method (getter/setter)
+ */
+ public static final long PROPERTY = 1L<<39;
/** Modifier masks.
*/
@@ -231,6 +235,9 @@
InterfaceVarFlags = FINAL | STATIC | PUBLIC,
VarFlags = AccessFlags | FINAL | STATIC |
VOLATILE | TRANSIENT | ENUM,
+ InterfacePropertyFlags= ABSTRACT | FINAL | PUBLIC,
+ PropertyFlags = AccessFlags | ABSTRACT | FINAL | STATIC |
+ VOLATILE | SYNCHRONIZED | TRANSIENT,
ConstructorFlags = AccessFlags,
InterfaceMethodFlags = ABSTRACT | PUBLIC,
MethodFlags = AccessFlags | ABSTRACT | STATIC | NATIVE |
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Symbol.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Symbol.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/code/Symbol.java (working copy)
@@ -978,6 +978,37 @@
}
}
+ /** A class for property symbols.
+ */
+ public static class PropertySymbol extends VarSymbol {
+ /** getter, non null.
+ */
+ public MethodSymbol getter;
+
+ /** setter, null if the property is final.
+ */
+ public MethodSymbol setter;
+
+ public PropertySymbol(long flags,Name name,Type type,Symbol owner) {
+ super(flags,name,type,owner);
+ }
+
+ @Override
+ public VarSymbol clone(Symbol newOwner) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Symbol asMemberOf(Type site,Types types) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public ElementKind getKind() {
+ return ElementKind.PROPERTY;
+ }
+ }
+
/** A class for method symbols.
*/
public static class MethodSymbol extends Symbol implements ExecutableElement {
@@ -996,6 +1027,10 @@
* declaration.
*/
public Attribute defaultValue = null;
+
+ /** Property name in case of setter or getter of a property or null.
+ */
+ public Name propertyName = null;
/** Construct a method symbol, given its flags, name, type and owner.
*/
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Attr.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Attr.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Attr.java (working copy)
@@ -28,7 +28,6 @@
package com.sun.tools.javac.comp;
import java.util.*;
-import java.util.Set;
import javax.lang.model.element.ElementKind;
import javax.tools.JavaFileObject;
@@ -740,6 +739,11 @@
chk.setLint(prevLint);
}
}
+
+ public void visitPropertyDef(JCPropertyDecl tree) {
+
+ result = tree.sym.type;
+ }
public void visitSkip(JCSkip tree) {
result = null;
@@ -794,7 +798,6 @@
public void visitForeachLoop(JCEnhancedForLoop tree) {
Env loopEnv =
env.dup(env.tree, env.info.dup(env.info.scope.dup()));
- attribStat(tree.var, loopEnv);
Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));
chk.checkNonVoid(tree.pos(), exprType);
Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
@@ -811,6 +814,10 @@
: types.upperBound(iterableParams.head);
}
}
+ if (tree.var.vartype==null) { // infer the type of the variable if needed
+ tree.var.type=elemtype;
+ }
+ attribStat(tree.var, loopEnv);
chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
loopEnv.tree = tree; // before, we were not in loop!
attribStat(tree.body, loopEnv);
@@ -1756,6 +1763,7 @@
env.info.varArgs = false;
sym = rs.resolveMethod(tree.pos(), env, tree.name, pt.getParameterTypes(), pt.getTypeArguments());
varArgs = env.info.varArgs;
+ //FIXME Remi, why tree.sym.kind != VAR ???
} else if (tree.sym != null && tree.sym.kind != VAR) {
sym = tree.sym;
} else {
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Check.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Check.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Check.java (working copy)
@@ -580,9 +580,16 @@
case VAR:
if (sym.owner.kind != TYP)
mask = LocalVarFlags;
- else if ((sym.owner.flags_field & INTERFACE) != 0)
+ else if ((sym.owner.flags_field & INTERFACE) != 0) {
+ if ((flags & PROPERTY) != 0) {
+ implicit = InterfaceMethodFlags;
+ mask = InterfacePropertyFlags;
+ }
+ else
mask = implicit = InterfaceVarFlags;
- else
+ } else if ((flags & PROPERTY) != 0)
+ mask = PropertyFlags;
+ else
mask = VarFlags;
break;
case MTH:
@@ -2025,6 +2032,25 @@
}
return true;
}
+
+ /** Find an equivalent symbol in given scope.
+ * @param sym The symbol.
+ * @param s The scope.
+ */
+ MethodSymbol findOverrideEquivalent(MethodSymbol sym, Scope s) {
+ if (sym.type.isErroneous())
+ return null;
+ if (sym.owner.name == names.any) return null;
+ for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
+ if (sym != e.sym &&
+ sym.kind == e.sym.kind &&
+ sym.name != names.error &&
+ (types.overrideEquivalent(sym.type, e.sym.type))) {
+ return (MethodSymbol)e.sym;
+ }
+ }
+ return null;
+ }
/** Check that single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Lower.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Lower.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/Lower.java (working copy)
@@ -2968,6 +2968,26 @@
result = tree;
currentMethodSym = oldMethodSym;
}
+
+ public void visitPropertyDef(JCPropertyDecl tree) {
+ PropertySymbol sym = tree.sym;
+ if ((sym.flags_field & ABSTRACT) != 0) {
+ // remove the symbol from the class scope
+ currentClass.members().remove(sym);
+ } else {
+ sym.flags_field = sym.flags_field
+ & ~AccessFlags & ~ABSTRACT
+ | PRIVATE;
+ }
+ //System.out.println("scope "+currentClass.members());
+
+ //result = tree;
+ super.visitPropertyDef(tree);
+ }
+
+ private Name toBeanName(String name) {
+ return Name.fromString(names,Character.toUpperCase(name.charAt(0))+name.substring(1));
+ }
public void visitBlock(JCBlock tree) {
MethodSymbol oldMethodSym = currentMethodSym;
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java (working copy)
@@ -28,7 +28,6 @@
package com.sun.tools.javac.comp;
import java.util.*;
-import java.util.Set;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
@@ -44,6 +43,7 @@
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.TypeTags.*;
+
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/** This is the second phase of Enter, in which classes are completed
@@ -423,6 +423,7 @@
addEnumMembers(tree, env);
}
memberEnter(tree.defs, env);
+ addPropertiesMembers(tree, env);
}
/** Add the implicit members for an enum type
@@ -495,6 +496,123 @@
tree.sym);
memberEnter(make.MethodDef(compareTo, null), env);
}
+
+ /** Add the implicit members for properties
+ * to the symbol table.
+ */
+ private void addPropertiesMembers(JCClassDecl classDef, Env env) {
+ for(JCTree tree: classDef.defs) {
+ //FIXME Remi use a visitor instead ??
+ if (tree instanceof JCPropertyDecl) {
+ addPropertyMembers(classDef, (JCPropertyDecl)tree, env);
+ }
+ }
+ }
+
+ private void addPropertyMembers(JCClassDecl encClass, JCPropertyDecl tree, Env env) {
+ List defs=encClass.defs;
+ boolean isClassAbstract = (encClass.mods.flags & (Flags.ABSTRACT | Flags.INTERFACE)) !=0;
+
+ boolean isAbstract = (tree.mods.flags & Flags.ABSTRACT) != 0;
+ boolean isFinal = (tree.mods.flags & Flags.FINAL) != 0;
+
+ Name name=tree.name;
+
+ // filter out volatile and transient and mark as property
+ long methodMods = (tree.mods.flags & ~(Flags.VOLATILE | Flags.TRANSIENT))
+ | Flags.PROPERTY | Flags.SYNTHETIC;
+
+ Name beanName = toBeanName(name.toString());
+
+ // public final type getXxx/isXXX() { return xxx; }
+ Name getterPrefix;
+ if (tree.proptype.tag == JCTree.TYPEIDENT &&
+ ((JCPrimitiveTypeTree)tree.proptype).typetag == TypeTags.BOOLEAN) {
+ getterPrefix = names.is;
+ } else {
+ getterPrefix = names.get;
+ }
+
+ Scope scope = enter.enterScope(env);
+
+ MethodSymbol getsym;
+ Name getterName = getterPrefix.append(beanName);
+ if (isAbstract && !isClassAbstract) {
+ MethodType mtype = new MethodType(
+ List.nil(),tree.proptype.type,List.nil(),syms.methodClass);
+ /*Type mtype=memberEnter.signature(getter.typarams, getter.params,
+ getter.restype, getter.thrown,
+ memberEnter.methodEnv(getter, env));*/
+ MethodSymbol sym = new MethodSymbol(methodMods, getterName, mtype, scope.owner);
+
+ getsym = chk.findOverrideEquivalent(sym, scope);
+ if (getsym == null) {
+ log.error(tree.pos, "property.getter.not.defined", tree.sym, sym, sym.location());
+ }
+ } else {
+ // getXxx/isXxx()
+ JCBlock body = (isClassAbstract)? null:
+ make.Block(0, List.of(make.Return(make.Ident(tree.sym))));
+ JCMethodDecl getter = make.at(tree.pos).
+ MethodDef(make.Modifiers(methodMods),
+ getterName,
+ tree.proptype,
+ List.nil(),
+ List.nil(),
+ List.nil(),
+ body,
+ null);
+
+ memberEnter(getter, env);
+ defs = defs.append(getter);
+ getsym = getter.sym;
+ }
+ tree.sym.getter = getsym;
+ if (getsym != null)
+ getsym.propertyName = name;
+
+ if (!isFinal) {
+ MethodSymbol setsym;
+ Name setterName = names.set.append(beanName);
+ if (isAbstract && !isClassAbstract) {
+ MethodType mtype = new MethodType(
+ List.of(tree.proptype.type),Symtab.voidType,List.nil(),syms.methodClass);
+ MethodSymbol sym = new MethodSymbol(methodMods, setterName, mtype, scope.owner);
+
+ setsym = chk.findOverrideEquivalent(sym, scope);
+ if (setsym == null) {
+ log.error(tree.pos, "property.setter.not.defined", tree.sym, sym, sym.location());
+ }
+ } else {
+ // void setXxx( xxx) { this.xxx=xxx; }
+ JCBlock body=(isClassAbstract)? null:
+ make.Block(0, List.of(make.Exec(make.Assign(
+ make.Select(make.Ident(names._this),tree.sym),make.Ident(name)))));
+ JCMethodDecl setter = make.at(tree.pos).
+ MethodDef(make.Modifiers(methodMods),
+ setterName,
+ make.TypeIdent(TypeTags.VOID),
+ List.nil(),
+ List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
+ name, tree.proptype, null)),
+ List.nil(),
+ body,
+ null);
+
+ memberEnter(setter, env);
+ defs = defs.append(setter);
+ setsym = setter.sym;
+ }
+ tree.sym.setter = setsym;
+ if (setsym != null)
+ setsym.propertyName = name;
+ }
+ encClass.defs=defs;
+ }
+
+ private Name toBeanName(String name) {
+ return Name.fromString(names,Character.toUpperCase(name.charAt(0))+name.substring(1));
+ }
public void visitTopLevel(JCCompilationUnit tree) {
if (tree.starImportScope.elems != null) {
@@ -611,7 +729,7 @@
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
return localEnv;
}
-
+
public void visitVarDef(JCVariableDecl tree) {
Env localEnv = env;
if ((tree.mods.flags & STATIC) != 0 ||
@@ -619,10 +737,32 @@
localEnv = env.dup(tree, env.info.dup());
localEnv.info.staticLevel++;
}
- attr.attribType(tree.vartype, localEnv);
+
+ // the type is not already known (not infered by foreach) but is declared
+ if (tree.type==null && tree.vartype!=null) {
+ tree.type=attr.attribType(tree.vartype, localEnv);
+ }
+
Scope enclScope = enter.enterScope(env);
- VarSymbol v =
- new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner);
+
+ VarSymbol v;
+ if (tree.type!=null) {
+ v = new VarSymbol(0, tree.name, tree.type, enclScope.owner);
+ }
+ else {
+ // create a variable without its type and infer it
+ v = new VarSymbol(0, tree.name, null, enclScope.owner);
+ // In order to catch self-references, we set
+ // the variable's declaration position to
+ // maximal possible value, effectively marking
+ // the variable as undefined.
+ v.pos = Position.MAXPOS;
+ tree.sym = v;
+ v.type = attr.attribExpr(tree.init, initEnv(tree, env), Type.noType).baseType();
+ v.pos = Position.NOPOS;
+
+ }
+
v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree);
tree.sym = v;
if (tree.init != null) {
@@ -657,6 +797,66 @@
localEnv.info.staticLevel++;
return localEnv;
}
+
+ //FIXME Remi add lint
+ public void visitPropertyDef(JCPropertyDecl tree) {
+ Env localEnv = env;
+ if ((tree.mods.flags & STATIC) != 0 ||
+ //FIXME Remi the following line must be removed
+ (env.info.scope.owner.flags() & INTERFACE) != 0) {
+ localEnv = env.dup(tree, env.info.dup());
+ localEnv.info.staticLevel++;
+ }
+
+ tree.type=attr.attribType(tree.proptype, localEnv);
+
+ Scope enclScope = enter.enterScope(env);
+
+ // mark as property
+ long flags = tree.mods.flags | Flags.PROPERTY;
+ /*
+ if ((env.info.scope.owner.flags() & INTERFACE) != 0) {
+ flags |= ABSTRACT;
+ }*/
+
+ // create a property symbol
+ PropertySymbol sym = new PropertySymbol(flags, tree.name, tree.type, enclScope.owner);
+ tree.sym = sym;
+
+ if (tree.init != null) {
+ sym.flags_field |= HASINIT;
+ if ((sym.flags_field & FINAL) != 0 && tree.init.tag != JCTree.NEWCLASS)
+ sym.setLazyConstValue(initEnv(tree, env), log, attr, tree.init);
+ }
+
+ sym.flags_field = chk.checkFlags(tree.pos(), flags, sym, tree);
+
+ // add to scope
+ if (chk.checkUnique(tree.pos(), sym, enclScope)) {
+ enclScope.enter(sym);
+ }
+
+ annotateLater(tree.mods.annotations, localEnv, sym);
+ sym.pos = tree.pos;
+ }
+
+ /** Create a fresh environment for a property's initializer.
+ * The owner of the environment's scope is be the property itself.
+ *
+ * @param tree The property definition.
+ * @param env The environment current outside of the property definition.
+ */
+ //TODO Remi merge the code of the initEnv(JCVariableDecl) and initEnv(JCPropertyDecl)
+ Env initEnv(JCPropertyDecl tree, Env env) {
+ Env localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup()));
+ localEnv.info.scope = new Scope.DelegatedScope(env.info.scope);
+ localEnv.info.scope.owner = tree.sym;
+
+ if ((tree.mods.flags & STATIC) != 0 ||
+ (env.enclClass.sym.flags() & INTERFACE) != 0)
+ localEnv.info.staticLevel++;
+ return localEnv;
+ }
/** Default member enter visitor method: do nothing
*/
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java (working copy)
@@ -925,6 +925,8 @@
int newbp = bp + attrLen;
readEnclosingMethodAttr(sym);
bp = newbp;
+ } else if (attrName == names.Property) {
+ readPropertyName(sym);
} else {
unrecognized(attrName);
bp = bp + attrLen;
@@ -1033,6 +1035,14 @@
private static boolean isAsciiDigit(char c) {
return '0' <= c && c <= '9';
}
+
+ void readPropertyName(Symbol sym) {
+ if (sym.kind == MTH) {
+ Name name = readName(nextChar());
+ ((MethodSymbol)sym).propertyName = name;
+ }
+ sym.flags_field |= PROPERTY;
+ }
/** Read member attributes.
*/
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java (working copy)
@@ -29,8 +29,6 @@
import java.io.*;
import java.util.*;
-import java.util.Set;
-import java.util.HashSet;
import javax.tools.JavaFileManager;
import javax.tools.FileObject;
@@ -673,6 +671,15 @@
endAttr(alenIdx);
acount++;
}
+ if ((flags & PROPERTY) != 0) {
+ int alenIdx = writeAttr(names.Property);
+ if (sym.kind == MTH) {
+ Name propertyName = ((MethodSymbol)sym).propertyName;
+ databuf.appendChar(pool.put(propertyName));
+ }
+ endAttr(alenIdx);
+ acount++;
+ }
acount += writeJavaAnnotations(sym.getAnnotationMirrors());
return acount;
}
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Gen.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Gen.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Gen.java (working copy)
@@ -463,7 +463,8 @@
case JCTree.METHODDEF:
methodDefs.append(def);
break;
- case JCTree.VARDEF:
+
+ case JCTree.VARDEF: {
JCVariableDecl vdef = (JCVariableDecl) def;
VarSymbol sym = vdef.sym;
checkDimension(vdef.pos(), sym.type);
@@ -492,6 +493,38 @@
}
}
break;
+ }
+ case JCTree.PROPERTYDEF: {
+ //FIXME Remi
+ JCPropertyDecl prop = (JCPropertyDecl) def;
+ PropertySymbol sym = prop.sym;
+ checkDimension(prop.pos(), sym.type);
+ if (prop.init != null) {
+ if ((sym.flags() & STATIC) == 0) {
+ // Always initialize instance variables.
+ JCStatement init = make.at(prop.pos()).
+ Assignment(sym, prop.init);
+ initCode.append(init);
+ if (endPositions != null) {
+ Integer endPos = endPositions.remove(prop);
+ if (endPos != null) endPositions.put(init, endPos);
+ }
+ } else if (sym.getConstValue() == null) {
+ // Initialize class (static) variables only if
+ // they are not compile-time constants.
+ JCStatement init = make.at(prop.pos).
+ Assignment(sym, prop.init);
+ clinitCode.append(init);
+ if (endPositions != null) {
+ Integer endPos = endPositions.remove(prop);
+ if (endPos != null) endPositions.put(init, endPos);
+ }
+ } else {
+ checkStringConstant(prop.init.pos(), sym.getConstValue());
+ }
+ }
+ break;
+ }
default:
assert false;
}
@@ -882,7 +915,7 @@
*/
void genMethod(JCMethodDecl tree, Env env, boolean fatcode) {
MethodSymbol meth = tree.sym;
- // System.err.println("generating " + meth + " in " + meth.owner); //DEBUG
+ // System.err.println("generating " + meth + " in " + meth.owner); //DEBUG
if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) +
(((tree.mods.flags & STATIC) == 0 || meth.isConstructor()) ? 1 : 0) >
ClassFile.MAX_PARAMETERS) {
@@ -2056,11 +2089,21 @@
} else if ((sym.flags() & STATIC) != 0) {
if (!isAccessSuper(env.enclMethod))
sym = binaryQualifier(sym, env.enclClass.type);
- result = items.makeStaticItem(sym);
+ if ((sym.flags() & PROPERTY) != 0
+ && (env.enclMethod.sym.flags_field & PROPERTY) == 0) {
+ result = items.makePropertyItem((PropertySymbol)sym, true);
+ } else {
+ result = items.makeStaticItem(sym);
+ }
} else {
items.makeThisItem().load();
sym = binaryQualifier(sym, env.enclClass.type);
- result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
+ if ((sym.flags() & PROPERTY) != 0
+ && (env.enclMethod.sym.flags_field & PROPERTY) == 0) {
+ result = items.makePropertyItem((PropertySymbol)sym, (sym.flags() & PRIVATE) != 0);
+ } else {
+ result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
+ }
}
}
@@ -2108,7 +2151,12 @@
if (!selectSuper && (ssym == null || ssym.kind != TYP))
base = base.load();
base.drop();
- result = items.makeStaticItem(sym);
+ if ((sym.flags() & PROPERTY) != 0
+ && (env.enclMethod.sym.flags_field & PROPERTY) == 0) {
+ result = items.makePropertyItem((PropertySymbol) sym, true);
+ } else {
+ result = items.makeStaticItem(sym);
+ }
} else {
base.load();
if (sym == syms.lengthVar) {
@@ -2115,10 +2163,14 @@
code.emitop0(arraylength);
result = items.makeStackItem(syms.intType);
} else {
- result = items.
- makeMemberItem(sym,
- (sym.flags() & PRIVATE) != 0 ||
- selectSuper || accessSuper);
+ boolean nonVirtual = (sym.flags() & PRIVATE) != 0 ||
+ selectSuper || accessSuper;
+ if ((sym.flags() & PROPERTY) != 0
+ && (env.enclMethod.sym.flags_field & PROPERTY) == 0) {
+ result = items.makePropertyItem((PropertySymbol) sym, nonVirtual);
+ } else {
+ result = items.makeMemberItem(sym, nonVirtual);
+ }
}
}
}
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Items.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Items.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/jvm/Items.java (working copy)
@@ -141,7 +141,16 @@
* @param member The represented symbol.
*/
Item makeStaticItem(Symbol member) {
- return new StaticItem(member);
+ return new StaticItem(member);
+ }
+
+ /** Make an item representing a property.
+ * @param property The property symbol.
+ * @param nonvirtual Is the reference not virtual? (true for constructors
+ * and private members).
+ */
+ Item makePropertyItem(PropertySymbol property, boolean nonvirtual) {
+ return new PropertyItem(property, nonvirtual);
}
/** Make an item representing an instance variable or method.
@@ -150,7 +159,7 @@
* and private members).
*/
Item makeMemberItem(Symbol member, boolean nonvirtual) {
- return new MemberItem(member, nonvirtual);
+ return new MemberItem(member, nonvirtual);
}
/** Make an item representing a literal.
@@ -525,6 +534,79 @@
}
}
+ /** An item representing a property variable.
+ */
+ class PropertyItem extends Item {
+
+ /** The represented symbol.
+ */
+ PropertySymbol member;
+
+ /** Flag that determines whether or not access is virtual.
+ */
+ boolean nonvirtual;
+
+ PropertyItem(PropertySymbol member, boolean nonvirtual) {
+ super(Code.typecode(member.erasure(types)));
+ this.member = member;
+ this.nonvirtual = nonvirtual;
+ }
+
+ Item load() {
+ MethodSymbol getter=member.getter;
+ MethodType mtype = (MethodType)getter.erasure(types);
+ int rescode = Code.typecode(mtype.restype);
+ if ((member.owner.flags() & Flags.INTERFACE) != 0) {
+ code.emitInvokeinterface(pool.put(getter), mtype);
+ } else if ((member.flags() & Flags.STATIC) !=0 ) {
+ code.emitInvokestatic(pool.put(getter), mtype);
+ } else if (nonvirtual) {
+ code.emitInvokespecial(pool.put(getter), mtype);
+ } else {
+ code.emitInvokevirtual(pool.put(getter), mtype);
+ }
+ return stackItem[rescode];
+ }
+
+ void store() {
+ MethodSymbol setter=member.setter;
+ MethodType mtype = (MethodType)setter.erasure(types);
+ if ((member.owner.flags() & Flags.INTERFACE) != 0) {
+ code.emitInvokeinterface(pool.put(setter), mtype);
+ } else if ((member.flags() & Flags.STATIC) !=0 ) {
+ code.emitInvokestatic(pool.put(setter), mtype);
+ } else if (nonvirtual) {
+ code.emitInvokespecial(pool.put(setter), mtype);
+ } else {
+ code.emitInvokevirtual(pool.put(setter), mtype);
+ }
+ }
+
+ Item invoke() {
+ throw new AssertionError();
+ }
+
+ void duplicate() {
+ stackItem[OBJECTcode].duplicate();
+ }
+
+ void drop() {
+ stackItem[OBJECTcode].drop();
+ }
+
+ void stash(int toscode) {
+ stackItem[OBJECTcode].stash(toscode);
+ }
+
+ int width() {
+ return 1;
+ }
+
+ public String toString() {
+ return "property(" + member + (nonvirtual ? " nonvirtual)" : ")");
+ }
+ }
+
/** An item representing a literal.
*/
class ImmediateItem extends Item {
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Parser.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Parser.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Parser.java (working copy)
@@ -123,7 +123,11 @@
/** The name table. */
private Name.Table names;
-
+
+ private final boolean inferLocallyAlgol;
+ private final boolean inferLocallyFinal;
+ private final boolean allowProperty;
+
/** Construct a parser from a given scanner, tree factory and log.
*/
protected Parser(Factory fac,
@@ -144,6 +148,9 @@
this.allowForeach = source.allowForeach();
this.allowStaticImport = source.allowStaticImport();
this.allowAnnotations = source.allowAnnotations();
+ this.inferLocallyAlgol = "Algol".equals(options.get("inferLocally"));
+ this.inferLocallyFinal = "final".equals(options.get("inferLocally"));
+ this.allowProperty = options.get("allowProperty") != null;
this.keepDocComments = keepDocComments;
if (keepDocComments) docComments = new HashMap();
this.errorTree = F.Erroneous();
@@ -465,6 +472,10 @@
S.nextToken();
return name;
}
+ } else if (S.token() == PROPERTY) {
+ Name name = S.name();
+ S.nextToken();
+ return name;
} else {
accept(IDENTIFIER);
return names.error;
@@ -469,7 +480,7 @@
accept(IDENTIFIER);
return names.error;
}
-}
+ }
/**
* Qualident = Ident { DOT Ident }
@@ -931,7 +942,7 @@
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
case TRUE: case FALSE: case NULL:
- case NEW: case IDENTIFIER: case ASSERT: case ENUM:
+ case NEW: case IDENTIFIER: case ASSERT: case ENUM: case PROPERTY:
case BYTE: case SHORT: case CHAR: case INT:
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
JCExpression t1 = term3();
@@ -978,7 +989,7 @@
typeArgs = null;
} else return illegal();
break;
- case IDENTIFIER: case ASSERT: case ENUM:
+ case IDENTIFIER: case ASSERT: case ENUM: case PROPERTY:
if (typeArgs != null) return illegal();
t = toP(F.at(S.pos()).Ident(ident()));
loop: while (true) {
@@ -1545,12 +1556,27 @@
allowEnums && S.token() == ENUM) {
stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
} else {
+ Name name = S.name();
JCExpression t = type();
- stats.appendList(variableDeclarators(mods, t,
+ if (inferLocallyFinal && S.token() == EQ && t.tag == JCTree.IDENT && (mods.flags & Flags.FINAL) != 0) {
+ accept(EQ);
+ JCExpression init = variableInitializer();
+ stats.append(to(F.at(pos).VarDef(mods, name, null, init)));
+ accept(SEMI);
+ } else {
+ if (inferLocallyAlgol && S.token() == COLONASSIGN && t.tag == JCTree.IDENT) {
+ S.nextToken();
+ JCExpression init = variableInitializer();
+ stats.append(to(F.at(pos).VarDef(mods, name, null, init)));
+ accept(SEMI);
+ } else {
+ stats.appendList(variableDeclarators(mods, t,
new ListBuffer()));
- // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
- storeEnd(stats.elems.last(), S.endPos());
- accept(SEMI);
+ // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
+ storeEnd(stats.elems.last(), S.endPos());
+ accept(SEMI);
+ }
+ }
}
break;
}
@@ -1578,10 +1604,18 @@
break;
}
/* fall through to default */
+ case PROPERTY:
default:
Name name = S.name();
JCExpression t = term(EXPR | TYPE);
- if (S.token() == COLON && t.tag == JCTree.IDENT) {
+ if (inferLocallyAlgol && S.token() == COLONASSIGN && t.tag == JCTree.IDENT) {
+ S.nextToken();
+ JCExpression init = variableInitializer();
+ JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
+ stats.append(to(F.at(pos).VarDef(mods, name, null, init)));
+ accept(SEMI);
+
+ } else if (S.token() == COLON && t.tag == JCTree.IDENT) {
S.nextToken();
JCStatement stat = statement();
stats.append(F.at(pos).Labelled(name, stat));
@@ -1588,7 +1622,8 @@
} else if ((lastmode & TYPE) != 0 &&
(S.token() == IDENTIFIER ||
S.token() == ASSERT ||
- S.token() == ENUM)) {
+ S.token() == ENUM ||
+ S.token() == PROPERTY)) {
pos = S.pos();
JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
F.at(pos);
@@ -1740,7 +1775,7 @@
}
case BREAK: {
S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM || S.token() == PROPERTY) ? ident() : null;
JCBreak t = to(F.at(pos).Break(label));
accept(SEMI);
return t;
@@ -1747,7 +1782,7 @@
}
case CONTINUE: {
S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM || S.token() == PROPERTY) ? ident() : null;
JCContinue t = to(F.at(pos).Continue(label));
accept(SEMI);
return t;
@@ -1777,6 +1812,7 @@
/* else fall through to default case */
}
case ENUM:
+ case PROPERTY:
default:
Name name = S.name();
JCExpression expr = expression();
@@ -1873,14 +1909,32 @@
ListBuffer stats = lb();
int pos = S.pos();
if (S.token() == FINAL || S.token() == MONKEYS_AT) {
- return variableDeclarators(optFinal(0), type(), stats).toList();
+ JCModifiers mods=optFinal(0);
+ Name name = S.name();
+ JCExpression t=type();
+ if (inferLocallyFinal && S.token() == COLON && t.tag == JCTree.IDENT && (mods.flags & Flags.FINAL) != 0) {
+ return stats.append(to(F.at(pos).VarDef(mods, name, null, null))).toList();
+ } else {
+ if (inferLocallyAlgol && S.token() == COLON && t.tag == JCTree.IDENT) {
+ return stats.append(to(F.at(pos).VarDef(mods, name, null, null))).toList();
+ } else {
+ return variableDeclarators(mods, t, stats).toList();
+ }
+ }
} else {
+ Name name = S.name();
JCExpression t = term(EXPR | TYPE);
- if ((lastmode & TYPE) != 0 &&
- (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
- return variableDeclarators(modifiersOpt(), t, stats).toList();
- else
- return moreStatementExpressions(pos, t, stats).toList();
+ if ((lastmode & TYPE) != 0) {
+ if (inferLocallyAlgol && S.token() == COLON && t.tag == JCTree.IDENT) {
+ JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
+ return stats.append(to(F.at(pos).VarDef(mods, name, null, null))).toList();
+ } else {
+ if (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM || S.token() == PROPERTY) {
+ return variableDeclarators(modifiersOpt(), t, stats).toList();
+ }
+ }
+ }
+ return moreStatementExpressions(pos, t, stats).toList();
}
}
@@ -2056,6 +2110,25 @@
}
}
+ /** PropertyDeclaratorRest = BracketsOpt ["=" VariableInitializer]
+ *
+ * @param reqInit Is an initializer always required?
+ * @param dc The documentation comment for the variable declarations, or null.
+ */
+ JCPropertyDecl propertyDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
+ String dc) {
+ type = bracketsOpt(type);
+ JCExpression init = null;
+ if (S.token() == EQ) {
+ S.nextToken();
+ init = variableInitializer();
+ }
+ JCPropertyDecl result =
+ toP(F.at(pos).PropertyDef(mods, name, type, init));
+ attach(result, dc);
+ return result;
+ }
+
/** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
*/
public > T variableDeclarators(JCModifiers mods,
@@ -2274,7 +2347,7 @@
int pos = S.pos();
accept(CLASS);
Name name = ident();
-
+
List typarams = typeParametersOpt();
JCTree extending = null;
@@ -2498,6 +2571,7 @@
Name name = S.name();
pos = S.pos();
JCExpression type;
+ boolean isProperty = allowProperty && S.token() == PROPERTY;
boolean isVoid = S.token() == VOID;
if (isVoid) {
type = to(F.at(pos).TypeIdent(TypeTags.VOID));
@@ -2513,8 +2587,9 @@
isInterface, true, dc));
} else {
pos = S.pos();
- name = ident();
- if (S.token() == LPAREN) {
+ JCExpression type2 = type();
+ if (S.token() == LPAREN && type2.tag == JCTree.IDENT) {
+ name = ((JCIdent)type2).getName();
return List.of(methodDeclaratorRest(
pos, mods, type, name, typarams,
isInterface, isVoid, dc));
@@ -2519,16 +2594,26 @@
pos, mods, type, name, typarams,
isInterface, isVoid, dc));
} else if (!isVoid && typarams.isEmpty()) {
- List defs =
- variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
- new ListBuffer()).toList();
- storeEnd(defs.last(), S.endPos());
- accept(SEMI);
- return defs;
+ if (isProperty && S.token() == IDENTIFIER) {
+ name = ident();
+ JCPropertyDecl property=propertyDeclaratorRest(pos, mods, type2, name, dc);
+ accept(SEMI);
+ return List.of(property);
+ } else if (type2.tag == JCTree.IDENT) {
+ name = ((JCIdent)type2).getName();
+ List defs =
+ variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
+ new ListBuffer()).toList();
+ storeEnd(defs.last(), S.endPos());
+ accept(SEMI);
+ return defs;
+ } else {
+ return List.of(syntaxError(pos, "expected", keywords.token2string(IDENTIFIER)));
+ }
} else {
pos = S.pos();
- List err = isVoid
- ? List.of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
+ List err = (isVoid && type2.tag == JCTree.IDENT)
+ ? List.of(toP(F.at(pos).MethodDef(mods, ((JCIdent)type2).getName(), type, typarams,
List.nil(), List.nil(), null, null)))
: null;
return List.of(syntaxError(S.pos(), err, "expected", keywords.token2string(LPAREN)));
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Token.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Token.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/parser/Token.java (working copy)
@@ -76,6 +76,7 @@
PACKAGE("package"),
PRIVATE("private"),
PROTECTED("protected"),
+ PROPERTY("property"),
PUBLIC("public"),
RETURN("return"),
SHORT("short"),
@@ -111,6 +112,7 @@
COMMA(","),
DOT("."),
ELLIPSIS("..."),
+ COLONASSIGN(":="),
EQ("="),
GT(">"),
LT("<"),
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/resources/compiler.properties
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/resources/compiler.properties (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/resources/compiler.properties (working copy)
@@ -338,6 +338,12 @@
compiler.err.pkg.clashes.with.class.of.same.name=\
package {0} clashes with class of same name
+# Errors related to properties
+compiler.err.property.setter.not.defined=\
+ could not find getter {1} for property {0}
+compiler.err.property.setter.not.defined=\
+ could not find setter {1} for property {0}
+
# Errors related to annotation processing
compiler.err.proc.cant.access=\
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/JCTree.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/JCTree.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/JCTree.java (working copy)
@@ -43,7 +43,6 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol.*;
-import com.sun.source.tree.Tree;
import com.sun.source.tree.*;
import static com.sun.tools.javac.code.BoundKind.*;
@@ -105,10 +104,14 @@
/** Variable definitions, of type VarDef.
*/
public static final int VARDEF = METHODDEF + 1;
+
+ /** Property definitions, of type PropertyDef.
+ */
+ public static final int PROPERTYDEF = VARDEF + 1;
/** The no-op statement ";", of type Skip
*/
- public static final int SKIP = VARDEF + 1;
+ public static final int SKIP = PROPERTYDEF + 1;
/** Blocks, of type Block.
*/
@@ -720,6 +723,51 @@
return v.visitVariable(this, d);
}
}
+
+ /**
+ * A property definition.
+ * @param modifiers property modifiers
+ * @param name property name
+ * @param vartype type of the property
+ * @param init property initial value
+ * @param sym symbol
+ */
+ public static class JCPropertyDecl extends JCTree implements PropertyTree {
+ public JCModifiers mods;
+ public Name name;
+ public JCExpression proptype;
+ public JCExpression init;
+ public PropertySymbol sym;
+
+ /** field, null if the property is abstract.
+ */
+ public VarSymbol field;
+
+ protected JCPropertyDecl(JCModifiers mods,
+ Name name,
+ JCExpression proptype,
+ JCExpression init) {
+ super(PROPERTYDEF);
+ this.mods = mods;
+ this.name = name;
+ this.proptype = proptype;
+ this.init = init;
+ }
+ @Override
+ public void accept(Visitor v) { v.visitPropertyDef(this); }
+
+ public Kind getKind() { return Kind.PROPERTY; }
+ public JCModifiers getModifiers() { return mods; }
+ public Name getName() { return name; }
+ public JCTree getType() { return proptype; }
+ public JCExpression getInitializer() {
+ return init;
+ }
+ @Override
+ public R accept(TreeVisitor v, D d) {
+ return v.visitProperty(this, d);
+ }
+ }
/**
* A no-op statement ";".
@@ -1982,6 +2030,7 @@
public void visitClassDef(JCClassDecl that) { visitTree(that); }
public void visitMethodDef(JCMethodDecl that) { visitTree(that); }
public void visitVarDef(JCVariableDecl that) { visitTree(that); }
+ public void visitPropertyDef(JCPropertyDecl that) { visitTree(that); }
public void visitSkip(JCSkip that) { visitTree(that); }
public void visitBlock(JCBlock that) { visitTree(that); }
public void visitDoLoop(JCDoWhileLoop that) { visitTree(that); }
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/Pretty.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/Pretty.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/Pretty.java (working copy)
@@ -506,6 +506,26 @@
throw new UncheckedIOException(e);
}
}
+
+ public void visitPropertyDef(JCPropertyDecl tree) {
+ try {
+ if (docComments != null && docComments.get(tree) != null) {
+ println(); align();
+ }
+ printDocComment(tree);
+ printExpr(tree.mods);
+ print("property ");
+ printExpr(tree.proptype);
+ print(" " + tree.name);
+ if (tree.init != null) {
+ print(" = ");
+ printExpr(tree.init);
+ }
+ print(";");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
public void visitSkip(JCSkip tree) {
try {
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java (working copy)
@@ -385,6 +385,14 @@
JCExpression init = copy(t.init, p);
return M.at(t.pos).VarDef(mods, t.name, vartype, init);
}
+
+ public JCTree visitProperty(PropertyTree node, P p) {
+ JCPropertyDecl t = (JCPropertyDecl) node;
+ JCModifiers mods = copy(t.mods, p);
+ JCExpression proptype = copy(t.proptype, p);
+ JCExpression init = copy(t.init, p);
+ return M.at(t.pos).PropertyDef(mods, t.name, proptype, init);
+ }
public JCTree visitWhileLoop(WhileLoopTree node, P p) {
JCWhileLoop t = (JCWhileLoop) node;
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java (working copy)
@@ -191,6 +191,12 @@
tree.pos = pos;
return tree;
}
+
+ public JCPropertyDecl PropertyDef(JCModifiers mods, Name name, JCExpression proptype, JCExpression init) {
+ JCPropertyDecl tree = new JCPropertyDecl(mods, name, proptype, init);
+ tree.pos = pos;
+ return tree;
+ }
public JCSkip Skip() {
JCSkip tree = new JCSkip();
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java (working copy)
@@ -97,6 +97,12 @@
scan(tree.vartype);
scan(tree.init);
}
+
+ public void visitPropertyDef(JCPropertyDecl tree) {
+ scan(tree.mods);
+ scan(tree.proptype);
+ scan(tree.init);
+ }
public void visitSkip(JCSkip tree) {
}
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java (working copy)
@@ -154,6 +154,13 @@
tree.init = translate(tree.init);
result = tree;
}
+
+ public void visitPropertyDef(JCPropertyDecl tree) {
+ tree.mods = translate(tree.mods);
+ tree.proptype = translate(tree.proptype);
+ tree.init = translate(tree.init);
+ result = tree;
+ }
public void visitSkip(JCSkip tree) {
result = tree;
Index: /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/util/Name.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/util/Name.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/com/sun/tools/javac/util/Name.java (working copy)
@@ -469,6 +469,7 @@
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
Value = fromString("Value");
EnclosingMethod = fromString("EnclosingMethod");
+ Property = fromString("Property");
desiredAssertionStatus = fromString("desiredAssertionStatus");
@@ -481,6 +482,9 @@
value = fromString("value");
getMessage = fromString("getMessage");
getClass = fromString("getClass");
+ get = fromString("get");
+ is = fromString("is");
+ set = fromString("set");
TYPE = fromString("TYPE");
FIELD = fromString("FIELD");
@@ -603,6 +607,7 @@
public final Name Value;
public final Name EnclosingMethod;
+ public final Name Property;
public final Name desiredAssertionStatus;
@@ -615,6 +620,9 @@
public final Name value;
public final Name getMessage;
public final Name getClass;
+ public final Name get;
+ public final Name is;
+ public final Name set;
public final Name TYPE;
public final Name FIELD;
Index: /home/forax/java/workspace/java-compiler/src/share/classes/javax/lang/model/element/ElementKind.java
===================================================================
--- /home/forax/java/workspace/java-compiler/src/share/classes/javax/lang/model/element/ElementKind.java (revision 151)
+++ /home/forax/java/workspace/java-compiler/src/share/classes/javax/lang/model/element/ElementKind.java (working copy)
@@ -73,6 +73,10 @@
LOCAL_VARIABLE,
/** A parameter of an exception handler. */
EXCEPTION_PARAMETER,
+ /** A property.
+ * @since 1.7
+ */
+ PROPERTY,
// Executables
/** A method. */