diff options
author | Walter Harley | 2006-01-20 01:04:48 +0000 |
---|---|---|
committer | Walter Harley | 2006-01-20 01:04:48 +0000 |
commit | 6fea7eafdd413dccff31028f8da1f1ac6859e6fe (patch) | |
tree | d21f8a6a1a96c18c4c4706c412bbf5f2a589b773 | |
parent | c4c0df5e4aeb7d3e8571312c597020a7d0812327 (diff) | |
download | eclipse.jdt.core-6fea7eafdd413dccff31028f8da1f1ac6859e6fe.tar.gz eclipse.jdt.core-6fea7eafdd413dccff31028f8da1f1ac6859e6fe.tar.xz eclipse.jdt.core-6fea7eafdd413dccff31028f8da1f1ac6859e6fe.zip |
wharley - merge from 3.1.1 to 3.2. Base of merge is v20060120-0034.
30 files changed, 1076 insertions, 592 deletions
diff --git a/org.eclipse.jdt.apt.core/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jdt.apt.core/.settings/org.eclipse.core.resources.prefs index e1e45ea8e3..e9ac78be6a 100644 --- a/org.eclipse.jdt.apt.core/.settings/org.eclipse.core.resources.prefs +++ b/org.eclipse.jdt.apt.core/.settings/org.eclipse.core.resources.prefs @@ -1,6 +1,5 @@ -#Thu Aug 18 15:38:15 PDT 2005 +#Wed Jan 11 15:27:03 PST 2006 eclipse.preferences.version=1 encoding//src/org/eclipse/jdt/apt/core/build/messages.properties=8859_1 encoding//src/org/eclipse/jdt/apt/core/internal/messages.properties=8859_1 encoding//src/org/eclipse/jdt/apt/core/internal/util/messages.properties=8859_1 -encoding//src/org/eclipse/jdt/apt/core/messages.properties=8859_1 diff --git a/org.eclipse.jdt.apt.core/scripts/build-sdk-prime.cmd b/org.eclipse.jdt.apt.core/scripts/build-sdk-prime.cmd index 36b4485ef4..ded674b2ca 100644 --- a/org.eclipse.jdt.apt.core/scripts/build-sdk-prime.cmd +++ b/org.eclipse.jdt.apt.core/scripts/build-sdk-prime.cmd @@ -43,7 +43,7 @@ if NOT EXIST "%2" ( @set ROOT=%1 @set FULL_SDK_ZIP=%2 -@set APT_VERSION=3.1.1.apt02 +@set APT_VERSION=3.1.1.apt03 @set JDT_VERSION=3.1.1 @set TEMPDIR=\temp\eclipse_sdk_mod diff --git a/org.eclipse.jdt.apt.core/scripts/exportplugin.xml b/org.eclipse.jdt.apt.core/scripts/exportplugin.xml index 423d9e01d8..fb1b2e8c38 100644 --- a/org.eclipse.jdt.apt.core/scripts/exportplugin.xml +++ b/org.eclipse.jdt.apt.core/scripts/exportplugin.xml @@ -22,7 +22,7 @@ <target name="export plug-in [_1.0.0]"> <antcall target="zz_internal_export"> - <param name="plugin_version" value="3.1.1.apt02"/> + <param name="plugin_version" value="3.1.1.apt03"/> </antcall> </target> @@ -45,7 +45,7 @@ <echo message="UPDATE ${plugin}_${plugin_version}.jar" /> <zip zipfile="${plugin-dir}/${plugin}_${plugin_version}.jar"> <fileset dir="."> - <include name="tools.jar" /> + <include name="mirrorapi.jar" /> <include name="plugin.xml" /> <include name="plugin.properties" /> <include name="META-INF/**" /> diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java index 4fff1fb633..14af0a5fbe 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java @@ -11,14 +11,11 @@ package org.eclipse.jdt.apt.core; -import java.io.IOException; -import java.io.InputStream; import java.util.Map; import java.util.WeakHashMap; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; @@ -33,15 +30,12 @@ import org.osgi.framework.BundleContext; public class AptPlugin extends Plugin { public static final String PLUGIN_ID = "org.eclipse.jdt.apt.core"; //$NON-NLS-1$ - private static final String TOOLSJARNAME = "./tools.jar"; //$NON-NLS-1$ - /** * Status IDs for system log entries. Must be unique per plugin. */ public static final int STATUS_EXCEPTION = 1; public static final int STATUS_NOTOOLSJAR = 2; public static final int STATUS_CANTLOADPLUGINFACTORY = 3; - public static final String ERRTXT_NOTOOLSJAR = Messages.AptPlugin_couldNotFindToolsDotJar; public static final String APT_BATCH_PROCESSOR_PROBLEM_MARKER = PLUGIN_ID + ".marker"; //$NON-NLS-1$ /** Marker ID used for build problem, e.g., missing factory jar */ @@ -62,7 +56,6 @@ public class AptPlugin extends Plugin { thePlugin = this; super.start(context); initDebugTracing(); - checkToolsJar(); AptConfig.initialize(); AnnotationProcessorFactoryLoader.getLoader(); // register resource-changed listener @@ -73,27 +66,6 @@ public class AptPlugin extends Plugin { trace("registered resource change listener"); //$NON-NLS-1$ } - /** - * Check for the Sun mirror interfaces. If they aren't found, - * log an error. - */ - private void checkToolsJar() { - boolean foundToolsJar = true; - InputStream is = null; - try { - is = thePlugin.openStream(new Path(TOOLSJARNAME)); - } - catch (IOException e) { - foundToolsJar = false; - } - finally { - try {if (is != null) is.close();} catch (IOException ioe) {} - } - if (!foundToolsJar) { - log(new Status(IStatus.ERROR, PLUGIN_ID, STATUS_NOTOOLSJAR, ERRTXT_NOTOOLSJAR, null)); - } - } - public void stop(BundleContext context) throws Exception { super.stop(context); } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/Messages.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/Messages.java deleted file mode 100644 index f82c96a003..0000000000 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/Messages.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005 BEA Systems, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * jgarms@bea.com - initial API and implementation - * - *******************************************************************************/ -package org.eclipse.jdt.apt.core; - -import org.eclipse.osgi.util.NLS; - -public class Messages extends NLS { - private static final String BUNDLE_NAME = "org.eclipse.jdt.apt.core.messages"; //$NON-NLS-1$ - - private Messages() { - } - - static { - // initialize resource bundle - NLS.initializeMessages(BUNDLE_NAME, Messages.class); - } - - public static String AptPlugin_couldNotFindToolsDotJar; -} diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java index 249090f75e..b42b8330af 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java @@ -41,46 +41,33 @@ public class AptProject { } /** + * This method should be called whenever compilation begins, to perform + * initialization and verify configuration. + */ + public void compilationStarted() { + _gfm.compilationStarted(); + } + + /** * This method should be called whenever project preferences are - * changed by the user. It is safe to call it on every change; - * irrelevant changes will be efficiently ignored. This may cause - * the classpath and generated source folder to change, so this - * should <em>not</em> be called from a resource change listener, - * preference change listener, or other context where resources - * may be locked. + * changed by the user. This may cause the classpath and generated + * source folder to change, so this should <em>not</em> be called + * from a context where resources may be locked, e.g., within + * certain resource change listeners. * @param key a preference key such as @see AptPreferenceConstants#APT_ENABLED * @param oldValue the old value, or null if unknown * @param newValue the new value, which will be ignored if it is null */ - public void handlePreferenceChange(String key, String oldValue, String newValue) { - if (newValue == null) { - // Null is used to indicate this preference has - // been removed, as the project has been deleted. - // We do nothing. - return; - } - if (newValue.equals(oldValue)) { - // Nothing has changed - return; - } - + public void preferenceChanged(String key) { if (AptPreferenceConstants.APT_GENSRCDIR.equals(key)) { - _gsfm.changeFolderName(oldValue, newValue); + _gsfm.folderNamePreferenceChanged(); } else if(AptPreferenceConstants.APT_ENABLED.equals(key) ){ - _gsfm.setEnabled(Boolean.parseBoolean(newValue)); + _gsfm.enabledPreferenceChanged(); } } /** - * This method should be called whenever compilation begins, to perform - * initialization and verify configuration. - */ - public void compilationStarted() { - _gfm.compilationStarted(); - } - - /** * Invoked whenever a project is cleaned. This will remove any state kept about * generated files for the given project. If the deleteFiles flag is specified, * then the contents of the generated source folder will be deleted. @@ -135,5 +122,5 @@ public class AptProject { { _gfm.clearAllMaps(); } - + } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedConstructorDeclarationImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedConstructorDeclarationImpl.java new file mode 100644 index 0000000000..e5e3529e31 --- /dev/null +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedConstructorDeclarationImpl.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2005 BEA Systems, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tyeung@bea.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.apt.core.internal.declaration; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; +import com.sun.mirror.declaration.ConstructorDeclaration; + +import com.sun.mirror.util.DeclarationVisitor; + +public class ASTBasedConstructorDeclarationImpl + extends ASTBasedExecutableDeclarationImpl + implements ConstructorDeclaration{ + + public ASTBasedConstructorDeclarationImpl( + final org.eclipse.jdt.core.dom.BodyDeclaration astNode, + final IFile file, + final BaseProcessorEnv env) + { + super(astNode, file, env); + } + + public void accept(DeclarationVisitor visitor) + { + super.accept(visitor); + visitor.visitConstructorDeclaration(this); + } + + public MirrorKind kind(){ return MirrorKind.CONSTRUCTOR; } +} diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedExecutableDeclarationImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedExecutableDeclarationImpl.java new file mode 100644 index 0000000000..1c1bc986a3 --- /dev/null +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedExecutableDeclarationImpl.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2005 BEA Systems, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tyeung@bea.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.apt.core.internal.declaration; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.TypeParameter; + +import com.sun.mirror.declaration.ExecutableDeclaration; +import com.sun.mirror.declaration.ParameterDeclaration; +import com.sun.mirror.declaration.TypeParameterDeclaration; +import com.sun.mirror.type.ReferenceType; +import com.sun.mirror.util.DeclarationVisitor; + +public abstract class ASTBasedExecutableDeclarationImpl + extends ASTBasedMemberDeclarationImpl + implements ExecutableDeclaration{ + + public ASTBasedExecutableDeclarationImpl( + final org.eclipse.jdt.core.dom.BodyDeclaration astNode, + final IFile file, + final BaseProcessorEnv env) + { + super(astNode, file, env); + } + + public void accept(DeclarationVisitor visitor) + { + super.accept(visitor); + visitor.visitExecutableDeclaration(this); + } + + public Collection<TypeParameterDeclaration> getFormalTypeParameters() + { + return ExecutableUtil.getFormalTypeParameters(this, _env); + } + + public Collection<ParameterDeclaration> getParameters() + { + return ExecutableUtil.getParameters(this, _env); + } + + public Collection<ReferenceType> getThrownTypes() + { + return ExecutableUtil.getThrownTypes(this, _env); + } + + public boolean isVarArgs() + { + return getMethodAstNode().isVarargs(); + } + + public String getSimpleName() + { + final org.eclipse.jdt.core.dom.MethodDeclaration methodAstNode = getMethodAstNode(); + final SimpleName nameNode = methodAstNode.getName(); + return nameNode == null ? EMPTY_STRING : nameNode.getIdentifier(); + } + + org.eclipse.jdt.core.dom.MethodDeclaration getMethodAstNode(){ + return (org.eclipse.jdt.core.dom.MethodDeclaration)_astNode; + } + + public String toString() + { + final StringBuilder buffer = new StringBuilder(); + final org.eclipse.jdt.core.dom.MethodDeclaration methodAstNode = getMethodAstNode(); + @SuppressWarnings("unchecked") + final List<TypeParameter> typeParams = methodAstNode.typeParameters(); + if( typeParams != null && typeParams.size() > 0 ){ + buffer.append('<'); + for(int i=0, size=typeParams.size(); i<size; i++ ){ + if( i != 0 ) + buffer.append(", "); //$NON-NLS-1$ + buffer.append(typeParams.get(i).toString()); + } + buffer.append('>'); + } + + if( methodAstNode.getReturnType2() != null ) + buffer.append(methodAstNode.getReturnType2()); + buffer.append(' '); + buffer.append(methodAstNode.getName()); + buffer.append('('); + int i=0; + @SuppressWarnings("unchecked") + final List<SingleVariableDeclaration> params = methodAstNode.parameters(); + for( SingleVariableDeclaration param : params ){ + if( i++ != 0 ) + buffer.append(", "); //$NON-NLS-1$ + buffer.append(param.getName()); + } + buffer.append(')'); + + return buffer.toString(); + } + +} diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedMethodDeclarationImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedMethodDeclarationImpl.java index b77713f41c..70d4a4f2ef 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedMethodDeclarationImpl.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ASTBasedMethodDeclarationImpl.java @@ -10,28 +10,18 @@ *******************************************************************************/ package org.eclipse.jdt.apt.core.internal.declaration; - -import java.util.Collection; -import java.util.List; - import org.eclipse.core.resources.IFile; import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; import org.eclipse.jdt.apt.core.internal.util.Factory; import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeParameter; import com.sun.mirror.declaration.MethodDeclaration; -import com.sun.mirror.declaration.ParameterDeclaration; -import com.sun.mirror.declaration.TypeParameterDeclaration; -import com.sun.mirror.type.ReferenceType; import com.sun.mirror.type.TypeMirror; import com.sun.mirror.util.DeclarationVisitor; public class ASTBasedMethodDeclarationImpl - extends ASTBasedMemberDeclarationImpl + extends ASTBasedExecutableDeclarationImpl implements MethodDeclaration{ public ASTBasedMethodDeclarationImpl( @@ -45,37 +35,9 @@ public class ASTBasedMethodDeclarationImpl public void accept(DeclarationVisitor visitor) { super.accept(visitor); - visitor.visitExecutableDeclaration(this); visitor.visitMethodDeclaration(this); } - public Collection<TypeParameterDeclaration> getFormalTypeParameters() - { - return ExecutableUtil.getFormalTypeParameters(this, _env); - } - - public Collection<ParameterDeclaration> getParameters() - { - return ExecutableUtil.getParameters(this, _env); - } - - public Collection<ReferenceType> getThrownTypes() - { - return ExecutableUtil.getThrownTypes(this, _env); - } - - public boolean isVarArgs() - { - return getMethodAstNode().isVarargs(); - } - - public String getSimpleName() - { - final org.eclipse.jdt.core.dom.MethodDeclaration methodAstNode = getMethodAstNode(); - final SimpleName nameNode = methodAstNode.getName(); - return nameNode == null ? EMPTY_STRING : nameNode.getIdentifier(); - } - public TypeMirror getReturnType() { final org.eclipse.jdt.core.dom.MethodDeclaration methodAstNode = getMethodAstNode(); @@ -97,42 +59,5 @@ public class ASTBasedMethodDeclarationImpl } public MirrorKind kind(){ return MirrorKind.METHOD; } - - private org.eclipse.jdt.core.dom.MethodDeclaration getMethodAstNode(){ - return (org.eclipse.jdt.core.dom.MethodDeclaration)_astNode; - } - - public String toString() - { - final StringBuilder buffer = new StringBuilder(); - final org.eclipse.jdt.core.dom.MethodDeclaration methodAstNode = getMethodAstNode(); - @SuppressWarnings("unchecked") - final List<TypeParameter> typeParams = methodAstNode.typeParameters(); - if( typeParams != null && typeParams.size() > 0 ){ - buffer.append('<'); - for(int i=0, size=typeParams.size(); i<size; i++ ){ - if( i != 0 ) - buffer.append(", "); //$NON-NLS-1$ - buffer.append(typeParams.get(i).toString()); - } - buffer.append('>'); - } - if( methodAstNode.getReturnType2() != null ) - buffer.append(methodAstNode.getReturnType2()); - buffer.append(' '); - buffer.append(methodAstNode.getName()); - buffer.append('('); - int i=0; - @SuppressWarnings("unchecked") - final List<SingleVariableDeclaration> params = methodAstNode.parameters(); - for( SingleVariableDeclaration param : params ){ - if( i++ != 0 ) - buffer.append(", "); //$NON-NLS-1$ - buffer.append(param.getName()); - } - buffer.append(')'); - - return buffer.toString(); - } } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ClassDeclarationImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ClassDeclarationImpl.java index 869b8f0f19..81f213493e 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ClassDeclarationImpl.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/ClassDeclarationImpl.java @@ -15,8 +15,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.eclipse.core.resources.IFile; import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; import org.eclipse.jdt.apt.core.internal.util.Factory; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; @@ -42,11 +46,66 @@ public class ClassDeclarationImpl extends TypeDeclarationImpl implements ClassDe super.accept(visitor); visitor.visitClassDeclaration(this); } + + private void getASTConstructor( + final AbstractTypeDeclaration typeDecl, + final List<ConstructorDeclaration> results){ + + final List bodyDecls = typeDecl.bodyDeclarations(); + for( int i=0, len=bodyDecls.size(); i<len; i++ ){ + final BodyDeclaration bodyDecl = (BodyDeclaration)bodyDecls.get(i); + IFile file = null; + if( bodyDecl.getNodeType() == ASTNode.METHOD_DECLARATION ){ + final org.eclipse.jdt.core.dom.MethodDeclaration methodDecl = + (org.eclipse.jdt.core.dom.MethodDeclaration)bodyDecl; + + if( methodDecl.isConstructor() ){ + final IMethodBinding methodBinding = methodDecl.resolveBinding(); + // built an ast based representation. + if( methodBinding == null ){ + if( file == null ) + file = getResource(); + ConstructorDeclaration mirrorDecl = + (ConstructorDeclaration)Factory.createDeclaration(methodDecl, file, _env); + if( mirrorDecl != null ) + results.add(mirrorDecl); + } + } + } + } + } public Collection<ConstructorDeclaration> getConstructors() { + final List<ConstructorDeclaration> results = new ArrayList<ConstructorDeclaration>(); + if( isFromSource() ){ + // need to consult the ast since methods with broken signature + // do not appear in bindings. + final ITypeBinding typeBinding = getDeclarationBinding(); + final ASTNode node = + _env.getASTNodeForBinding(typeBinding); + if( node != null ){ + switch( node.getNodeType() ) + { + case ASTNode.TYPE_DECLARATION: + case ASTNode.ANNOTATION_TYPE_DECLARATION: + case ASTNode.ENUM_DECLARATION: + AbstractTypeDeclaration typeDecl = + (AbstractTypeDeclaration)node; + // built the ast based methods first. + getASTConstructor(typeDecl, results); + break; + default: + // the ast node for a type binding should be a AbstractTypeDeclaration. + throw new IllegalStateException("expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$ + + node.getClass().getName() ); + } + } + } + // build methods for binding type or + // build the binding based method for source type. + final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods(); - final List<ConstructorDeclaration> results = new ArrayList<ConstructorDeclaration>(methods.length); for( IMethodBinding method : methods ){ if( method.isSynthetic() ) continue; if( method.isConstructor() ){ diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/TypeDeclarationImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/TypeDeclarationImpl.java index 44f7ac2ac2..799f45ef2d 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/TypeDeclarationImpl.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/declaration/TypeDeclarationImpl.java @@ -16,11 +16,18 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.eclipse.core.resources.IFile; import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; import org.eclipse.jdt.apt.core.internal.util.Factory; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import com.sun.mirror.declaration.*; import com.sun.mirror.type.DeclaredType; @@ -65,11 +72,59 @@ public abstract class TypeDeclarationImpl extends MemberDeclarationImpl implemen } public ITypeBinding getTypeBinding(){ return (ITypeBinding)_binding; } + + private void getASTFields( + final AbstractTypeDeclaration typeDecl, + final List<FieldDeclaration> results){ + final List bodyDecls = typeDecl.bodyDeclarations(); + for( int i=0, len=bodyDecls.size(); i<len; i++ ){ + final BodyDeclaration bodyDecl = (BodyDeclaration)bodyDecls.get(i); + IFile file = null; + if( bodyDecl.getNodeType() == ASTNode.FIELD_DECLARATION ){ + final List<VariableDeclarationFragment> fragments = + ((org.eclipse.jdt.core.dom.FieldDeclaration)bodyDecl).fragments(); + for( VariableDeclarationFragment frag : fragments ){ + final IBinding fieldBinding = frag.resolveBinding(); + if( fieldBinding == null ){ + if( file == null ) + file = getResource(); + final EclipseDeclarationImpl decl = Factory.createDeclaration(frag, file, _env); + if( decl != null ) + results.add((FieldDeclaration)decl); + } + } + } + } + } public Collection<FieldDeclaration> getFields() { - final IVariableBinding[] fields = getDeclarationBinding().getDeclaredFields(); - final List<FieldDeclaration> results = new ArrayList<FieldDeclaration>(fields.length); + final List<FieldDeclaration> results = new ArrayList<FieldDeclaration>(); + final ITypeBinding typeBinding = getDeclarationBinding(); + if( isFromSource() ){ + final ASTNode node = + _env.getASTNodeForBinding(typeBinding); + if( node != null ){ + switch( node.getNodeType() ) + { + case ASTNode.TYPE_DECLARATION: + case ASTNode.ANNOTATION_TYPE_DECLARATION: + case ASTNode.ENUM_DECLARATION: + AbstractTypeDeclaration typeDecl = + (AbstractTypeDeclaration)node; + // built the ast based methods first. + getASTFields(typeDecl, results); + break; + default: + // the ast node for a type binding should be a AbstractTypeDeclaration. + throw new IllegalStateException("expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$ + + node.getClass().getName() ); + } + } + } + // either type is binary or + // constructing the binding based fields for source type. + final IVariableBinding[] fields = typeBinding.getDeclaredFields(); for( IVariableBinding field : fields ){ // note that the name HAS_INCONSISTENT_TYPE_HIERACHY is not a legal java identifier // so there is no chance that we are filtering out actual declared fields. @@ -179,11 +234,83 @@ public abstract class TypeDeclarationImpl extends MemberDeclarationImpl implemen final ITypeBinding type = getTypeBinding(); return type.getTypeDeclaration(); } + + /** + * create mirror methods that does not have a binding represention. + */ + protected void getASTMethods( + final AbstractTypeDeclaration typeDecl, + final List<MethodDeclaration> results){ + final List bodyDecls = typeDecl.bodyDeclarations(); + for( int i=0, len=bodyDecls.size(); i<len; i++ ){ + final BodyDeclaration bodyDecl = (BodyDeclaration)bodyDecls.get(i); + IFile file = null; + switch(bodyDecl.getNodeType()){ + case ASTNode.METHOD_DECLARATION: + final org.eclipse.jdt.core.dom.MethodDeclaration methodDecl = + (org.eclipse.jdt.core.dom.MethodDeclaration)bodyDecl; + + if( !methodDecl.isConstructor() ){ + final IMethodBinding methodBinding = methodDecl.resolveBinding(); + // built an ast based representation. + if( methodBinding == null ){ + if( file == null ) + file = getResource(); + MethodDeclaration mirrorDecl = + (MethodDeclaration)Factory.createDeclaration(methodDecl, file, _env); + if( mirrorDecl != null ) + results.add(mirrorDecl); + } + } + break; + case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION: + final AnnotationTypeMemberDeclaration memberDecl = + (AnnotationTypeMemberDeclaration)bodyDecl; + final IMethodBinding methodBinding = memberDecl.resolveBinding(); + // built an ast based representation. + if( methodBinding == null ){ + if( file == null ) + file = getResource(); + MethodDeclaration mirrorDecl = + (MethodDeclaration)Factory.createDeclaration(memberDecl, file, _env); + if( mirrorDecl != null ) + results.add(mirrorDecl); + } + break; + } + } + } protected List<? extends MethodDeclaration> _getMethods() { - final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods(); - final List<MethodDeclaration> results = new ArrayList<MethodDeclaration>(methods.length); + final List<MethodDeclaration> results = new ArrayList<MethodDeclaration>(); + if( isFromSource() ){ + // need to consult the ast since methods with broken signature + // do not appear in bindings. + final ITypeBinding typeBinding = getDeclarationBinding(); + final ASTNode node = + _env.getASTNodeForBinding(typeBinding); + if( node != null ){ + switch( node.getNodeType() ) + { + case ASTNode.TYPE_DECLARATION: + case ASTNode.ANNOTATION_TYPE_DECLARATION: + case ASTNode.ENUM_DECLARATION: + AbstractTypeDeclaration typeDecl = + (AbstractTypeDeclaration)node; + // built the ast based methods first. + getASTMethods(typeDecl, results); + break; + default: + // the ast node for a type binding should be a AbstractTypeDeclaration. + throw new IllegalStateException("expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$ + + node.getClass().getName() ); + } + } + } + // build methods for binding type or + // build the binding based method for source type. + final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods(); for( IMethodBinding method : methods ){ if( method.isConstructor() || method.isSynthetic() ) continue; Declaration mirrorDecl = Factory.createDeclaration(method, _env); diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java index 121f2107d7..5648e6b41c 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java @@ -98,6 +98,8 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment private static final int SHORT_INDEX = 7; private static final int VOID_INDEX = 8; + private static final String DOT_JAVA = ".java"; //$NON-NLS-1$ + protected CompilationUnit _astRoot; protected final Phase _phase; protected IFile _file; @@ -203,7 +205,7 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment if( type == null ) return; typeBindings.add(type); for( ITypeBinding nestedType : type.getDeclaredTypes() ) { - typeBindings.add(nestedType); + //typeBindings.add(nestedType); getTypeBindings(nestedType, typeBindings); } } @@ -371,7 +373,7 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment return Factory.createReferenceType(typeBinding, this); // finally go search for it in the universe. - typeBinding = getTypeBinding(typeKey); + typeBinding = getTypeDefinitionBindingFromName(name); if( typeBinding != null ){ return Factory.createReferenceType(typeBinding, this); } @@ -380,14 +382,45 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment } /** - * @param key the key to a type binding, could be reference type, array or primitive. - * @return the binding corresponding to the given key or null if none is found. - */ - public ITypeBinding getTypeBinding(final String key) - { + * @param fullyQualifiedName the fully qualified name of a type. + * The name cannot contain type argument or array signature. + * @return the type binding corresponding to the parameter. + */ + ITypeBinding getTypeDefinitionBindingFromName( + final String fullyQualifiedName ){ + final int dollarIndex = fullyQualifiedName.indexOf('$'); + final String toplevelTypeName; + if( dollarIndex < 0 ) + toplevelTypeName = fullyQualifiedName; + else + toplevelTypeName = fullyQualifiedName.substring(0, dollarIndex); + + // locate the compilation unit for the type of interest. + // we need this information so that when we request the binding for 'fullyQualifiedName' + // we can get the dom pipeline to return back to us the ast compilation unit + // which we will need to correctly compute the number of methods, fields and constructors. + // see CR259011 -theodora + ICompilationUnit unit = getICompilationUnitForTopLevelType(toplevelTypeName); + final String key = BindingKey.createTypeBindingKey(fullyQualifiedName); + return getTypeBindingFromKey(key, unit); + } + + /** + * @param key + * @param unit the unit that contains the definition of type whose type key is <code>key</code> + * if <code>key</code> is a wild card, primitive, array type or parameterized type, this should be null. + * @return return the type binding for the given key or null if none is found. + */ + private ITypeBinding getTypeBindingFromKey(final String key, final ICompilationUnit unit){ + class BindingRequestor extends ASTRequestor { private ITypeBinding _result = null; + public void acceptAST(ICompilationUnit source, CompilationUnit ast) { + if( source == unit ){ + _modelCompUnit2astCompUnit.put(source, ast); + } + } public void acceptBinding(String bindingKey, IBinding binding) { if( binding != null && binding.getKind() == IBinding.TYPE ) @@ -399,8 +432,28 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment final ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setResolveBindings(true); parser.setProject(_javaProject); - parser.createASTs(NO_UNIT, new String[]{key}, requestor, null); - return requestor._result; + ICompilationUnit[] units = unit == null ? NO_UNIT : new ICompilationUnit[]{unit}; + parser.createASTs(units, new String[]{key}, requestor, null); + final ITypeBinding result = requestor._result; + if(result != null && unit != null){ + final CompilationUnit astUnit = _modelCompUnit2astCompUnit.get(unit); + // make sure everything is lining up properly. + if( astUnit.findDeclaringNode(result) != null ){ + ITypeBinding declaringClass = getDeclaringClass(result); + _typeBinding2ModelCompUnit.put(declaringClass, unit); + } + } + return result; + } + + /** + * @param key the key to a type binding, could be reference type, array or primitive. + * @return the binding corresponding to the given key or null if none is found. + */ + public ITypeBinding getTypeBindingFromKey(final String key) + { + return getTypeBindingFromKey(key, null); + } public TypeDeclaration getTypeDeclaration(final IType type) { @@ -500,6 +553,28 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment return _astRoot; return null; } + + /** + * Retrieve the <code>ICompilationUnit</code> whose top-level type has + * <code>topTypeQName</code> as its fully qualified name. + * @param topTypeQName + * @return the <code>ICompilationUnit</code> matching <code>topTypeQName</code> or + * <code>null</code> if one doesn't exist. + */ + private ICompilationUnit getICompilationUnitForTopLevelType(final String topTypeQName ){ + final String pathname = topTypeQName.replace('.', File.separatorChar) + DOT_JAVA; + final IPath path = Path.fromOSString(pathname); + try{ + final IJavaElement element = _javaProject.findElement(path); + if( element instanceof ICompilationUnit ) + return (ICompilationUnit)element; + else // dropping class files. + return null; + } + catch(JavaModelException e){ + return null; + } + } /** * @param binding must be correspond to a type, method or field declaration. @@ -521,19 +596,14 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment } else{ final ITypeBinding typeBinding = getDeclaringClass(binding); + // binary type don't have compilation unit. + if( !typeBinding.isFromSource() ) + return null; if( _typeBinding2ModelCompUnit.get(typeBinding) != null ) unit = _typeBinding2ModelCompUnit.get(typeBinding); else{ final String qname = typeBinding.getQualifiedName(); - final String pathname = qname.replace('.', File.separatorChar); - final IPath path = Path.fromOSString(pathname); - try{ - unit = (ICompilationUnit)_javaProject.findElement(path); - _typeBinding2ModelCompUnit.put(typeBinding, unit); - } - catch(JavaModelException e){ - throw new IllegalStateException(e); - } + unit = getICompilationUnitForTopLevelType(qname); } } if( unit == null ) return null; @@ -621,18 +691,14 @@ public class BaseProcessorEnv implements AnnotationProcessorEnvironment else{ final ITypeBinding type = getDeclaringClass(binding); assert type.isTopLevel() : "type must be top-level type"; //$NON-NLS-1$ + ICompilationUnit unit = _typeBinding2ModelCompUnit.get(type); + if( unit != null ) + return (IFile)unit.getResource(); final String qname = type.getQualifiedName(); - final String pathname = qname.replace('.', File.separatorChar); - final IPath path = Path.fromOSString(pathname); - try{ - // the element would be a compilation unit. - final IJavaElement element = _javaProject.findElement(path); - if( element == null ) return null; - return (IFile)element.getResource(); - } - catch(JavaModelException e){ - throw new IllegalStateException(e); - } + unit = getICompilationUnitForTopLevelType(qname); + if( unit == null ) + return null; + return (IFile)unit.getResource(); } } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java index 3377f386b5..1c4f80eb82 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java @@ -105,8 +105,14 @@ public class BinaryFileOutputStream extends ByteArrayOutputStream { } } catch (CoreException ce) { - AptPlugin.log(ce, "Could not create generated file"); //$NON-NLS-1$ - throw new IOException(ce.getMessage()); + if (_file.exists()) { + // Do nothing. This is a case-insensitive file system mismatch, + // and the underlying platform has saved the contents already. + } + else { + AptPlugin.log(ce, "Could not create generated file"); //$NON-NLS-1$ + throw new IOException(ce.getMessage()); + } } } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java index 7e60e6c7c8..f673b4acd2 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java @@ -181,7 +181,7 @@ public class ProcessorEnvImpl extends CompilationProcessorEnv } // finally go search for it in the universe. - typeBinding = getTypeBinding(typeKey); + typeBinding = getTypeDefinitionBindingFromName(name); if( typeBinding != null ){ return Factory.createReferenceType(typeBinding, this); } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/ClasspathUtil.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/ClasspathUtil.java index 6f2faffe65..1d8e293bad 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/ClasspathUtil.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/ClasspathUtil.java @@ -61,7 +61,7 @@ public class ClasspathUtil { * @return * @throws JavaModelException */ - public static boolean isProjectClassPathUpToDate( + public static boolean doesClasspathContainEntry( IJavaProject jp, IClasspathEntry[] cp, IPath path, @@ -88,7 +88,7 @@ public class ClasspathUtil { { IClasspathEntry[] cp = jp.getRawClasspath(); IPath workspaceRelativePath = folder.getFullPath(); - boolean found = isProjectClassPathUpToDate(jp, cp, workspaceRelativePath, progressMonitor); + boolean found = doesClasspathContainEntry(jp, cp, workspaceRelativePath, progressMonitor); if( found ){ IPath projectRelativePath = folder.getProjectRelativePath().addTrailingSeparator(); @@ -150,7 +150,7 @@ public class ClasspathUtil { { IClasspathEntry[] cp = jp.getRawClasspath(); IPath path = folder.getFullPath(); - boolean found = ClasspathUtil.isProjectClassPathUpToDate(jp, cp, path, progressMonitor); + boolean found = ClasspathUtil.doesClasspathContainEntry(jp, cp, path, progressMonitor); if (!found) { diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java index f28eb4ac48..2488731487 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java @@ -778,11 +778,11 @@ public class GeneratedFileManager { AptPlugin.log(e, "Unable to delete configuration marker."); //$NON-NLS-1$ } _skipTypeGeneration = false; - _gsfm.createGeneratedSourceFolder(); + _gsfm.ensureFolderExists(); final IFolder genFolder; synchronized(this){ genFolder = _gsfm.getFolder(); - _snapshotFolderName = _gsfm.getFolderName(); + _snapshotFolderName = genFolder.getProjectRelativePath().toString(); } try { _generatedPackageFragmentRoot = null; diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java index 9f3be3b1ec..75bbed4371 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java @@ -72,13 +72,13 @@ public class GeneratedResourceChangeListener implements IResourceChangeListener } } -private void addGeneratedSrcFolderTo(final Set<IProject> projs ){ + private void addGeneratedSrcFolderTo(final Set<IProject> projs ){ for(IProject proj : projs ){ final IJavaProject javaProj = JavaCore.create(proj); if(AptConfig.isEnabled(javaProj)){ final GeneratedSourceFolderManager gsfm = AptPlugin.getAptProject(javaProj).getGeneratedSourceFolderManager(); - gsfm.createGeneratedSourceFolder(); + gsfm.ensureFolderExists(); } } @@ -117,7 +117,7 @@ private void addGeneratedSrcFolderTo(final Set<IProject> projs ){ final GeneratedSourceFolderManager gsfm = aptProj.getGeneratedSourceFolderManager(); IFolder f = (IFolder) r; if ( gsfm.isGeneratedSourceFolder( f ) ){ - gsfm.generatedSourceFolderDeleted(); + gsfm.folderDeleted(); // all deletion occurs before any add (adding the generated source directory) if( !_removedProjects.contains(project) ){ _addGenFolderTo.add(project); diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedSourceFolderManager.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedSourceFolderManager.java index 7d728a16ea..142a57716b 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedSourceFolderManager.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedSourceFolderManager.java @@ -11,20 +11,15 @@ package org.eclipse.jdt.apt.core.internal.generatedfile; -import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.apt.core.AptPlugin; import org.eclipse.jdt.apt.core.internal.AptProject; import org.eclipse.jdt.apt.core.internal.util.FileSystemUtil; import org.eclipse.jdt.apt.core.util.AptConfig; -import org.eclipse.jdt.apt.core.util.AptPreferenceConstants; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaModelException; @@ -47,7 +42,7 @@ import org.eclipse.jdt.core.JavaModelException; * </ul> * We attempt to change the classpath entry and the folder on disk whenever * the enabled/disabled state or the folder name change. These changes are - * discovered via the handlePreferenceChange() method. + * discovered via the preferenceChanged() method. * <p> * GeneratedSourceFolderManager is responsible only for the folder itself, not * its contents. Contents are managed by @see GeneratedFileManager. @@ -58,21 +53,26 @@ public class GeneratedSourceFolderManager { private final AptProject _aptProject; /** - * The folder where generated source files are placed. This will be null until - * the folder is actually created and the project's source path is updated to - * include the folder. It will also be null if there was an error creating the - * folder. + * The folder where generated source files are placed. This will be + * null if APT is disabled, or in any other error state (e.g., folder + * does not exist on disk; folder exists on disk but classpath entry + * does not exist). + * <p> + * In general, if we see that this member is null but the ENABLED + * preference is true, we will try to create the folder and add it to + * the classpath; if we see that this member is non-null but the + * ENABLED preference is false, we will try to delete this folder's + * contents and remove it from the classpath; and if we see that the + * ENABLED preference is true, but the GENSRCDIR folder name preference + * is different than the name of this folder, we will try to delete + * this folder's contents, remove it from the classpath, and create a + * new folder and add it to the classpath. When we do this work depends + * on when we get notified of relevant changes and on what locks we are + * able to obtain. */ private IFolder _generatedSourceFolder = null; /** - * The name of the generated source folder, relative to the project. This - * will be identical to the value of the APT_GENSRCDIR preference, except when - * the preference has changed and this object has not yet been informed. - */ - private String _generatedSourceFolderName = null; - - /** * Should be constructed only by AptProject. Other clients should call * @see AptProject#getGeneratedSourceFolderManager() to get this object. */ @@ -81,244 +81,219 @@ public class GeneratedSourceFolderManager { _aptProject = aptProject; final IJavaProject javaProject = aptProject.getJavaProject(); - // get generated source dir from config - // default value is set in org.eclipse.jdt.apt.core.internal.util.AptCorePreferenceInitializer - _generatedSourceFolderName = AptConfig.getString( javaProject, AptPreferenceConstants.APT_GENSRCDIR); - // properly initialize the GeneratedFileManager if project path is up-to-date and the generated - // source folder is there. - final IFolder folder = getFolder(); - if(folder.exists()){ - boolean uptodate = false; - try{ - uptodate = ClasspathUtil.isProjectClassPathUpToDate(javaProject, null, folder.getFullPath(), null); - }catch(JavaModelException e){ - e.printStackTrace(); + // Set _generatedSourceFolder only if APT is enabled, the folder exists, + // and the folder is on the classpath. + // Otherwise leave it null, which will cause us to try to fix things later on. + if (AptConfig.isEnabled(javaProject)) { + final IFolder folder = getFolder(); + if (folder.exists()) { + if (isOnClasspath(folder)) { + _generatedSourceFolder = folder; + } } - if( uptodate ) - _generatedSourceFolder = folder; - } + } } /** - * Sets the name of the generated soruce folder. The source folder will not be created - * and will not be added to the project's source paths. If there is an existing source - * folder, it will be deleted. - * To properly have the new generated source folder configured, call #ensureGeneratedSourceFolder(). - * - * @param newValue The string name of the new generated source folder. This should be relative - * to the project root. Absolute paths are not supported. The specified string should be - * a valid folder name for the file system, and should not be an existing source folder for the - * project. - * - * @see #getFolder() - * @see #getFolderName() + * Add the folder to the classpath, unless it's already there. + * @param srcFolder the folder to add to the classpath. Must not be null. + * @return true if, at the end of the routine, the folder is on the classpath. */ - private void configure( String newValue, String oldValue ) - { - - // bail if they specify null, empty-string or don't change the name of the source folder - if ( newValue == null || - newValue.length() == 0 || - newValue.equals(oldValue) ) - return; - - _aptProject.projectClean( true ); - - IFolder srcFolder = null; - synchronized ( this ) - { - _generatedSourceFolderName = newValue; - srcFolder = _generatedSourceFolder; + private boolean addToClasspath(IFolder srcFolder) { + boolean onClasspath = false; + try { + ClasspathUtil.updateProjectClasspath( _aptProject.getJavaProject(), srcFolder, null ); + if(AptPlugin.DEBUG) + AptPlugin.trace("Ensured classpath has an entry for " + srcFolder); //$NON-NLS-1$ + onClasspath = true; } - - // if the preference change occur before we actually - // initialized the _generatedSourceFolder. - // This may happen when the pre-processor resource change event occurs after - // the preference change event. - if( oldValue != null && srcFolder == null ){ - srcFolder = _aptProject.getJavaProject().getProject().getFolder( oldValue ); + catch (CoreException e) { + e.printStackTrace(); + AptPlugin.log(e, "Failed to add classpath entry for generated source folder " + srcFolder.getName()); //$NON-NLS-1$ } - - resetGeneratedSrcFolder(srcFolder, true); + return onClasspath; } /** - * Creates the generated source folder if it doesn't exist. - * No changes to the classpath will be made. + * Call this to create the folder and add it to the classpath, when APT is enabled + * (in which case the folder did not previously exist) or when the folder name is + * changed (in which case the old stuff must also be removed). + * <p> + * This method will take a resource lock if the generated source folder needs + * to be created on disk, and it will take a java model lock if the project's + * source paths need to be updated. Care should be taken when calling this + * method to ensure that locking behavior is correct. + * <p> + * This should only be called on an event thread, with no locks on the project + * or classpath. */ - public void createGeneratedSourceFolder(){ - IFolder srcFolder = getFolder(); - // This most likely means the preference change event hasn't occured yet - // and we don't know about the name of the generated source directory. - if( srcFolder == null ) + private void configure() { + + assert(_generatedSourceFolder == null): "Should have already removed old folder by now"; //$NON-NLS-1$ + IFolder srcFolder = getFolderPreference(); + if (srcFolder == null) { + IStatus status = AptPlugin.createStatus(null, "Could not create generated source folder (" + //$NON-NLS-1$ + AptConfig.getGenSrcDir(_aptProject.getJavaProject()) + ")"); //$NON-NLS-1$ + AptPlugin.log(status); return; - try{ - srcFolder.refreshLocal( IResource.DEPTH_INFINITE, null ); - if (!srcFolder.exists()) { - if( AptPlugin.DEBUG ) - AptPlugin.trace("creating " + srcFolder.getProjectRelativePath()); //$NON-NLS-1$ - - FileSystemUtil.makeDerivedParentFolders(srcFolder); - } - } - catch(CoreException ce){ - AptPlugin.log(ce, "Failure during refreshLocal on " + srcFolder.getProjectRelativePath()); //$NON-NLS-1$ } - synchronized (this) { - _generatedSourceFolder = srcFolder; + + // Ensure that the new folder exists on disk. + if (createOnDisk(srcFolder)) { + // Add it to the classpath. + if (addToClasspath(srcFolder)) { + // Only if we get this far do we actually set _generatedSourceFolder. + synchronized ( this ) { + _generatedSourceFolder = srcFolder; + } + } } } + /** - * Creates the generated source folder if it doesn't exist, and adds it as a source path - * to the project. To access the generated source folder, but not have it be created - * or added as a source path, use getGeneratedSourceFolder(). Note that this method - * will take a resource lock if the generated source folder needs to be created on disk, - * and it will take a java model lock if the project's source paths need to be updated. - * Care should be taken when calling this method to ensure that locking behavior is correct. - * - * @return <code>true</code> iff the any resource or classpath has been modified. - * return <code>false</code> otherwise. - * - * @see #getFolder() - * @see #isGeneratedSourceFolderConfigured() + * Creates the generated source folder if necessary. This should be called just + * before doing a build. + * No changes to the classpath will be made. */ - private boolean ensureGeneratedSourceFolder(){ + public void ensureFolderExists(){ + // If APT is disabled, do nothing. + if (!AptConfig.isEnabled(_aptProject.getJavaProject())) { + return; + } - boolean reset = false; - IFolder curSrcFolder = null; - - // Determine current state of affairs, with respect to - // folder, folder name, and classpath. - synchronized( this ) - { - if( _generatedSourceFolder != null ){ - final IPath srcFolderPath = _generatedSourceFolder.getProjectRelativePath(); - - if( !_generatedSourceFolderName.equals( srcFolderPath.toString()) ){ - // Folder name has been changed! Save the current folder so we can clear it out later. - reset = true; - curSrcFolder = _generatedSourceFolder; - _generatedSourceFolder = null; - } - else { - // Folder name and folder are in sync. Check that folder is on classpath. - - // If the folder doesn't exist on disk, there is no point examining the classpath. - try{ - _generatedSourceFolder.refreshLocal( IResource.DEPTH_INFINITE, null ); - } - catch(CoreException ce){ - AptPlugin.log(ce, "Failure during refreshLocal on " + srcFolderPath); //$NON-NLS-1$ - } - if (!_generatedSourceFolder.exists()) { - return false; - } - - try { - IJavaProject jp = _aptProject.getJavaProject(); - IClasspathEntry[] cp = jp.getRawClasspath(); - IPath path = _generatedSourceFolder.getFullPath(); - if (ClasspathUtil.isProjectClassPathUpToDate(jp, cp, path, null)) { - return false; - } - } - catch (JavaModelException jme) { - AptPlugin.log(jme, "Failure examining the classpath"); //$NON-NLS-1$ - } - } - } + // In principle we could bail out here, if (_generatedSourceFolder != null). + // However, this method is an opportunity to detect and fix problems such + // as the folder getting deleted without generatedSourceFolderDeleted() + // getting called (e.g., without user having done a refresh). + IFolder srcFolder = getFolder(); + if (srcFolder == null) { + IStatus status = AptPlugin.createStatus(null, "Could not create generated source folder (" + //$NON-NLS-1$ + AptConfig.getGenSrcDir(_aptProject.getJavaProject()) + ")"); //$NON-NLS-1$ + AptPlugin.log(status); + return; } - IFolder srcFolder = null; - try{ - if( reset ){ - // Folder name was out of sync with folder. Delete the old folder and classpath entry. - ClasspathUtil.removeFromProjectClasspath(_aptProject.getJavaProject(), curSrcFolder, null ); - if ( curSrcFolder.exists() ){ - if( AptPlugin.DEBUG ) - AptPlugin.trace("deleting gen src dir " + curSrcFolder.getName() ); //$NON-NLS-1$ - curSrcFolder.delete( true, false, null ); + if (createOnDisk(srcFolder)) { + if (isOnClasspath(srcFolder)) { + synchronized (this) { + // Only set _generatedSourceFolder if folder is on disk and on classpath. + _generatedSourceFolder = srcFolder; } } - + } + } + + /** + * Create a folder on disk, unless it already exists. + * <p> + * This method will frequently be called on multiple threads simultaneously + * (e.g., build thread and UI thread). + * @param srcFolder the folder to create. Must not be null. + * @return true if, at the end of the routine, the folder exists on disk. + */ + private boolean createOnDisk(IFolder srcFolder) { + boolean exists = false; + try { // don't take any locks while creating the folder, since we are doing file-system operations - srcFolder = getFolder(); srcFolder.refreshLocal( IResource.DEPTH_INFINITE, null ); if (!srcFolder.exists()) { FileSystemUtil.makeDerivedParentFolders(srcFolder); + if(AptPlugin.DEBUG) + AptPlugin.trace("Created folder " + srcFolder + " on disk"); //$NON-NLS-1$ //$NON-NLS-2$ } - - // - // make sure __generated_src dir is on the cp if not already - // - ClasspathUtil.updateProjectClasspath( _aptProject.getJavaProject(), srcFolder, null ); - - if(AptPlugin.DEBUG) - AptPlugin.trace("Added directory " + srcFolder.getName() + " and updated classpath" ); //$NON-NLS-1$ //$NON-NLS-2$ + exists = true; } - catch(CoreException e){ + catch (CoreException e) { e.printStackTrace(); - AptPlugin.log(e, "Failed to create generated source directory"); //$NON-NLS-1$ - return false; + AptPlugin.log(e, "Failed to ensure existence of generated source folder " + srcFolder.getName()); //$NON-NLS-1$ + } + return exists; + } + + /** + * Call this method when the APT_ENABLED preference has changed. + * + * Configure the generated source folder according to whether APT is enabled + * or disabled. If enabled, the folder will be created and a classpath entry + * will be added. If disabled, the folder and classpath entry will be removed. + * <p> + * This should only be called on an event thread, with no locks on the project + * or classpath. + * @param enable + */ + public void enabledPreferenceChanged() + { + final boolean enable = AptConfig.isEnabled(_aptProject.getJavaProject()); + // Short-circuit if nothing changed. + if (enable == (_generatedSourceFolder != null)) { + if( AptPlugin.DEBUG ) { + AptPlugin.trace("enabledChanged() doing nothing; state is already " + enable); //$NON-NLS-1$ + } + // no change in state + return; } - synchronized ( this ) - { - _generatedSourceFolder = srcFolder; - return true; + if ( AptPlugin.DEBUG ) { + AptPlugin.trace("enabledChanged() changing state to " + enable + //$NON-NLS-1$ + " for " + _aptProject.getJavaProject().getElementName()); //$NON-NLS-1$ + } + if( enable ) { + configure(); + } + else { + removeFolder(); } } - + + /** + * Respond to a change in the name of the generated source folder. + * If APT is enabled, remove the old folder and classpath entry and + * create new ones. + * <p> + * This should only be called on an event thread, with no locks on the project + * or classpath. + */ + public void folderNamePreferenceChanged() + { + // if APT is disabled, we don't need to do anything + final boolean aptEnabled = AptConfig.isEnabled(_aptProject.getJavaProject()); + if (!aptEnabled) { + return; + } + + // if name didn't change, we don't need to do anything + if (_generatedSourceFolder != null && _generatedSourceFolder.equals(getFolderPreference())) { + if( AptPlugin.DEBUG ) { + AptPlugin.trace("folderNameChanged() doing nothing; name is already " + //$NON-NLS-1$ + _generatedSourceFolder.getProjectRelativePath()); + } + return; + } + + removeFolder(); + configure(); + } /** * Invoked when the generated source folder has been deleted. This will - * flush any in-memory state tracking generated files and clean up the project classpath. + * flush any in-memory state tracking generated files, and cause the + * generated source folder to be recreated the next time we build. * * Note: this should only be called within a resource change event to ensure that the classpath * is correct during any build. Resource change event never occurs during a build. */ - public void generatedSourceFolderDeleted() + public void folderDeleted() { _aptProject.projectClean( false ); IFolder srcFolder; synchronized(this){ - srcFolder = getFolder(); + srcFolder = _generatedSourceFolder; _generatedSourceFolder = null; } if(AptPlugin.DEBUG) - AptPlugin.trace("nulled out gen src dir " + srcFolder.getName() ); //$NON-NLS-1$ - } - - /** - * @return get the generated source folder. May return null if - * creation has failed, the folder has been deleted or has not been created. - */ - public IFolder getFolder(){ - - final String folderName; - synchronized (this) { - if( _generatedSourceFolder != null ) - return _generatedSourceFolder; - folderName = getFolderName(); - } - if(folderName == null) - return null; - - return _aptProject.getJavaProject().getProject().getFolder( folderName ); - } - - /** - * returns the name of the folder for generated source files. The name is relative - * to the project root. - * - * @see #getFolder() - * @see #isGeneratedSourceFolderConfigured() - */ - public synchronized String getFolderName() - { - return _generatedSourceFolderName; + AptPlugin.trace("set _generatedSourceFolder to null; was " + srcFolder ); //$NON-NLS-1$ } /** @@ -357,78 +332,42 @@ public class GeneratedSourceFolderManager { return outputRootPath; } - + /** - * Configure the generated source folder according to whether APT is enabled - * or disabled. If enabled, the folder will be created and a classpath entry - * will be added. If disabled, the folder and classpath entry will be removed. - * <p> - * This should only be called on an event thread, with no locks on the project - * or classpath. - * @param enable + * Get the current generated source folder; or if it is null, return + * an IFolder corresponding to the current generated source folder name. + * This is a handle-only operation and does not have anything to do with + * whether the folder exists on disk. + * @throws IllegalArgumentException if the name is invalid (e.g., ".."). */ - public void setEnabled(boolean enable) - { - if( AptPlugin.DEBUG ){ - if( enable ) - AptPlugin.trace("enabling APT for " + _aptProject.getJavaProject().getElementName()); //$NON-NLS-1$ - else - AptPlugin.trace("disabling APT for " + _aptProject.getJavaProject().getElementName()); //$NON-NLS-1$ - } - if( enable ) { - final String folderName = _generatedSourceFolderName; - if( AptPlugin.DEBUG ){ - AptPlugin.trace("configure generated source folder to be " + folderName ); //$NON-NLS-1$ - } - configure(folderName, null); - } else{ - final IFolder srcFolder = getFolder(); - _aptProject.projectClean(true); - resetGeneratedSrcFolder(srcFolder, false); + public IFolder getFolder(){ + + synchronized (this) { + if( _generatedSourceFolder != null ) + return _generatedSourceFolder; } + + return getFolderPreference(); } - + /** - * Configure the name of the generated source folder. If APT is enabled, - * remove the old folder and classpath entry and create new ones. If - * disabled, simply record the new name. - * <p> - * This should only be called on an event thread, with no locks on the project - * or classpath. - * TODO: why does this need to know the old name? Didn't we get it in the constructor? - * @param oldName can be null if the old value is not known. - * @param newName + * Get an IFolder that corresponds to the folder name preference. + * This has nothing to do with whether APT is enabled or disabled, + * nothing to do with whether the folder exists on disk; it's just + * a handle corresponding to a name. + * @return null if the IFolder could not be created, which probably + * means that the name is something illegal like "..". */ - public void changeFolderName(String oldName, String newName) - { - if (newName == null) { - // Null is used to indicate this preference has - // been removed, as the project has been deleted. - // We do nothing - return; + private IFolder getFolderPreference() { + final String folderName = AptConfig.getGenSrcDir(_aptProject.getJavaProject()); + IFolder folder = null; + try { + folder = _aptProject.getJavaProject().getProject().getFolder( folderName ); } - if (newName.equals(oldName)) { - // No-op -- same config - return; + catch (IllegalArgumentException e) { + // In the event that the folderName is invalid, just return null. } - - final boolean aptEnabled = AptConfig.isEnabled(_aptProject.getJavaProject()); - if( AptPlugin.DEBUG ) - AptPlugin.trace("configure generated source directory new value = " + //$NON-NLS-1$ - newName + - " old value = " + oldName + //$NON-NLS-1$ - " APT is enabled = " + aptEnabled); //$NON-NLS-1$ - if( aptEnabled ) - // If APT is enabled, - // clean up the old cp entry, delete the old folder, - // create the new one and update the classpath. - configure( newName, oldName ); - else - // If APT is not enabled, the folder should not exist - // and there should be no entry on the classpath. - synchronized (this) { - _generatedSourceFolderName = newName; - } + return folder; } /** @@ -444,79 +383,64 @@ public class GeneratedSourceFolderManager { { return folder != null && folder.equals( getFolder() ); } - + + private boolean isOnClasspath(IFolder srcFolder) { + boolean found = false; + try { + if (ClasspathUtil.doesClasspathContainEntry( + _aptProject.getJavaProject(), null, srcFolder.getFullPath(), null)) { + found = true; + } + } catch (JavaModelException e) { + e.printStackTrace(); + } + return found; + } + /** - * Cleanup the classpath and schedule a job to delete the generated source folder. - * @param recreate if <code>true</code> configure the generated source directory. + * Remove a folder from disk and from the classpath. + * @param srcFolder */ - private void resetGeneratedSrcFolder(final IFolder srcFolder, boolean recreate){ - // clean up the classpath first so that when we actually delete the - // generated source folder and won't cause a classpath error. - if( srcFolder != null ){ - try{ - ClasspathUtil.removeFromProjectClasspath( _aptProject.getJavaProject(), srcFolder, null ); - }catch(JavaModelException e){ - AptPlugin.log( e, "Error occurred deleting old generated src folder " + srcFolder.getName() ); //$NON-NLS-1$ - } + private void removeFolder() { + IFolder srcFolder = null; + synchronized ( this ) + { + srcFolder = _generatedSourceFolder; + _generatedSourceFolder = null; + } + if (srcFolder == null) { + return; } - if( recreate ) - ensureGeneratedSourceFolder(); + // Clear out the generated file maps + _aptProject.projectClean(false); - // delete the generated source folder as well as - // all of its derived ancestors that are containers only to the - // generated source folder - if( srcFolder != null ){ - IFolder folderToDelete = srcFolder; - for( IContainer c = srcFolder.getParent(); - c != null && (c instanceof IFolder); - c = c.getParent() ){ - - try{ - // members can't be empty, there has to be at least 1. - // will only delete the parent if it contains only the - // folder that we want to delete. - if( c.isDerived() && c.members().length == 1 ){ - folderToDelete = (IFolder)c; - } - else - break; - }catch(CoreException e){ - AptPlugin.log(e, "failure while accessing member of " + c.getName() ); //$NON-NLS-1$ - break; - } - } - removeFolder(folderToDelete); + // clean up the classpath first so that when we actually delete the + // generated source folder we won't cause a classpath error. + try { + ClasspathUtil.removeFromProjectClasspath( _aptProject.getJavaProject(), srcFolder, null ); + } catch (JavaModelException e) { + AptPlugin.log( e, "Failed to remove classpath entry for old generated src folder " + srcFolder.getName() ); //$NON-NLS-1$ } + + FileSystemUtil.deleteFolder(srcFolder); } /** - * Remove the specified folder from disk. - * @param srcFolder + * Check whether the proposed name is permitted. + * @param dirString can be anything, including null. + * @return true if attempting to set the generated source folder to + * <code>dirString</code> is likely to succeed. */ - private void removeFolder(final IFolder srcFolder) { - if( srcFolder != null ){ - final IWorkspaceRunnable runnable = new IWorkspaceRunnable(){ - public void run(IProgressMonitor monitor) - { - if( srcFolder != null ){ - try{ - srcFolder.delete(true, false, null); - }catch(CoreException e){ - AptPlugin.log(e, "failed to delete old generated source folder " + srcFolder.getName() ); //$NON-NLS-1$ - }catch(OperationCanceledException cancel){ - AptPlugin.log(cancel, "deletion of generated source folder got cancelled"); //$NON-NLS-1$ - } - } - }; - }; - IWorkspace ws = _aptProject.getJavaProject().getProject().getWorkspace(); - try{ - ws.run(runnable, ws.getRoot(), IWorkspace.AVOID_UPDATE, null); - }catch(CoreException e){ - AptPlugin.log(e, "Runnable for deleting old generated source folder " + srcFolder.getName() + " failed."); //$NON-NLS-1$ //$NON-NLS-2$ - } + public static boolean validate(final IJavaProject jproj, final String folderName) { + IFolder folder = null; + try { + folder = jproj.getProject().getFolder( folderName ); + } + catch (IllegalArgumentException e) { + return false; } + return folder != null; } - + } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/type/ArrayTypeImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/type/ArrayTypeImpl.java index 2ad0bc230d..c607657564 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/type/ArrayTypeImpl.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/type/ArrayTypeImpl.java @@ -50,7 +50,7 @@ public class ArrayTypeImpl implements ArrayType, EclipseMirrorImpl else{ final ITypeBinding leaf = elementType.getElementType(); final String componentKey = BindingKey.createArrayTypeBindingKey(leaf.getKey(), dimension - 1); - componentType = _env.getTypeBinding(componentKey); + componentType = _env.getTypeBindingFromKey(componentKey); if( componentType == null ) throw new IllegalStateException("unknown component type for " + _arrayBinding); //$NON-NLS-1$ } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/Factory.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/Factory.java index a109090d51..e8bd0204bb 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/Factory.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/Factory.java @@ -27,6 +27,7 @@ import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.jdt.apt.core.internal.EclipseMirrorImpl; import org.eclipse.jdt.apt.core.internal.declaration.ASTBasedAnnotationElementDeclarationImpl; +import org.eclipse.jdt.apt.core.internal.declaration.ASTBasedConstructorDeclarationImpl; import org.eclipse.jdt.apt.core.internal.declaration.ASTBasedFieldDeclarationImpl; import org.eclipse.jdt.apt.core.internal.declaration.ASTBasedMethodDeclarationImpl; import org.eclipse.jdt.apt.core.internal.declaration.AnnotationDeclarationImpl; @@ -132,7 +133,12 @@ public class Factory case ASTNode.VARIABLE_DECLARATION_FRAGMENT: return new ASTBasedFieldDeclarationImpl( (VariableDeclarationFragment)node, file, env ); case ASTNode.METHOD_DECLARATION : - return new ASTBasedMethodDeclarationImpl( (org.eclipse.jdt.core.dom.MethodDeclaration)node, file, env ); + final org.eclipse.jdt.core.dom.MethodDeclaration methodDecl = + (org.eclipse.jdt.core.dom.MethodDeclaration)node; + if( methodDecl.isConstructor() ) + return new ASTBasedConstructorDeclarationImpl(methodDecl, file, env); + else + return new ASTBasedMethodDeclarationImpl(methodDecl, file, env ); case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION: return new ASTBasedMethodDeclarationImpl((AnnotationTypeMemberDeclaration)node, file, env); default : diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java index a378c94936..04d164eb08 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java @@ -24,8 +24,13 @@ import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.apt.core.AptPlugin; /** * Simple utility class to encapsulate an mkdirs() that avoids a timing issue @@ -35,6 +40,36 @@ public final class FileSystemUtil { private FileSystemUtil() {} + /** + * Remove the specified folder from disk, using a WorkspaceRunnable so that + * the job blocks until it can obtain the necessary locks. + * @param folder + */ + public static void deleteFolder(final IFolder folder) { + if( folder != null ){ + final IWorkspaceRunnable runnable = new IWorkspaceRunnable(){ + public void run(IProgressMonitor monitor) + { + if( folder != null ){ + try{ + folder.delete(true, false, null); + }catch(CoreException e){ + AptPlugin.log(e, "failed to delete old generated source folder " + folder.getName() ); //$NON-NLS-1$ + }catch(OperationCanceledException cancel){ + AptPlugin.log(cancel, "deletion of generated source folder got cancelled"); //$NON-NLS-1$ + } + } + }; + }; + IWorkspace ws = ResourcesPlugin.getWorkspace(); + try{ + ws.run(runnable, ws.getRoot(), IWorkspace.AVOID_UPDATE, null); + }catch(CoreException e){ + AptPlugin.log(e, "Runnable for deleting old generated source folder " + folder.getName() + " failed."); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + public static void mkdirs( File parent ) { if ( parent == null ) diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/TypesUtil.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/TypesUtil.java index fb4f853165..efb0929368 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/TypesUtil.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/TypesUtil.java @@ -86,7 +86,7 @@ public class TypesUtil implements Types throw new IllegalArgumentException("illegal component type: " + componentType); //$NON-NLS-1$ final String bindingKey = BindingKey.createArrayTypeBindingKey(leaf.getKey(), dimension); - final ITypeBinding arrayType = _env.getTypeBinding(bindingKey); + final ITypeBinding arrayType = _env.getTypeBindingFromKey(bindingKey); if(arrayType == null) return null; return (ArrayType)Factory.createTypeMirror(arrayType, _env); @@ -168,7 +168,7 @@ public class TypesUtil implements Types "but found " + numArgs ); //$NON-NLS-1$ final String typeKey = BindingKey.createParameterizedTypeBindingKey(memberBinding.getKey(), argKeys); - final ITypeBinding resultBinding = _env.getTypeBinding(typeKey); + final ITypeBinding resultBinding = _env.getTypeBindingFromKey(typeKey); return Factory.createReferenceType(resultBinding, _env); } else{ @@ -275,7 +275,7 @@ public class TypesUtil implements Types throw new IllegalArgumentException("Wildcard can only have a upper bound, a lower bound or be unbounded."); //$NON-NLS-1$ final String wildcardkey = BindingKey.createWilcardTypeBindingKey(boundKey, boundKind); - final ITypeBinding wildcard = _env.getTypeBinding(wildcardkey); + final ITypeBinding wildcard = _env.getTypeBindingFromKey(wildcardkey); return (WildcardType)Factory.createTypeMirror(wildcard, _env); } diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/messages.properties b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/messages.properties deleted file mode 100644 index 1619830255..0000000000 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/messages.properties +++ /dev/null @@ -1 +0,0 @@ -AptPlugin_couldNotFindToolsDotJar=Could not find tools.jar in plugin directory: org.eclipse.jdt.apt.core will not load diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java index 50183853c3..a4b0530538 100644 --- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java +++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java @@ -17,6 +17,8 @@ import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -30,6 +32,7 @@ import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jdt.apt.core.AptPlugin; import org.eclipse.jdt.apt.core.internal.AnnotationProcessorFactoryLoader; import org.eclipse.jdt.apt.core.internal.AptProject; +import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager; import org.eclipse.jdt.apt.core.internal.util.FactoryPath; import org.eclipse.jdt.apt.core.internal.util.FactoryPathUtil; import org.eclipse.jdt.core.IClasspathEntry; @@ -133,7 +136,7 @@ public class AptConfig { return options; } - IPath workspaceRootPath = jproj.getProject().getWorkspace().getRoot().getLocation(); + IWorkspaceRoot root = jproj.getProject().getWorkspace().getRoot(); // Add sourcepath and classpath variables try { @@ -151,35 +154,53 @@ public class AptConfig { else { classpathSB.append(File.pathSeparatorChar); } - classpathSB.append(entry.getPath().makeAbsolute().toOSString()); + IPath cpPath = entry.getPath(); + + IResource res = root.findMember(cpPath); + + // If res is null, the path is absolute (it's an external jar) + if (res == null) { + classpathSB.append(cpPath.toOSString()); + } + else { + // It's relative + classpathSB.append(res.getLocation().toOSString()); + } } else if (kind == IClasspathEntry.CPE_SOURCE) { if (firstSP) { firstSP = false; } else { - sourcepathSB.append(File.separatorChar); + sourcepathSB.append(File.pathSeparatorChar); } - // Sourcepath is a bit odd -- it's workspace-relative - IPath sourcepath = entry.getPath(); - sourcepathSB.append(workspaceRootPath.append(sourcepath).toOSString()); + + sourcepathSB.append(root.findMember(entry.getPath()).getLocation().toOSString()); } } // if you add options here, also add them in isAutomaticProcessorOption(), // and document them in docs/reference/automatic_processor_options.html. // Classpath and sourcepath - options.put("-classpath",classpathSB.toString()); //$NON-NLS-1$ + options.put("-classpath",classpathSB.toString()); //$NON-NLS-1$ options.put("-sourcepath", sourcepathSB.toString()); //$NON-NLS-1$ // Get absolute path for generated source dir IFolder genSrcDir = jproj.getProject().getFolder(getGenSrcDir(jproj)); - options.put("-s", genSrcDir.getRawLocation().toOSString()); //$NON-NLS-1$ + String genSrcDirString = genSrcDir.getRawLocation().toOSString(); + options.put("-s", genSrcDirString); //$NON-NLS-1$ // Absolute path for bin dir as well IPath binPath = jproj.getOutputLocation(); - IPath binDir = workspaceRootPath.append(binPath); - options.put("-d", binDir.toOSString()); //$NON-NLS-1$ + IResource binPathResource = root.findMember(binPath); + String binDirString; + if (binPathResource != null) { + binDirString = root.findMember(binPath).getLocation().toOSString(); + } + else { + binDirString = binPath.toOSString(); + } + options.put("-d", binDirString); //$NON-NLS-1$ String target = jproj.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true); options.put("-target", target); //$NON-NLS-1$ @@ -621,19 +642,19 @@ public class AptConfig { } public static String getGenSrcDir(IJavaProject jproject) { - String genSrcDir = getString(jproject, AptPreferenceConstants.APT_GENSRCDIR); - if (genSrcDir == null) { - throw new IllegalStateException("Generated Source Directory was null."); //$NON-NLS-1$ - } - return genSrcDir; + return getString(jproject, AptPreferenceConstants.APT_GENSRCDIR); } public static void setGenSrcDir(IJavaProject jproject, String dirString) { - if (dirString == null) { - throw new IllegalArgumentException("Cannot set the Generated Source Directory to null"); //$NON-NLS-1$ + if (!GeneratedSourceFolderManager.validate(jproject, dirString)) { + throw new IllegalArgumentException("Illegal name for generated source folder: " + dirString); //$NON-NLS-1$ } setString(jproject, AptPreferenceConstants.APT_GENSRCDIR, dirString); } + + public static boolean validateGenSrcDir(IJavaProject jproject, String dirName) { + return GeneratedSourceFolderManager.validate(jproject, dirName); + } private static void setBoolean(IJavaProject jproject, String optionName, boolean value) { IScopeContext context = (null != jproject) ? @@ -642,9 +663,9 @@ public class AptConfig { // get old val as a String, so it can be null if setting doesn't exist yet String oldValue = node.get(optionName, null); node.putBoolean(optionName, value); - if (jproject != null) { + if (jproject != null && oldValue == null || (value != Boolean.parseBoolean(oldValue))) { AptProject aproj = AptPlugin.getAptProject(jproject); - aproj.handlePreferenceChange(optionName, oldValue, Boolean.toString(value)); + aproj.preferenceChanged(optionName); } flushPreference(optionName, node); } @@ -655,9 +676,9 @@ public class AptConfig { IEclipsePreferences node = context.getNode(AptPlugin.PLUGIN_ID); String oldValue = node.get(optionName, null); node.put(optionName, value); - if (jproject != null) { + if (jproject != null && !value.equals(oldValue)) { AptProject aproj = AptPlugin.getAptProject(jproject); - aproj.handlePreferenceChange(optionName, oldValue, value); + aproj.preferenceChanged(optionName); } flushPreference(optionName, node); } diff --git a/org.eclipse.jdt.apt.tests/plugin.xml b/org.eclipse.jdt.apt.tests/plugin.xml index a9e8928145..546ac06473 100644 --- a/org.eclipse.jdt.apt.tests/plugin.xml +++ b/org.eclipse.jdt.apt.tests/plugin.xml @@ -59,6 +59,9 @@ <factory class="org.eclipse.jdt.apt.tests.annotations.apitest.APIAnnotationProcessorFactory"> </factory> + <factory + class="org.eclipse.jdt.apt.tests.annotations.mirrortest.ASTBasedMirrorDeclarationProcessorFactory"> + </factory> </factories> </extension> diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/MirrorDeclarationTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/MirrorDeclarationTests.java index 1575d72698..af43cafbac 100644 --- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/MirrorDeclarationTests.java +++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/MirrorDeclarationTests.java @@ -19,6 +19,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.apt.tests.annotations.ProcessorTestStatus; import org.eclipse.jdt.apt.tests.annotations.mirrortest.MirrorDeclarationCodeExample; +import org.eclipse.jdt.core.tests.builder.Problem; public class MirrorDeclarationTests extends APTTestBase { @@ -111,4 +112,99 @@ public class MirrorDeclarationTests extends APTTestBase { fullBuild( project.getFullPath() ); expectingNoProblems(); } + + /** + * Test AST based mirror implementation and binding based mirror implementation. + * Specifically, + * (i) method declaration with unresolvable return type. + * (ii) constructor declaration with unresolvable parameter + * (iii) field declaration with unresolvable type. + * + * This test focus on declarations from file in context. + * + * @throws Exception + */ + public void testUnresolvableDeclarations0() + throws Exception + { + IProject project = env.getProject( getProjectName() ); + IPath srcRoot = getSourcePath(); + String declAnno = + "package test;\n" + + "public @interface DeclarationAnno{}"; + + env.addClass(srcRoot, "test", "DeclarationAnno", declAnno); + + String codeFoo = + "package test;\n" + + "@DeclarationAnno\n" + + "public class Foo {\n" + + " int field0;\n " + + " UnknownType field1;\n " + + " public Foo(UnknownType type){} \n" + + " public void voidMethod(){} \n " + + " public UnknownType getType(){}\n " + + " public class Inner{} \n" + + "}"; + + final IPath fooPath = env.addClass(srcRoot, "test", "Foo", codeFoo); + fullBuild( project.getFullPath() ); + + expectingOnlySpecificProblemsFor(fooPath, new Problem[]{ + new Problem("", "UnknownType cannot be resolved to a type", fooPath), + new Problem("", "UnknownType cannot be resolved to a type", fooPath), + new Problem("", "UnknownType cannot be resolved to a type", fooPath)} + ); + } + + /** + * Test AST based mirror implementation and binding based mirror implementation. + * Specifically, + * (i) method declaration with unresolvable return type. + * (ii) constructor declaration with unresolvable parameter + * (iii) field declaration with unresolvable type. + * + * This test focus on declarations from file outside of processor + * environment context. + * + * @throws Exception + */ + public void testUnresolvableDeclarations1() + throws Exception + { + IProject project = env.getProject( getProjectName() ); + IPath srcRoot = getSourcePath(); + String declAnno = + "package test;\n" + + "public @interface DeclarationAnno{}"; + + env.addClass(srcRoot, "test", "DeclarationAnno", declAnno); + + String codeBar = + "package test;\n" + + "@DeclarationAnno\n" + + "public class Bar {}"; + env.addClass(srcRoot, "test", "Bar", codeBar); + + String codeFoo = + "package test;\n" + + "@DeclarationAnno\n" + + "public class Foo {\n" + + " int field0;\n " + + " UnknownType field1;\n " + + " public Foo(UnknownType type){} \n" + + " public void voidMethod(){} \n " + + " public UnknownType getType(){}\n " + + " public class Inner{} \n" + + "}"; + + final IPath fooPath = env.addClass(srcRoot, "test", "Foo", codeFoo); + + fullBuild( project.getFullPath() ); + expectingOnlySpecificProblemsFor(fooPath, new Problem[]{ + new Problem("", "UnknownType cannot be resolved to a type", fooPath), + new Problem("", "UnknownType cannot be resolved to a type", fooPath), + new Problem("", "UnknownType cannot be resolved to a type", fooPath)} + ); + } } diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/BaseProcessor.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/BaseProcessor.java index 6535e74add..fd1440af08 100644 --- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/BaseProcessor.java +++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/BaseProcessor.java @@ -13,6 +13,7 @@ package org.eclipse.jdt.apt.tests.annotations; import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; +import com.sun.mirror.apt.Messager; public abstract class BaseProcessor implements AnnotationProcessor { @@ -21,5 +22,33 @@ public abstract class BaseProcessor implements AnnotationProcessor { public BaseProcessor(final AnnotationProcessorEnvironment env) { _env = env; } - + + protected void assertEqual(final int expected, final int actual, final String message){ + if(expected != actual){ + final Messager msgr = _env.getMessager(); + msgr.printError(message + " expected: " + expected + " actual: " + actual ); + } + } + + protected void assertEqual(final String expected, final String actual, final String message){ + if( expected == null ){ + final Messager msgr = _env.getMessager(); + msgr.printError(message + " actual: " + actual ); + } + else if( actual == null ){ + final Messager msgr = _env.getMessager(); + msgr.printError(message + "expected " + expected ); + } + else if( !expected.equals(actual) ){ + final Messager msgr = _env.getMessager(); + msgr.printError(message + " expected: " + expected + " actual: " + actual ); + } + } + + protected void assertNonNull(final Object obj, final String message){ + if( obj == null ){ + final Messager msgr = _env.getMessager(); + msgr.printError(message); + } + } } diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/ASTBasedMirrorDeclarationProcessorFactory.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/ASTBasedMirrorDeclarationProcessorFactory.java new file mode 100644 index 0000000000..db8e4c1532 --- /dev/null +++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/ASTBasedMirrorDeclarationProcessorFactory.java @@ -0,0 +1,122 @@ +package org.eclipse.jdt.apt.tests.annotations.mirrortest; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.jdt.apt.tests.annotations.BaseFactory; +import org.eclipse.jdt.apt.tests.annotations.BaseProcessor; + +import com.sun.mirror.apt.AnnotationProcessor; +import com.sun.mirror.apt.AnnotationProcessorEnvironment; +import com.sun.mirror.declaration.AnnotationTypeDeclaration; +import com.sun.mirror.declaration.ClassDeclaration; +import com.sun.mirror.declaration.ConstructorDeclaration; +import com.sun.mirror.declaration.FieldDeclaration; +import com.sun.mirror.declaration.MethodDeclaration; +import com.sun.mirror.declaration.TypeDeclaration; + +public class ASTBasedMirrorDeclarationProcessorFactory + extends BaseFactory +{ + public ASTBasedMirrorDeclarationProcessorFactory(){ + super("test.DeclarationAnno"); + } + + public AnnotationProcessor getProcessorFor( + Set<AnnotationTypeDeclaration> arg0, + AnnotationProcessorEnvironment env) { + return new ASTBasedMirrorDeclarationProcessor(env); + } + + public static final class ASTBasedMirrorDeclarationProcessor + extends BaseProcessor{ + + public ASTBasedMirrorDeclarationProcessor(AnnotationProcessorEnvironment env){ + super(env); + } + public void process() { + final Collection<TypeDeclaration> typeDecls = _env.getTypeDeclarations(); + boolean done = false; + for( TypeDeclaration typeDecl : typeDecls ){ + if(typeDecl instanceof ClassDeclaration ){ + examineClass( (ClassDeclaration)typeDecl ); + if( typeDecl.getQualifiedName().equals("test.Foo") ) + done = true; + } + } + // if the current file does not contain "test.Foo", + // look for it by name and run the same tests. + if( !done ){ + final ClassDeclaration fooDecl = (ClassDeclaration)_env.getTypeDeclaration("test.Foo"); + examineClass(fooDecl); + final ClassDeclaration innerTypeDecl = (ClassDeclaration)_env.getTypeDeclaration("test.Foo$Inner"); + examineClass(innerTypeDecl); + } + } + + private void examineClass(ClassDeclaration typeDecl ){ + + assertNonNull(typeDecl, "missing type declaration"); + if( typeDecl != null ){ + final String typename = typeDecl.getSimpleName(); + if(typename.equals("Foo")){ + final Collection<? extends MethodDeclaration> methods = + typeDecl.getMethods(); + assertEqual(2, methods.size(), "number of methods do not match "); + for(MethodDeclaration method : methods ){ + final String name = method.getSimpleName(); + if( name.equals("getType") ){ + final String methodString = method.toString(); + final String expectedString = "UnknownType getType()"; + assertEqual(expectedString, methodString, "signature mismatch"); + } + else if( name.equals("voidMethod")){ + final String methodString = method.toString(); + final String expectedString = "void voidMethod()"; + assertEqual(expectedString, methodString, "signature mismatch"); + } + else{ + assertEqual(null, method.toString(), "unexpected method"); + } + } + + final Collection<ConstructorDeclaration> constructors = + typeDecl.getConstructors(); + assertEqual(1, constructors.size(), "number of constructors do not match"); + for( ConstructorDeclaration constructor : constructors ){ + final String constructorString = constructor.toString(); + final String expectedString = " Foo(type)"; + assertEqual(expectedString, constructorString, "signature mismatch"); + } + final Collection<FieldDeclaration> fields = + typeDecl.getFields(); + assertEqual(2, fields.size(), "number of fields do not match"); + for( FieldDeclaration field : fields ){ + final String name = field.getSimpleName(); + if( "field0".equals(name) || "field1".equals(name) ){ + continue; + } + assertEqual(null, name, "unexpected field"); + } + } + else if(typename.equals("Inner")){ + final Collection<? extends MethodDeclaration> methods = + typeDecl.getMethods(); + assertEqual(0, methods.size(), "number of methods do not match "); + + final Collection<ConstructorDeclaration> constructors = + typeDecl.getConstructors(); + assertEqual(1, constructors.size(), "number of constructors do not match"); + for( ConstructorDeclaration constructor : constructors ){ + final String constructorString = constructor.toString(); + final String expectedString = "Inner()"; + assertEqual(expectedString, constructorString, "signature mismatch"); + } + final Collection<FieldDeclaration> fields = + typeDecl.getFields(); + assertEqual(0, fields.size(), "number of fields do not match"); + } + } + } + } +} diff --git a/org.eclipse.jdt.apt.ui/scripts/exportplugin.xml b/org.eclipse.jdt.apt.ui/scripts/exportplugin.xml index 4313f06548..7ed0bfe024 100644 --- a/org.eclipse.jdt.apt.ui/scripts/exportplugin.xml +++ b/org.eclipse.jdt.apt.ui/scripts/exportplugin.xml @@ -22,7 +22,7 @@ <target name="export plug-in [_1.0.0]"> <antcall target="zz_internal_export"> - <param name="plugin_version" value="3.1.1.apt02"/> + <param name="plugin_version" value="3.1.1.apt03"/> </antcall> </target> diff --git a/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java b/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java index 3e0206c0c5..1a52069517 100644 --- a/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java +++ b/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java @@ -20,7 +20,6 @@ import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.jdt.apt.core.AptPlugin; import org.eclipse.jdt.apt.core.util.AptConfig; @@ -326,13 +325,11 @@ public class AptConfigurationBlock extends BaseConfigurationBlock { elements = getListElements(); } saveProcessorOptions(elements); - fAptProject.handlePreferenceChange( - AptPreferenceConstants.APT_GENSRCDIR, fOriginalGenSrcDir, fGenSrcDirField.getText()); - fAptProject.handlePreferenceChange( - AptPreferenceConstants.APT_ENABLED, - Boolean.toString(fOriginalAptEnabled), - Boolean.toString(fAptEnabledField.isSelected())); super.saveSettings(); + if (!fOriginalGenSrcDir.equals(fGenSrcDirField.getText())) + fAptProject.preferenceChanged(AptPreferenceConstants.APT_GENSRCDIR); + if (fOriginalAptEnabled != fAptEnabledField.isSelected()) + fAptProject.preferenceChanged(AptPreferenceConstants.APT_ENABLED); } /** @@ -383,20 +380,10 @@ public class AptConfigurationBlock extends BaseConfigurationBlock { * @return */ private IStatus validateGenSrcDir() { - // TODO: this check should be delegated to a validation routine in apt.core. String dirName = fGenSrcDirField.getText(); - Path path = null; - if (dirName != null) { - path= new Path(dirName); - } - if (path == null || - path.isAbsolute() || - path.isEmpty() || - !path.isValidPath(dirName) || - !dirName.trim().equals(dirName)) { + if (!AptConfig.validateGenSrcDir(fJProj, dirName)) { return new StatusInfo(IStatus.ERROR, Messages.AptConfigurationBlock_genSrcDirMustBeValidRelativePath); } - // TODO: how can we tell whether dirName points to a "normal" src directory? return new StatusInfo(); } |