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. */