diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-15 16:47:16 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-15 16:47:16 -0700 |
commit | f8057104af9cae031b544e971a52adafa7c0d9e1 (patch) | |
tree | 5006cc488ffc7c1a63ab3c08f877a046a6f3f351 /tools/signature-tools | |
download | platform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.tar.gz platform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.tar.bz2 platform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.zip |
auto import from //branches/cupcake_rel/...@138607
Diffstat (limited to 'tools/signature-tools')
196 files changed, 17642 insertions, 0 deletions
diff --git a/tools/signature-tools/Android.mk b/tools/signature-tools/Android.mk new file mode 100644 index 00000000000..cf9e053c645 --- /dev/null +++ b/tools/signature-tools/Android.mk @@ -0,0 +1,66 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +# signature-tools java library +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_JAVA_RESOURCE_DIRS := templates + +LOCAL_MODULE := signature-tools +LOCAL_JAVA_LIBRARIES := dx dex-tools +LOCAL_STATIC_JAVA_LIBRARIES := stringtemplate antlr-2.7.7 +LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR) + +include $(BUILD_HOST_JAVA_LIBRARY) + +# prebuilt stringtemplate.jar +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_PREBUILT_JAVA_LIBRARIES := stringtemplate:lib/stringtemplate.jar + +include $(BUILD_HOST_PREBUILT) + +# prebuilt antlr-2.7.7.jar +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_PREBUILT_JAVA_LIBRARIES := antlr-2.7.7:lib/antlr-2.7.7.jar + +include $(BUILD_HOST_PREBUILT) + +# signature-tool script +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_PREBUILT_EXECUTABLES := sig +include $(BUILD_HOST_PREBUILT) + +# signature-create script +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_PREBUILT_EXECUTABLES := sig-create +include $(BUILD_HOST_PREBUILT) + +# signature-check script +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_PREBUILT_EXECUTABLES := sig-check +include $(BUILD_HOST_PREBUILT) diff --git a/tools/signature-tools/README.txt b/tools/signature-tools/README.txt new file mode 100644 index 00000000000..b4198b9f1b5 --- /dev/null +++ b/tools/signature-tools/README.txt @@ -0,0 +1,55 @@ +__signature-tools__ + +This project contains the source code and tests for API signature comparison tools. +It consists roughly of five parts: + +#Signature model : A generic model to represent the structure of an API + +#Converters : A dex -> signature model converter (utilizing the dex-tools parser) + A java source -> signature model converter (utilizing the doclet tools) + +#Delta model : A model to represent differences between two signature models + +#Comparator : Put two signature models into the comparator and you get a delta model + +#Report engine : Translates a delta model to a html output based on templates (utilizing the StringTemplate framework) + + +Since this folder contains a .project file, it can be imported directly into eclipse as a java project. + +Feel free to improve! + +_Structure_ + +dex.reader + | + src : source code + | | + | signature : the driver classes + | | + | compare : the comparator code + | | | + | | model : the delta model + | | + | converter : the converters + | | + | io : common io interfaces + | | | + | | html : html report generator + | | + | model : signature model + | + test : source code of the test suite + | + templates : templates for html output generation + | + launches : eclipse launches for the tools + | + lib : required libraries + | + spec : various input files to try the tool + | + README.txt : you are here + | + TODO.txt : tasks which are still open + diff --git a/tools/signature-tools/TODO.txt b/tools/signature-tools/TODO.txt new file mode 100644 index 00000000000..fd20800e930 --- /dev/null +++ b/tools/signature-tools/TODO.txt @@ -0,0 +1,5 @@ +__Todo__ + +Add more complex tests +Add more spec +Add "plugin system" to enable different loader / differ / report engines. This can be simple as register the class name of the available loaders in a property file diff --git a/tools/signature-tools/lib/antlr-2.7.7.jar b/tools/signature-tools/lib/antlr-2.7.7.jar Binary files differnew file mode 100644 index 00000000000..5e5f14b3558 --- /dev/null +++ b/tools/signature-tools/lib/antlr-2.7.7.jar diff --git a/tools/signature-tools/lib/stringtemplate.jar b/tools/signature-tools/lib/stringtemplate.jar Binary files differnew file mode 100644 index 00000000000..8e415319628 --- /dev/null +++ b/tools/signature-tools/lib/stringtemplate.jar diff --git a/tools/signature-tools/sig b/tools/signature-tools/sig new file mode 100755 index 00000000000..19b57fa2004 --- /dev/null +++ b/tools/signature-tools/sig @@ -0,0 +1,47 @@ +#!/bin/bash +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Set up prog to be the path of this script, including following symlinks, +# and set up progdir to be the fully-qualified pathname of its directory. + +prog="$0" +while [ -h "${prog}" ]; do + newProg=`/bin/ls -ld "${prog}"` + newProg=`expr "${newProg}" : ".* -> \(.*\)$"` + if expr "x${newProg}" : 'x/' >/dev/null; then + prog="${newProg}" + else + progdir=`dirname "${prog}"` + prog="${progdir}/${newProg}" + fi +done +oldwd=`pwd` +progdir=`dirname "${prog}"` +cd "${progdir}" +progdir=`pwd` +prog="${progdir}"/`basename "${prog}"` +cd "${oldwd}" + +libdir=`dirname $progdir`/framework + +javaOpts="" +while expr "x$1" : 'x-J' >/dev/null; do + opt=`expr "$1" : '-J\(.*\)'` + javaOpts="${javaOpts} -${opt}" + shift +done + +exec java $javaOpts -classpath $libdir/signature-tools.jar:$libdir/dex-tools.jar:$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar signature.Main "$@"
\ No newline at end of file diff --git a/tools/signature-tools/sig-check b/tools/signature-tools/sig-check new file mode 100755 index 00000000000..0c1cbcee5c1 --- /dev/null +++ b/tools/signature-tools/sig-check @@ -0,0 +1,114 @@ +#!/bin/bash +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Set up prog to be the path of this script, including following symlinks, +# and set up progdir to be the fully-qualified pathname of its directory. + +prog="$0" +while [ -h "${prog}" ]; do + newProg=`/bin/ls -ld "${prog}"` + newProg=`expr "${newProg}" : ".* -> \(.*\)$"` + if expr "x${newProg}" : 'x/' >/dev/null; then + prog="${newProg}" + else + progdir=`dirname "${prog}"` + prog="${progdir}/${newProg}" + fi +done +oldwd=`pwd` +progdir=`dirname "${prog}"` +cd "${progdir}" +progdir=`pwd` +prog="${progdir}"/`basename "${prog}"` +cd "${oldwd}" + +libdir=`dirname $progdir`/framework +classpath=$libdir/signature-tools.jar:$libdir/dex-tools.jar:\ +$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar + +javaOpts="" +while expr "x$1" : 'x-J' >/dev/null; do + opt=`expr "$1" : '-J\(.*\)'` + javaOpts="${javaOpts} -${opt}" + shift +done + +COREDEX=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES/core_intermediates/classes.dex + +if [ ! -f ${COREDEX} ]; then + echo ERROR: $COREDEX not found + exit -1; +fi + +sig --compare \ +--from sig ${ANDROID_BUILD_TOP}/cts/tools/signature-tools/spec/android.spec \ +--name android cupcake reference \ +--to dex ${COREDEX} \ +--name Android 1.0 \(current build\) \ +--out ${ANDROID_BUILD_TOP}/out/delta \ +--packages \ +java.beans \ +java.io \ +java.lang \ +java.lang.annotation \ +java.lang.ref \ +java.lang.reflect \ +java.math \ +java.net \ +java.nio \ +java.nio.channels \ +java.nio.channels.spi \ +java.nio.charset \ +java.nio.charset.spi \ +java.security \ +java.security.acl \ +java.security.cert \ +java.security.interfaces \ +java.security.spec \ +java.sql \ +java.text \ +java.util \ +java.util.concurrent \ +java.util.concurrent.atomic \ +java.util.concurrent.locks \ +java.util.jar \ +java.util.logging \ +java.util.prefs \ +java.util.regex \ +java.util.zip \ +javax.crypto \ +javax.crypto.interfaces \ +javax.crypto.spec \ +javax.imageio \ +javax.imageio.event \ +javax.imageio.metadata \ +javax.imageio.plugins.bmp \ +javax.imageio.plugins.jpeg \ +javax.imageio.spi \ +javax.imageio.stream \ +javax.net \ +javax.net.ssl \ +javax.security.auth \ +javax.security.auth.callback \ +javax.security.auth.login \ +javax.security.auth.x500 \ +javax.security.cert \ +javax.sql \ +javax.xml.parsers \ +org.w3c.dom \ +org.xml.sax \ +org.xml.sax.ext \ +org.xml.sax.helpers diff --git a/tools/signature-tools/sig-create b/tools/signature-tools/sig-create new file mode 100755 index 00000000000..4049e69912b --- /dev/null +++ b/tools/signature-tools/sig-create @@ -0,0 +1,111 @@ +#!/bin/bash +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Set up prog to be the path of this script, including following symlinks, +# and set up progdir to be the fully-qualified pathname of its directory. + +prog="$0" +while [ -h "${prog}" ]; do + newProg=`/bin/ls -ld "${prog}"` + newProg=`expr "${newProg}" : ".* -> \(.*\)$"` + if expr "x${newProg}" : 'x/' >/dev/null; then + prog="${newProg}" + else + progdir=`dirname "${prog}"` + prog="${progdir}/${newProg}" + fi +done +oldwd=`pwd` +progdir=`dirname "${prog}"` +cd "${progdir}" +progdir=`pwd` +prog="${progdir}"/`basename "${prog}"` +cd "${oldwd}" + +libdir=`dirname $progdir`/framework +classpath=$libdir/signature-tools.jar:$libdir/dex-tools.jar:\ +$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar + +javaOpts="" +while expr "x$1" : 'x-J' >/dev/null; do + opt=`expr "$1" : '-J\(.*\)'` + javaOpts="${javaOpts} -${opt}" + shift +done + +COREDEX=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES/core_intermediates/classes.dex + +if [ ! -f ${COREDEX} ]; then + echo ERROR: $COREDEX not found + exit -1; +fi + +sig --create dex ${COREDEX} \ +--out ${ANDROID_BUILD_TOP}/out/dex \ +--name cts_dex_1.0.1 \ +--packages \ +java.beans \ +java.io \ +java.lang \ +java.lang.annotation \ +java.lang.ref \ +java.lang.reflect \ +java.math \ +java.net \ +java.nio \ +java.nio.channels \ +java.nio.channels.spi \ +java.nio.charset \ +java.nio.charset.spi \ +java.security \ +java.security.acl \ +java.security.cert \ +java.security.interfaces \ +java.security.spec \ +java.sql \ +java.text \ +java.util \ +java.util.concurrent \ +java.util.concurrent.atomic \ +java.util.concurrent.locks \ +java.util.jar \ +java.util.logging \ +java.util.prefs \ +java.util.regex \ +java.util.zip \ +javax.crypto \ +javax.crypto.interfaces \ +javax.crypto.spec \ +javax.imageio \ +javax.imageio.event \ +javax.imageio.metadata \ +javax.imageio.plugins.bmp \ +javax.imageio.plugins.jpeg \ +javax.imageio.spi \ +javax.imageio.stream \ +javax.net \ +javax.net.ssl \ +javax.security.auth \ +javax.security.auth.callback \ +javax.security.auth.login \ +javax.security.auth.x500 \ +javax.security.cert \ +javax.sql \ +javax.xml.parsers \ +org.w3c.dom \ +org.xml.sax \ +org.xml.sax.ext \ +org.xml.sax.helpers
\ No newline at end of file diff --git a/tools/signature-tools/spec/android.spec b/tools/signature-tools/spec/android.spec Binary files differnew file mode 100644 index 00000000000..fbbf53aaaba --- /dev/null +++ b/tools/signature-tools/spec/android.spec diff --git a/tools/signature-tools/src/signature/Main.java b/tools/signature-tools/src/signature/Main.java new file mode 100644 index 00000000000..5b1c9ff8b13 --- /dev/null +++ b/tools/signature-tools/src/signature/Main.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature; + +/** + * The main entry point for the signature tool. If invoked with + * <code>--create</code> the call is delegated to + * {@link signature.converter.Main}. If invoked with <code>--compare</code> the + * call is delegated to {@link signature.compare.Main}. + * + * @see signature.converter.Main + * @see signature.compare.Main + */ +public class Main { + + private static final String USAGE_MESSAGE = "usage:\n" + + " sig --create (doclet | dex) sourcefiles --out directory" + + " --name <name> --packages packageName{ packageName}\n" + + " sig --compare --from=(doclet | dex | sig) <sourcefiles>" + + " --name <name> --to=(doclet | dex | sig) <sourcefiles>" + + " --name <name> --out directory" + + " --packages packageName{ packageName}\n sig --help"; + + /** + * This class is uninstantiable. + */ + private Main() { + // This space intentionally left blank. + } + + /** + * Run! + */ + public static void main(String[] args) { + boolean gotCmd = false; + boolean showUsage = false; + + try { + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("--") || !arg.startsWith("--")) { + gotCmd = false; + showUsage = true; + break; + } + + gotCmd = true; + if (arg.equals("--create")) { + signature.converter.Main.main(without(args, i)); + break; + } else if (arg.equals("--compare")) { + signature.compare.Main.main(without(args, i)); + break; + } else if (arg.equals("--version")) { + version(); + break; + } else if (arg.equals("--help")) { + showUsage = true; + break; + } else { + gotCmd = false; + } + } + } catch (UsageException ex) { + showUsage = true; + } catch (RuntimeException ex) { + System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:"); + ex.printStackTrace(); + System.exit(2); + } catch (Throwable ex) { + System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:"); + ex.printStackTrace(); + System.exit(3); + } + + if (!gotCmd) { + System.err.println("error: no command specified"); + showUsage = true; + } + + if (showUsage) { + usage(); + System.exit(1); + } + } + + /** + * Prints the version message. + */ + private static void version() { + System.err.println("android sigtools version " + Version.VERSION); + System.exit(0); + } + + /** + * Prints the usage message. + */ + private static void usage() { + System.err.println(USAGE_MESSAGE); + } + + /** + * Returns a copy of the given argument array, but without the indicated + * element. + * + * @param orig + * non-null; original array + * @param n + * which element to omit + * @return non-null; new array + */ + private static String[] without(String[] orig, int n) { + int len = orig.length - 1; + String[] newa = new String[len]; + System.arraycopy(orig, 0, newa, 0, n); + System.arraycopy(orig, n + 1, newa, n, len - n); + return newa; + } + +} diff --git a/tools/signature-tools/src/signature/UsageException.java b/tools/signature-tools/src/signature/UsageException.java new file mode 100644 index 00000000000..6cdf9cf84bc --- /dev/null +++ b/tools/signature-tools/src/signature/UsageException.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature; + +/** + * Simple exception class used to communicate that the command-line tool should + * print the usage message. + */ +@SuppressWarnings("serial") +public class UsageException extends RuntimeException { + // This space intentionally left blank. +} diff --git a/tools/signature-tools/src/signature/Version.java b/tools/signature-tools/src/signature/Version.java new file mode 100644 index 00000000000..d20e81fcc5a --- /dev/null +++ b/tools/signature-tools/src/signature/Version.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature; + +/** + * {@code Version} defines the VERSION constant of the signature tools. + */ +public class Version { + /** + * The program version of the signature tools. + */ + public static final String VERSION = "0.1"; +} diff --git a/tools/signature-tools/src/signature/compare/ApiComparator.java b/tools/signature-tools/src/signature/compare/ApiComparator.java new file mode 100644 index 00000000000..9232d2da804 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/ApiComparator.java @@ -0,0 +1,1705 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IAnnotationElementDelta; +import signature.compare.model.IAnnotationFieldDelta; +import signature.compare.model.IApiDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IConstructorDelta; +import signature.compare.model.IDelta; +import signature.compare.model.IEnumConstantDelta; +import signature.compare.model.IFieldDelta; +import signature.compare.model.IGenericDeclarationDelta; +import signature.compare.model.IMethodDelta; +import signature.compare.model.IModifierDelta; +import signature.compare.model.IPackageDelta; +import signature.compare.model.IParameterDelta; +import signature.compare.model.IParameterizedTypeDelta; +import signature.compare.model.IPrimitiveTypeDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.compare.model.ITypeVariableDefinitionDelta; +import signature.compare.model.IUpperBoundsDelta; +import signature.compare.model.IValueDelta; +import signature.compare.model.IWildcardTypeDelta; +import signature.compare.model.impl.SigAnnotationDelta; +import signature.compare.model.impl.SigAnnotationElementDelta; +import signature.compare.model.impl.SigAnnotationFieldDelta; +import signature.compare.model.impl.SigApiDelta; +import signature.compare.model.impl.SigArrayTypeDelta; +import signature.compare.model.impl.SigClassDefinitionDelta; +import signature.compare.model.impl.SigClassReferenceDelta; +import signature.compare.model.impl.SigConstructorDelta; +import signature.compare.model.impl.SigEnumConstantDelta; +import signature.compare.model.impl.SigFieldDelta; +import signature.compare.model.impl.SigGenericDeclarationDelta; +import signature.compare.model.impl.SigMethodDelta; +import signature.compare.model.impl.SigModifierDelta; +import signature.compare.model.impl.SigPackageDelta; +import signature.compare.model.impl.SigParameterDelta; +import signature.compare.model.impl.SigParameterizedTypeDelta; +import signature.compare.model.impl.SigPrimitiveTypeDelta; +import signature.compare.model.impl.SigTypeDelta; +import signature.compare.model.impl.SigTypeVariableDefinitionDelta; +import signature.compare.model.impl.SigTypeVariableReferenceDelta; +import signature.compare.model.impl.SigUpperBoundsDelta; +import signature.compare.model.impl.SigValueDelta; +import signature.compare.model.impl.SigWildcardTypeDelta; +import signature.compare.model.subst.ClassProjection; +import signature.compare.model.subst.ViewpointAdapter; +import signature.model.IAnnotation; +import signature.model.IAnnotationElement; +import signature.model.IAnnotationField; +import signature.model.IApi; +import signature.model.IArrayType; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IConstructor; +import signature.model.IEnumConstant; +import signature.model.IExecutableMember; +import signature.model.IField; +import signature.model.IGenericDeclaration; +import signature.model.IMethod; +import signature.model.IPackage; +import signature.model.IParameter; +import signature.model.IParameterizedType; +import signature.model.IPrimitiveType; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; +import signature.model.IWildcardType; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.impl.SigAnnotationElement; +import signature.model.impl.SigArrayType; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * {@code ApiComparator} takes two signature models as input and creates a delta + * model describing the differences between those. + */ +public class ApiComparator implements IApiComparator { + + public IApiDelta compare(IApi from, IApi to) { + assert from.getVisibility() == to.getVisibility(); + + Set<IPackage> fromPackages = from.getPackages(); + Set<IPackage> toPackages = to.getPackages(); + + Set<IPackageDelta> packageDeltas = compareSets(fromPackages, + toPackages, new SigComparator<IPackage, IPackageDelta>() { + public IPackageDelta createChangedDelta(IPackage from, + IPackage to) { + return comparePackage(from, to); + } + + public IPackageDelta createAddRemoveDelta(IPackage from, + IPackage to) { + return new SigPackageDelta(from, to); + } + + public boolean considerEqualElement(IPackage from, + IPackage to) { + return from.getName().equals(to.getName()); + } + }); + + SigApiDelta delta = null; + if (packageDeltas != null) { + delta = new SigApiDelta(from, to); + delta.setPackageDeltas(packageDeltas); + } + return delta; + } + + private IPackageDelta comparePackage(IPackage from, IPackage to) { + assert from.getName().equals(to.getName()); + + Set<IClassDefinition> fromClasses = from.getClasses(); + Set<IClassDefinition> toClasses = to.getClasses(); + + Set<IClassDefinitionDelta> classDeltas = compareSets(fromClasses, + toClasses, + new SigComparator<IClassDefinition, IClassDefinitionDelta>() { + public boolean considerEqualElement(IClassDefinition from, + IClassDefinition to) { + return sameClassDefinition(from, to); + } + + public IClassDefinitionDelta createChangedDelta( + IClassDefinition from, IClassDefinition to) { + return compareClass(from, to); + } + + public IClassDefinitionDelta createAddRemoveDelta( + IClassDefinition from, IClassDefinition to) { + return new SigClassDefinitionDelta(from, to); + } + }); + + SigPackageDelta delta = null; + if (classDeltas != null) { + delta = new SigPackageDelta(from, to); + delta.setClassDeltas(classDeltas); + } + + // Annotations + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (delta != null) { + delta = new SigPackageDelta(from, to); + } + delta.setAnnotationDeltas(annotationDeltas); + } + return delta; + } + + private IClassDefinitionDelta compareClass(IClassDefinition from, + IClassDefinition to) { + assert from.getKind() == to.getKind(); + assert from.getName().equals(to.getName()); + assert from.getPackageName().equals(to.getPackageName()); + + SigClassDefinitionDelta classDelta = null; + + // modifiers + Set<IModifierDelta> modifierDeltas = compareModifiers(from + .getModifiers(), to.getModifiers()); + if (modifierDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setModifierDeltas(modifierDeltas); + } + + // super class + ITypeReferenceDelta<?> superTypeDelta = compareType(from + .getSuperClass(), to.getSuperClass(), false); + if (superTypeDelta != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setSuperClassDelta(superTypeDelta); + } + + // interfaces + Set<ITypeReferenceDelta<?>> interfaceDeltas = compareInterfaces(from, + to); + if (interfaceDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setInterfaceDeltas(interfaceDeltas); + } + + // type variables + Set<ITypeVariableDefinitionDelta> typeVariableDeltas = + compareTypeVariableSequence(from.getTypeParameters(), + to.getTypeParameters()); + if (typeVariableDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setTypeVariableDeltas(typeVariableDeltas); + } + + // constructors + Set<IConstructorDelta> constructorDeltas = compareConstructors(from + .getConstructors(), to.getConstructors()); + if (constructorDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setConstructorDeltas(constructorDeltas); + } + + // methods + Set<IMethodDelta> methodDeltas = compareMethods(from, to); + if (methodDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setMethodDeltas(methodDeltas); + } + + // fields + Set<IFieldDelta> fieldDeltas = compareFields(from.getFields(), to + .getFields()); + if (fieldDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setFieldDeltas(fieldDeltas); + } + + // enum constants + if (from.getKind() == Kind.ENUM) { + Set<IEnumConstantDelta> enumDeltas = compareEnumConstants(from + .getEnumConstants(), to.getEnumConstants()); + if (enumDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setEnumConstantDeltas(enumDeltas); + } + } else if (from.getKind() == Kind.ANNOTATION) { + Set<IAnnotationFieldDelta> annotationFieldDeltas = + compareAnnotationFields(from.getAnnotationFields(), + to.getAnnotationFields()); + if (annotationFieldDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setAnnotationFieldDeltas(annotationFieldDeltas); + } + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (classDelta == null) { + classDelta = new SigClassDefinitionDelta(from, to); + } + classDelta.setAnnotationDeltas(annotationDeltas); + } + return classDelta; + } + + private Set<ITypeReferenceDelta<?>> compareInterfaces( + IClassDefinition from, IClassDefinition to) { + Set<ITypeReference> fromClosure = getInterfaceClosure(from); + Set<ITypeReference> toClosure = getInterfaceClosure(to); + + Set<ITypeReference> fromInterfaces = from.getInterfaces(); + Set<ITypeReference> toInterfaces = to.getInterfaces(); + + Set<ITypeReferenceDelta<?>> deltas = + new HashSet<ITypeReferenceDelta<?>>(); + + // check whether all from interfaces are directly or indirectly + // implemented by the to method + for (ITypeReference type : fromInterfaces) { + if (!containsType(type, toInterfaces)) { + if (!(containsType(type, toClosure) /* + * && !containsType(type, + * toInterfaces) + */)) { + deltas.add(new SigTypeDelta<ITypeReference>(type, null)); + } + } + } + + // check whether all interfaces to are directly or indirectly + // implemented by the from method + for (ITypeReference type : toInterfaces) { + if (!containsType(type, fromInterfaces)) { + if (!(containsType(type, fromClosure) /* + * && !containsType(type, + * fromInterfaces) + */)) { + deltas.add(new SigTypeDelta<ITypeReference>(null, type)); + } + } + } + return deltas.isEmpty() ? null : deltas; + } + + + private boolean containsType(ITypeReference type, + Set<ITypeReference> setOfTypes) { + for (ITypeReference other : setOfTypes) { + if (compareType(type, other, false) == null) { + return true; + } + } + return false; + } + + private Set<ITypeReference> getInterfaceClosure(IClassDefinition clazz) { + Set<ITypeReference> closure = new HashSet<ITypeReference>(); + collectInterfaceClosure(ViewpointAdapter.getReferenceTo(clazz), + closure); + return closure; + } + + private void collectInterfaceClosure(ITypeReference clazz, + Set<ITypeReference> closure) { + + IClassDefinition classDefinition = getClassDefinition(clazz); + Set<ITypeReference> interfaces = classDefinition.getInterfaces(); + if (interfaces == null) { + return; + } + for (ITypeReference interfaze : interfaces) { + closure.add(interfaze); + } + + ITypeReference superclass = classDefinition.getSuperClass(); + if (superclass != null) { + if (superclass instanceof IParameterizedType) { + collectInterfaceClosure(((IParameterizedType) superclass) + .getRawType(), closure); + } else { + collectInterfaceClosure(superclass, closure); + } + } + for (ITypeReference interfaze : interfaces) { + if (interfaze instanceof IParameterizedType) { + collectInterfaceClosure(((IParameterizedType) interfaze) + .getRawType(), closure); + } else { + collectInterfaceClosure(interfaze, closure); + } + } + } + + private Set<IAnnotationDelta> compareAnnotations(Set<IAnnotation> from, + Set<IAnnotation> to) { + return compareSets(from, to, + new SigComparator<IAnnotation, IAnnotationDelta>() { + public IAnnotationDelta createAddRemoveDelta( + IAnnotation from, IAnnotation to) { + return new SigAnnotationDelta(from, to); + } + + public boolean considerEqualElement(IAnnotation from, + IAnnotation to) { + return sameClassDefinition(from.getType() + .getClassDefinition(), to.getType() + .getClassDefinition()); + } + + public IAnnotationDelta createChangedDelta( + IAnnotation from, IAnnotation to) { + return compareAnnotation(from, to); + } + }); + } + + private Set<IAnnotationFieldDelta> compareAnnotationFields( + Set<IAnnotationField> from, Set<IAnnotationField> to) { + return compareSets(from, to, + new SigComparator<IAnnotationField, IAnnotationFieldDelta>() { + public boolean considerEqualElement(IAnnotationField from, + IAnnotationField to) { + return from.getName().equals(to.getName()); + } + + public IAnnotationFieldDelta createAddRemoveDelta( + IAnnotationField from, IAnnotationField to) { + return new SigAnnotationFieldDelta(from, to); + } + + public IAnnotationFieldDelta createChangedDelta( + IAnnotationField from, IAnnotationField to) { + return compareAnnotationField(from, to); + } + }); + } + + private Set<IEnumConstantDelta> compareEnumConstants( + Set<IEnumConstant> from, Set<IEnumConstant> to) { + return compareSets(from, to, + new SigComparator<IEnumConstant, IEnumConstantDelta>() { + public boolean considerEqualElement(IEnumConstant from, + IEnumConstant to) { + return from.getName().equals(to.getName()); + } + + public IEnumConstantDelta createAddRemoveDelta( + IEnumConstant from, IEnumConstant to) { + return new SigEnumConstantDelta(from, to); + } + + public IEnumConstantDelta createChangedDelta( + IEnumConstant from, IEnumConstant to) { + return compareEnumConstant(from, to); + } + }); + } + + private Set<IFieldDelta> compareFields(Set<IField> from, Set<IField> to) { + return compareSets(from, to, new SigComparator<IField, IFieldDelta>() { + public boolean considerEqualElement(IField from, IField to) { + return from.getName().equals(to.getName()); + } + + public IFieldDelta createAddRemoveDelta(IField from, IField to) { + return new SigFieldDelta(from, to); + } + + public IFieldDelta createChangedDelta(IField from, IField to) { + return compareField(from, to); + } + }); + } + + private Set<IMethodDelta> compareMethods(IClassDefinition from, + IClassDefinition to) { + assert from != null; + assert to != null; + + Set<IMethod> toMethods = new HashSet<IMethod>(to.getMethods()); + Set<IMethod> toClosure = getMethodClosure(to); + Set<IMethod> fromMethods = new HashSet<IMethod>(from.getMethods()); + Set<IMethod> fromClosure = getMethodClosure(from); + + Set<IMethodDelta> deltas = new HashSet<IMethodDelta>(); + + for (IMethod method : fromMethods) { + IMethod compatibleMethod = findCompatibleMethod(method, toMethods); + if (compatibleMethod == null) { + compatibleMethod = findCompatibleMethod(method, toClosure); + if (compatibleMethod == null) { + deltas.add(new SigMethodDelta(method, null)); + } + } + + if (compatibleMethod != null) { + IMethodDelta delta = compareMethod(method, compatibleMethod); + if (delta != null) { + deltas.add(delta); + } + } + } + + for (IMethod method : toMethods) { + IMethod compatibleMethod = findCompatibleMethod(method, fromMethods); + if (compatibleMethod == null) { + compatibleMethod = findCompatibleMethod(method, fromClosure); + if (compatibleMethod == null) { + deltas.add(new SigMethodDelta(null, method)); + } + } + } + return deltas.isEmpty() ? null : deltas; + } + + private IMethod findCompatibleMethod(IMethod method, Set<IMethod> set) { + for (IMethod methodFromSet : set) { + if (equalsSignature(method, methodFromSet)) { + return methodFromSet; + } + } + return null; + } + + + private Set<IMethod> getMethodClosure(IClassDefinition clazz) { + Set<IMethod> closure = new HashSet<IMethod>(); + collectMethods(new ClassProjection(clazz, + new HashMap<ITypeVariableDefinition, ITypeReference>()), + closure); + return closure; + } + + private void collectMethods(IClassDefinition clazz, Set<IMethod> closure) { + if (clazz == null) { + return; + } + if (clazz.getMethods() != null) { + closure.addAll(clazz.getMethods()); + } + if (clazz.getSuperClass() != null) { + collectMethods(getClassDefinition(clazz.getSuperClass()), closure); + } + if (clazz.getInterfaces() != null) { + for (ITypeReference interfaze : clazz.getInterfaces()) { + collectMethods(getClassDefinition(interfaze), closure); + } + } + } + + private Set<IConstructorDelta> compareConstructors(Set<IConstructor> from, + Set<IConstructor> to) { + return compareSets(from, to, + new SigComparator<IConstructor, IConstructorDelta>() { + public boolean considerEqualElement(IConstructor from, + IConstructor to) { + return equalsSignature(from, to); + } + + public IConstructorDelta createAddRemoveDelta( + IConstructor from, IConstructor to) { + return new SigConstructorDelta(from, to); + } + + public IConstructorDelta createChangedDelta( + IConstructor from, IConstructor to) { + return compareConstructor(from, to); + } + }); + } + + // compares names and parameter types + private boolean equalsSignature(IExecutableMember from, + IExecutableMember to) { + if (from.getName().equals(to.getName())) { + return compareTypeSequence(getParameterList(from.getParameters()), + getParameterList(to.getParameters()), true) == null; + } + return false; + } + + private List<ITypeReference> getParameterList(List<IParameter> parameters) { + List<ITypeReference> parameterTypes = new LinkedList<ITypeReference>(); + for (IParameter parameter : parameters) { + parameterTypes.add(parameter.getType()); + } + return parameterTypes; + } + + private IAnnotationDelta compareAnnotation(IAnnotation from, + IAnnotation to) { + assert sameClassDefinition(from.getType().getClassDefinition(), to + .getType().getClassDefinition()); + + Set<IAnnotationElement> fromAnnotationElement = + getNormalizedAnnotationElements(from); + Set<IAnnotationElement> toAnnotationElement = + getNormalizedAnnotationElements(to); + + Set<IAnnotationElementDelta> annotationElementDeltas = + compareAnnotationElements( + fromAnnotationElement, toAnnotationElement); + SigAnnotationDelta delta = null; + + if (annotationElementDeltas != null) { + delta = new SigAnnotationDelta(from, to); + delta.setAnnotationElementDeltas(annotationElementDeltas); + } + return delta; + } + + /** + * Returns the annotation elements for the given annotation. The returned + * set contains all declared elements plus all elements with default values. + * + * @param annotation + * the annotation to return the elements for + * @return the default enriched annotation elements + */ + private Set<IAnnotationElement> getNormalizedAnnotationElements( + IAnnotation annotation) { + Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>( + annotation.getElements()); + + Set<String> names = new HashSet<String>(); + for (IAnnotationElement annotationElement : elements) { + names.add(annotationElement.getDeclaringField().getName()); + } + + for (IAnnotationField field : annotation.getType().getClassDefinition() + .getAnnotationFields()) { + if (!names.contains(field.getName())) { + SigAnnotationElement sigAnnotationElement = + new SigAnnotationElement(); + sigAnnotationElement.setDeclaringField(field); + sigAnnotationElement.setValue(field.getDefaultValue()); + elements.add(sigAnnotationElement); + } + } + return elements; + } + + private Set<IAnnotationElementDelta> compareAnnotationElements( + Set<IAnnotationElement> from, Set<IAnnotationElement> to) { + return compareSets(from, to, + new SigComparator<IAnnotationElement, IAnnotationElementDelta>() { + public boolean considerEqualElement( + IAnnotationElement from, IAnnotationElement to) { + return from.getDeclaringField().getName().equals( + to.getDeclaringField().getName()); + } + + public IAnnotationElementDelta createAddRemoveDelta( + IAnnotationElement from, IAnnotationElement to) { + return new SigAnnotationElementDelta(from, to); + } + + public IAnnotationElementDelta createChangedDelta( + IAnnotationElement from, IAnnotationElement to) { + return compareAnnotationElement(from, to); + } + }); + } + + private IAnnotationElementDelta compareAnnotationElement( + IAnnotationElement from, IAnnotationElement to) { + SigAnnotationElementDelta delta = null; + SigValueDelta valueDelta = compareValue(from.getValue(), to.getValue()); + + if (valueDelta != null) { + delta = new SigAnnotationElementDelta(from, to); + delta.setValueDelta(valueDelta); + } + return delta; + } + + /** + * Removes the {@link Modifier#ABSTRACT} modifier. + */ + private Set<Modifier> prepareMethodModifiers(IMethod method) { + Set<Modifier> modifierCopy = new HashSet<Modifier>(method + .getModifiers()); + modifierCopy.remove(Modifier.ABSTRACT); + return modifierCopy; + } + + private IMethodDelta compareMethod(IMethod from, IMethod to) { + assert from != null && to != null; + + SigMethodDelta methodDelta = null; + Set<IModifierDelta> modiferDeltas = compareModifiers( + prepareMethodModifiers(from), prepareMethodModifiers(to)); + if (modiferDeltas != null) { + methodDelta = new SigMethodDelta(from, to); + methodDelta.setModifierDeltas(modiferDeltas); + } + + Set<IParameterDelta> parameterDeltas = compareParameterSequence(from + .getParameters(), to.getParameters()); + if (parameterDeltas != null) { + if (methodDelta == null) { + methodDelta = new SigMethodDelta(from, to); + } + methodDelta.setParameterDeltas(parameterDeltas); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (methodDelta == null) { + methodDelta = new SigMethodDelta(from, to); + } + methodDelta.setAnnotationDeltas(annotationDeltas); + } + + Set<ITypeVariableDefinitionDelta> typeParameterDeltas = + compareTypeVariableSequence(from.getTypeParameters(), + to.getTypeParameters()); + if (typeParameterDeltas != null) { + if (methodDelta == null) { + methodDelta = new SigMethodDelta(from, to); + } + methodDelta.setTypeVariableDeltas(typeParameterDeltas); + } + + Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes( + normalizeExceptions(from.getExceptions()), + normalizeExceptions(to.getExceptions())); + if (exceptionDeltas != null) { + if (methodDelta == null) { + methodDelta = new SigMethodDelta(from, to); + } + methodDelta.setExceptionDeltas(exceptionDeltas); + } + + ITypeReferenceDelta<?> returnTypeDelta = compareType(from + .getReturnType(), to.getReturnType(), false); + if (returnTypeDelta != null) { + if (methodDelta == null) { + methodDelta = new SigMethodDelta(from, to); + } + methodDelta.setReturnTypeDelta(returnTypeDelta); + } + + return methodDelta; + } + + // remove runtime exceptions, + // remove sub types of containing exception + private Set<ITypeReference> normalizeExceptions( + Set<ITypeReference> exceptions) { + Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>( + exceptions); + + Iterator<ITypeReference> iterator = exceptionCopy.iterator(); + while (iterator.hasNext()) { + ITypeReference exception = iterator.next(); + if (isRuntimeExceptionOrErrorSubtype(exception)) { + iterator.remove(); + } + } + exceptionCopy = removeSpecializations(exceptionCopy); + return exceptionCopy; + } + + private Set<ITypeReference> removeSpecializations( + Set<ITypeReference> exceptions) { + Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>( + exceptions); + for (ITypeReference type : exceptions) { + Iterator<ITypeReference> it = exceptionCopy.iterator(); + while (it.hasNext()) { + ITypeReference subType = it.next(); + if (isSuperClass(getClassDefinition(type), + getClassDefinition(subType))) { + it.remove(); + } + } + } + return exceptionCopy; + } + + /** + * Returns true if superC is a super class of subC. + */ + private boolean isSuperClass(IClassDefinition superC, + IClassDefinition subC) { + if (superC == null || subC == null) { + return false; + } + + if (subC.getSuperClass() == null) { + return false; + } else { + if (getClassDefinition(subC.getSuperClass()).equals(superC)) { + return true; + } else { + return isSuperClass(superC, getClassDefinition(subC + .getSuperClass())); + } + } + } + + private boolean isSuperInterface(IClassDefinition superClass, + IClassDefinition subClass) { + if (superClass == null || subClass == null) { + return false; + } + + if (subClass.getInterfaces() == null) { + return false; + } else { + if (getClassDefinitions(subClass.getInterfaces()).contains( + superClass)) { + return true; + } else { + for (ITypeReference subType : subClass.getInterfaces()) { + if (isSuperInterface(superClass, + getClassDefinition(subType))) { + return true; + } + } + return false; + } + } + } + + private Set<IClassDefinition> getClassDefinitions( + Set<ITypeReference> references) { + Set<IClassDefinition> definitions = new HashSet<IClassDefinition>(); + for (ITypeReference ref : references) { + definitions.add(getClassDefinition(ref)); + } + return definitions; + } + + /** + * Returns null if type is not one of: + * <ul> + * <li>IClassReference</li> + * <li>IParameterizedType</li> + * </ul> + */ + private IClassDefinition getClassDefinition(ITypeReference type) { + assert type != null; + + IClassDefinition returnValue = null; + if (type instanceof IClassReference) { + returnValue = ((IClassReference) type).getClassDefinition(); + } else if (type instanceof IParameterizedType) { + returnValue = ((IParameterizedType) type).getRawType() + .getClassDefinition(); + } + return returnValue; + } + + private boolean isRuntimeExceptionOrErrorSubtype(ITypeReference exception) { + + IClassDefinition clazz = getClassDefinition(exception); + if (clazz != null) { + if (isRuntimeExceptionOrError(clazz)) { + return true; + } else if (clazz.getSuperClass() != null) { + return isRuntimeExceptionOrErrorSubtype(clazz.getSuperClass()); + } else { + return false; + } + } + return false; + } + + private boolean isRuntimeExceptionOrError(IClassDefinition exception) { + if (exception == null) { + return false; + } + String packageName = exception.getPackageName(); + String className = exception.getName(); + + if (packageName != null && className != null + && "java.lang".equals(packageName)) { + return "RuntimeException".equals(className) + || "Error".equals(className); + } + return false; + } + + private IConstructorDelta compareConstructor(IConstructor from, + IConstructor to) { + SigConstructorDelta constructorDelta = null; + Set<IModifierDelta> modiferDeltas = compareModifiers(from + .getModifiers(), to.getModifiers()); + if (modiferDeltas != null) { + constructorDelta = new SigConstructorDelta(from, to); + constructorDelta.setModifierDeltas(modiferDeltas); + } + + Set<IParameterDelta> parameterDeltas = compareParameterSequence(from + .getParameters(), to.getParameters()); + if (parameterDeltas != null) { + if (constructorDelta == null) { + constructorDelta = new SigConstructorDelta(from, to); + } + constructorDelta.setParameterDeltas(parameterDeltas); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (constructorDelta == null) { + constructorDelta = new SigConstructorDelta(from, to); + } + constructorDelta.setAnnotationDeltas(annotationDeltas); + } + + Set<ITypeVariableDefinitionDelta> typeParameterDeltas = + compareTypeVariableSequence(from.getTypeParameters(), + to.getTypeParameters()); + if (typeParameterDeltas != null) { + if (constructorDelta == null) { + constructorDelta = new SigConstructorDelta(from, to); + } + constructorDelta.setTypeVariableDeltas(typeParameterDeltas); + } + + Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes( + normalizeExceptions(from.getExceptions()), + normalizeExceptions(to.getExceptions())); + if (exceptionDeltas != null) { + if (constructorDelta == null) { + constructorDelta = new SigConstructorDelta(from, to); + } + constructorDelta.setExceptionDeltas(exceptionDeltas); + } + return constructorDelta; + } + + private Set<IParameterDelta> compareParameterSequence( + List<IParameter> from, List<IParameter> to) { + assert from.size() == to.size(); + Set<IParameterDelta> deltas = new HashSet<IParameterDelta>(); + Iterator<IParameter> fromIterator = from.iterator(); + Iterator<IParameter> toIterator = to.iterator(); + while (fromIterator.hasNext() && toIterator.hasNext()) { + IParameterDelta delta = compareParameter(fromIterator.next(), + toIterator.next()); + if (delta != null) { + deltas.add(delta); + } + } + return deltas.isEmpty() ? null : deltas; + } + + private IParameterDelta compareParameter(IParameter from, IParameter to) { + SigParameterDelta delta = null; + ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to + .getType(), false); + if (typeDelta != null) { + if (delta == null) { + delta = new SigParameterDelta(from, to); + } + delta.setTypeDelta(typeDelta); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (delta == null) { + delta = new SigParameterDelta(from, to); + } + delta.setAnnotationDeltas(annotationDeltas); + } + return delta; + } + + private Set<ITypeVariableDefinitionDelta> compareTypeVariableSequence( + List<ITypeVariableDefinition> from, + List<ITypeVariableDefinition> to) { + Set<ITypeVariableDefinitionDelta> deltas = + new HashSet<ITypeVariableDefinitionDelta>(); + if (from.size() != to.size()) { + for (ITypeVariableDefinition fromVariable : from) { + deltas.add(new SigTypeVariableDefinitionDelta(fromVariable, + null)); + } + for (ITypeVariableDefinition toVariable : to) { + deltas + .add(new SigTypeVariableDefinitionDelta(null, + toVariable)); + } + } + + Iterator<ITypeVariableDefinition> fromIterator = from.iterator(); + Iterator<ITypeVariableDefinition> toIterator = to.iterator(); + while (fromIterator.hasNext() && toIterator.hasNext()) { + ITypeVariableDefinitionDelta delta = compareTypeVariableDefinition( + fromIterator.next(), toIterator.next()); + if (delta != null) { + deltas.add(delta); + } + } + return deltas.isEmpty() ? null : deltas; + } + + private ITypeVariableDefinitionDelta compareTypeVariableDefinition( + ITypeVariableDefinition from, ITypeVariableDefinition to) { + IGenericDeclarationDelta declarationDelta = compareGenericDeclaration( + from, to); + + if (declarationDelta != null) { + SigTypeVariableDefinitionDelta delta = + new SigTypeVariableDefinitionDelta(from, to); + delta.setGenericDeclarationDelta(declarationDelta); + return delta; + } + IUpperBoundsDelta upperBoundDelta = compareUpperBounds(from + .getUpperBounds(), to.getUpperBounds()); + + if (upperBoundDelta != null) { + SigTypeVariableDefinitionDelta delta = + new SigTypeVariableDefinitionDelta(from, to); + delta.setUpperBoundsDelta(upperBoundDelta); + return delta; + } + return null; + } + + private ITypeReferenceDelta<ITypeVariableReference> compareTypeVariableReference( + ITypeVariableReference from, ITypeVariableReference to) { + IGenericDeclarationDelta declarationDelta = compareGenericDeclaration( + from.getTypeVariableDefinition(), to + .getTypeVariableDefinition()); + if (declarationDelta != null) { + SigTypeVariableReferenceDelta delta = + new SigTypeVariableReferenceDelta(from, to); + delta.setGenericDeclarationDelta(declarationDelta); + return delta; + } + return null; + } + + private Set<IModifierDelta> compareModifiers(Set<Modifier> from, + Set<Modifier> to) { + return compareSets(from, to, + new SigComparator<Modifier, IModifierDelta>() { + public boolean considerEqualElement(Modifier from, + Modifier to) { + return from.equals(to); + } + + public IModifierDelta createAddRemoveDelta(Modifier from, + Modifier to) { + return new SigModifierDelta(from, to); + } + + public IModifierDelta createChangedDelta(Modifier from, + Modifier to) { + return null; + } + }); + } + + + private IFieldDelta compareField(IField from, IField to) { + SigFieldDelta fieldDelta = null; + + Set<IModifierDelta> modiferDeltas = compareModifiers(from + .getModifiers(), to.getModifiers()); + if (modiferDeltas != null) { + fieldDelta = new SigFieldDelta(from, to); + fieldDelta.setModifierDeltas(modiferDeltas); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (fieldDelta == null) { + fieldDelta = new SigFieldDelta(from, to); + } + fieldDelta.setAnnotationDeltas(annotationDeltas); + } + + ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to + .getType(), false); + if (typeDelta != null) { + if (fieldDelta == null) { + fieldDelta = new SigFieldDelta(from, to); + } + fieldDelta.setTypeDelta(typeDelta); + } + return fieldDelta; + } + + private IEnumConstantDelta compareEnumConstant(IEnumConstant from, + IEnumConstant to) { + SigEnumConstantDelta enumConstantDelta = null; + + Set<IModifierDelta> modiferDeltas = compareModifiers(from + .getModifiers(), to.getModifiers()); + if (modiferDeltas != null) { + enumConstantDelta = new SigEnumConstantDelta(from, to); + enumConstantDelta.setModifierDeltas(modiferDeltas); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (enumConstantDelta == null) { + enumConstantDelta = new SigEnumConstantDelta(from, to); + } + enumConstantDelta.setAnnotationDeltas(annotationDeltas); + } + + ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to + .getType(), false); + if (typeDelta != null) { + if (enumConstantDelta == null) { + enumConstantDelta = new SigEnumConstantDelta(from, to); + } + enumConstantDelta.setTypeDelta(typeDelta); + } + + // FIXME ordinal not supported in dex + // ValueDelta ordinalDelta = compareValue(from.getOrdinal(), + // to.getOrdinal()); + // if (ordinalDelta != null) { + // if (enumConstantDelta == null) { + // enumConstantDelta = new SigEnumConstantDelta(from, to); + // } + // enumConstantDelta.setOrdinalDelta(ordinalDelta); + // } + + return enumConstantDelta; + } + + private IAnnotationFieldDelta compareAnnotationField(IAnnotationField from, + IAnnotationField to) { + SigAnnotationFieldDelta annotationFieldDelta = null; + + Set<IModifierDelta> modiferDeltas = compareModifiers(from + .getModifiers(), to.getModifiers()); + if (modiferDeltas != null) { + annotationFieldDelta = new SigAnnotationFieldDelta(from, to); + annotationFieldDelta.setModifierDeltas(modiferDeltas); + } + + Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from + .getAnnotations(), to.getAnnotations()); + if (annotationDeltas != null) { + if (annotationFieldDelta == null) { + annotationFieldDelta = new SigAnnotationFieldDelta(from, to); + } + annotationFieldDelta.setAnnotationDeltas(annotationDeltas); + } + + ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to + .getType(), false); + if (typeDelta != null) { + if (annotationFieldDelta == null) { + annotationFieldDelta = new SigAnnotationFieldDelta(from, to); + } + annotationFieldDelta.setTypeDelta(typeDelta); + } + + IValueDelta defaultValueDelta = compareValue(from.getDefaultValue(), to + .getDefaultValue()); + if (defaultValueDelta != null) { + if (annotationFieldDelta == null) { + annotationFieldDelta = new SigAnnotationFieldDelta(from, to); + } + annotationFieldDelta.setDefaultValueDelta(defaultValueDelta); + } + + return annotationFieldDelta; + } + + private SigValueDelta compareValue(Object from, Object to) { + // same value + if (from == null && to == null) { + return null; + } + + // one of both is null and other is not + if (from == null || to == null) { + return new SigValueDelta(from, to); + } + + SigValueDelta delta = null; + // different types + if (from.getClass() == to.getClass()) { + if (from.getClass().isArray()) { + Object[] fromArray = (Object[]) from; + Object[] toArray = (Object[]) from; + if (!Arrays.equals(fromArray, toArray)) { + delta = new SigValueDelta(from, to); + } + } else if (from instanceof IEnumConstant) { + IEnumConstantDelta enumConstantDelta = compareEnumConstant( + (IEnumConstant) from, (IEnumConstant) to); + if (enumConstantDelta != null) { + delta = new SigValueDelta(from, to); + } + } else if (from instanceof IAnnotation) { + IAnnotationDelta annotationDelta = compareAnnotation( + (IAnnotation) from, (IAnnotation) to); + if (annotationDelta != null) { + delta = new SigValueDelta(from, to); + } + } else if (from instanceof IField) { + IFieldDelta fieldDelta = compareField((IField) from, + (IField) to); + if (fieldDelta != null) { + delta = new SigValueDelta(from, to); + } + } else if (from instanceof ITypeReference) { + ITypeReferenceDelta<? extends ITypeReference> typeDelta = + compareType((ITypeReference) from, (ITypeReference) to, + false); + if (typeDelta != null) { + delta = new SigValueDelta(from, to); + } + } else if (!from.equals(to)) { + delta = new SigValueDelta(from, to); + } + + } else if (!(from == null && to == null)) { + delta = new SigValueDelta(from, to); + } + return delta; + } + + private boolean considerEqualTypes(ITypeReference from, ITypeReference to) { + assert from != null && to != null; + + if (implementInterface(from, to, IPrimitiveType.class)) { + return comparePrimitiveType((IPrimitiveType) from, + (IPrimitiveType) to) == null; + } + if (implementInterface(from, to, IClassReference.class)) { + return sameClassDefinition(((IClassReference) from) + .getClassDefinition(), ((IClassReference) to) + .getClassDefinition()); + } + if (implementInterface(from, to, IArrayType.class)) { + return considerEqualTypes(((IArrayType) from).getComponentType(), + ((IArrayType) to).getComponentType()); + } + if (implementInterface(from, to, IParameterizedType.class)) { + return compareClassReference(((IParameterizedType) from) + .getRawType(), ((IParameterizedType) to) + .getRawType()) == null; + } + if (implementInterface(from, to, ITypeVariableReference.class)) { + return compareTypeVariableReference((ITypeVariableReference) from, + (ITypeVariableReference) to) == null; + } + + return false; + } + + private Set<ITypeReference> fromComparison = new HashSet<ITypeReference>(); + private Set<ITypeReference> toComparison = new HashSet<ITypeReference>(); + + + private boolean areInComparison(ITypeReference from, ITypeReference to) { + return fromComparison.contains(from) && toComparison.contains(to); + } + + private void markInComparison(ITypeReference from, ITypeReference to) { + fromComparison.add(from); + toComparison.add(to); + } + + private void markFinishedComparison(ITypeReference from, + ITypeReference to) { + fromComparison.remove(from); + toComparison.remove(to); + } + + private ITypeReferenceDelta<? extends ITypeReference> compareType( + ITypeReference from, ITypeReference to, boolean acceptErasedTypes) { + + if (from == null && to == null) { + return null; + } + if ((from == null && to != null) || (from != null && to == null)) { + return new SigTypeDelta<ITypeReference>(from, to); + } + if (areInComparison(from, to)) { + return null; + } + try { + markInComparison(from, to); + + if (implementInterface(from, to, IPrimitiveType.class)) { + return comparePrimitiveType((IPrimitiveType) from, + (IPrimitiveType) to); + } + if (implementInterface(from, to, IClassReference.class)) { + return compareClassReference((IClassReference) from, + (IClassReference) to); + } + if (implementInterface(from, to, IArrayType.class)) { + return compareArrayType((IArrayType) from, (IArrayType) to); + } + if (implementInterface(from, to, IParameterizedType.class)) { + return compareParameterizedType((IParameterizedType) from, + (IParameterizedType) to, acceptErasedTypes); + } + if (implementInterface(from, to, ITypeVariableReference.class)) { + return compareTypeVariableReference( + (ITypeVariableReference) from, + (ITypeVariableReference) to); + } + if (implementInterface(from, to, IWildcardType.class)) { + return compareWildcardType((IWildcardType) from, + (IWildcardType) to); + } + + if (acceptErasedTypes) { + if (isGeneric(from) && !isGeneric(to)) { + return compareType(getErasedType(from), to, false); + } + + if (!isGeneric(from) && isGeneric(to)) { + return compareType(from, getErasedType(to), false); + } + } + return new SigTypeDelta<ITypeReference>(from, to); + } finally { + markFinishedComparison(from, to); + } + } + + private boolean isGeneric(ITypeReference reference) { + if (reference instanceof IParameterizedType + || reference instanceof ITypeVariableReference + || reference instanceof IWildcardType) { + return true; + } + if (reference instanceof IArrayType) { + return isGeneric(((IArrayType) reference).getComponentType()); + } + return false; + } + + private ITypeReference getErasedType(ITypeReference reference) { + + if (reference instanceof IParameterizedType) { + return ((IParameterizedType) reference).getRawType(); + } + if (reference instanceof ITypeVariableReference) { + ITypeVariableDefinition typeVariableDefinition = + ((ITypeVariableReference) reference) + .getTypeVariableDefinition(); + return getErasedType( + typeVariableDefinition.getUpperBounds().get(0)); + } + if (reference instanceof IWildcardType) { + return getErasedType(((IWildcardType) reference).getUpperBounds() + .get(0)); + } + if (reference instanceof IArrayType) { + // FIXME implement with erasure projection? + return new SigArrayType(getErasedType(((IArrayType) reference) + .getComponentType())); + } + if (reference instanceof IPrimitiveType) { + return reference; + } + if (reference instanceof IClassReference) { + return reference; + } + throw new IllegalArgumentException("Unexpected type: " + reference); + } + + private boolean implementInterface(ITypeReference from, ITypeReference to, + Class<?> check) { + return check.isAssignableFrom(from.getClass()) + && check.isAssignableFrom(to.getClass()); + } + + private IWildcardTypeDelta compareWildcardType(IWildcardType from, + IWildcardType to) { + SigWildcardTypeDelta delta = null; + + ITypeReference fromLowerBound = from.getLowerBound(); + ITypeReference toLowerBound = to.getLowerBound(); + + ITypeReferenceDelta<?> lowerBoundDelta = compareType(fromLowerBound, + toLowerBound, false); + if (lowerBoundDelta != null) { + delta = new SigWildcardTypeDelta(from, to); + delta.setLowerBoundDelta(lowerBoundDelta); + } + + IUpperBoundsDelta upperBoundsDelta = compareUpperBounds(from + .getUpperBounds(), to.getUpperBounds()); + if (upperBoundsDelta != null) { + if (delta == null) { + delta = new SigWildcardTypeDelta(from, to); + } + delta.setUpperBoundDelta(upperBoundsDelta); + } + return delta; + } + + private IGenericDeclarationDelta compareGenericDeclaration( + ITypeVariableDefinition fromVariable, + ITypeVariableDefinition toVariable) { + IGenericDeclarationDelta delta = null; + + IGenericDeclaration from = fromVariable.getGenericDeclaration(); + IGenericDeclaration to = toVariable.getGenericDeclaration(); + + if (from != null && to != null) { + + if (from.getClass() != to.getClass()) { + delta = new SigGenericDeclarationDelta(from, to); + } else if (from instanceof IClassDefinition) { + IClassDefinition fromDeclaringClass = (IClassDefinition) from; + IClassDefinition toDeclaringClass = (IClassDefinition) to; + + if (!sameClassDefinition(fromDeclaringClass, + toDeclaringClass)) { + delta = new SigGenericDeclarationDelta(from, to); + } + + } else if (from instanceof IConstructor) { + IConstructor fromConstructor = (IConstructor) from; + IConstructor toConstructor = (IConstructor) from; + + String fromConstructorName = fromConstructor.getName(); + String fromClassName = fromConstructor.getDeclaringClass() + .getQualifiedName(); + + String toConstructorName = toConstructor.getName(); + String toClassName = toConstructor.getDeclaringClass() + .getQualifiedName(); + + if ((!fromConstructorName.equals(toConstructorName)) + || (!fromClassName.equals(toClassName))) { + delta = new SigGenericDeclarationDelta(from, to); + } + + } else if (from instanceof IMethod) { + IMethod fromMethod = (IMethod) from; + IMethod toMethod = (IMethod) from; + + String fromConstructorName = fromMethod.getName(); + String fromClassName = fromMethod.getDeclaringClass() + .getQualifiedName(); + + String toConstructorName = toMethod.getName(); + String toClassName = toMethod.getDeclaringClass() + .getQualifiedName(); + + if ((!fromConstructorName.equals(toConstructorName)) + || (!fromClassName.equals(toClassName))) { + delta = new SigGenericDeclarationDelta(from, to); + } + } else { + throw new IllegalStateException("Invlaid eclaration site: " + + from); + } + + // check position + int fromPosition = getPositionOf(fromVariable, from); + int toPosition = getPositionOf(toVariable, to); + + if (fromPosition != toPosition) { + delta = new SigGenericDeclarationDelta(from, to); + } + + + } else { + // one of both is null + delta = new SigGenericDeclarationDelta(from, to); + } + return delta; + } + + private int getPositionOf(ITypeVariableDefinition variable, + IGenericDeclaration declaration) { + return declaration.getTypeParameters().indexOf(variable); + } + + private IUpperBoundsDelta compareUpperBounds(List<ITypeReference> from, + List<ITypeReference> to) { + if (from.isEmpty() && to.isEmpty()) { + return null; + } + SigUpperBoundsDelta delta = null; + + ITypeReference fromFirstUpperBound = from.get(0); + ITypeReference toFirstUpperBound = to.get(0); + + ITypeReferenceDelta<?> firstUpperBoundDelta = compareType( + fromFirstUpperBound, toFirstUpperBound, false); + if (firstUpperBoundDelta != null) { + delta = new SigUpperBoundsDelta(from, to); + delta.setFirstUpperBoundDelta(firstUpperBoundDelta); + } else { + // normalize + Set<ITypeReference> normalizedfrom = removeGeneralizations( + new HashSet<ITypeReference>(from)); + Set<ITypeReference> normalizedto = removeGeneralizations( + new HashSet<ITypeReference>(to)); + + Set<ITypeReferenceDelta<?>> remainingUpperBoundsDelta = + compareTypes(normalizedfrom, normalizedto); + if (remainingUpperBoundsDelta != null) { + delta = new SigUpperBoundsDelta(from, to); + delta.setRemainingUpperBoundDeltas(remainingUpperBoundsDelta); + } + } + return delta; + } + + private Set<ITypeReference> removeGeneralizations( + Set<ITypeReference> bounds) { + Set<ITypeReference> boundsCopy = new HashSet<ITypeReference>(bounds); + for (ITypeReference type : bounds) { + Iterator<ITypeReference> it = boundsCopy.iterator(); + while (it.hasNext()) { + ITypeReference superType = it.next(); + if (isSuperClass(getClassDefinition(superType), + getClassDefinition(type)) + || isSuperInterface(getClassDefinition(superType), + getClassDefinition(type))) { + it.remove(); + } + } + } + return boundsCopy; + } + + private IParameterizedTypeDelta compareParameterizedType( + IParameterizedType from, IParameterizedType to, + boolean ignoreTypeArguments) { + + SigParameterizedTypeDelta delta = null; + // check raw type + ITypeReferenceDelta<?> rawTypeDelta = compareType(from.getRawType(), to + .getRawType(), false); + if (rawTypeDelta != null) { + delta = new SigParameterizedTypeDelta(from, to); + delta.setRawTypeDelta(rawTypeDelta); + } else { + // check owner type + ITypeReferenceDelta<?> ownerTypeDelta = compareType(from + .getOwnerType(), to.getOwnerType(), false); + if (ownerTypeDelta != null) { + delta = new SigParameterizedTypeDelta(from, to); + delta.setOwnerTypeDelta(ownerTypeDelta); + } else { + // check argument type + if (!ignoreTypeArguments) { + Set<ITypeReferenceDelta<?>> argumentTypeDeltas = + compareTypeSequence(from.getTypeArguments(), + to.getTypeArguments(), false); + if (argumentTypeDeltas != null) { + delta = new SigParameterizedTypeDelta(from, to); + delta.setArgumentTypeDeltas(argumentTypeDeltas); + } + } + } + } + return delta; + } + + private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypeSequence( + List<ITypeReference> from, List<ITypeReference> to, + boolean ignoreTypeArguments) { + Set<ITypeReferenceDelta<?>> deltas = + new HashSet<ITypeReferenceDelta<?>>(); + if (from.size() != to.size()) { + + for (ITypeReference type : from) { + deltas.add(new SigTypeDelta<ITypeReference>(type, null)); + } + for (ITypeReference type : to) { + deltas.add(new SigTypeDelta<ITypeReference>(null, type)); + } + return deltas; + } + + Iterator<? extends ITypeReference> fromIterator = from.iterator(); + Iterator<? extends ITypeReference> toIterator = to.iterator(); + while (fromIterator.hasNext() && toIterator.hasNext()) { + ITypeReferenceDelta<?> delta = compareType(fromIterator.next(), + toIterator.next(), ignoreTypeArguments); + if (delta != null) { + deltas.add(delta); + } + } + return deltas.isEmpty() ? null : deltas; + } + + private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypes( + Set<ITypeReference> from, Set<ITypeReference> to) { + return compareSets(from, to, + new SigComparator<ITypeReference, ITypeReferenceDelta<? extends ITypeReference>>() { + public ITypeReferenceDelta<? extends ITypeReference> createAddRemoveDelta( + ITypeReference from, ITypeReference to) { + return new SigTypeDelta<ITypeReference>(from, to); + } + + public boolean considerEqualElement(ITypeReference from, + ITypeReference to) { + return considerEqualTypes(from, to); + } + + public ITypeReferenceDelta<? extends ITypeReference> createChangedDelta( + ITypeReference from, ITypeReference to) { + return compareType(from, to, false); + } + }); + } + + private static interface SigComparator<T, S extends IDelta<? extends T>> { + boolean considerEqualElement(T from, T to); + + S createChangedDelta(T from, T to); + + /** + * If null is returned, it will be ignored. + */ + S createAddRemoveDelta(T from, T to); + } + + + private <T, S extends IDelta<? extends T>> Set<S> compareSets(Set<T> from, + Set<T> to, SigComparator<T, S> comparator) { + + Set<T> toCopy = new HashSet<T>(to); + Set<S> deltas = new HashSet<S>(); + + for (T fromType : from) { + Iterator<T> toIterator = toCopy.iterator(); + boolean equals = false; + boolean hasNext = toIterator.hasNext(); + + while (hasNext && !equals) { + T toElement = toIterator.next(); + equals = comparator.considerEqualElement(fromType, toElement); + if (equals) { + S compare = comparator.createChangedDelta(fromType, + toElement); + if (compare != null) { + deltas.add(compare); + } + } + hasNext = toIterator.hasNext(); + } + + if (equals) { + toIterator.remove(); + } else { + S delta = comparator.createAddRemoveDelta(fromType, null); + if (delta != null) { + deltas.add(delta); + } + } + } + + for (T type : toCopy) { + S delta = comparator.createAddRemoveDelta(null, type); + if (delta != null) { + deltas.add(delta); + } + } + return deltas.isEmpty() ? null : deltas; + } + + + private ITypeReferenceDelta<?> compareArrayType(IArrayType from, + IArrayType to) { + ITypeReferenceDelta<?> componentTypeDelta = compareType(from + .getComponentType(), to.getComponentType(), false); + if (componentTypeDelta != null) { + SigArrayTypeDelta delta = new SigArrayTypeDelta(from, to); + delta.setComponentTypeDelta(componentTypeDelta); + return delta; + } + return null; + } + + private ITypeReferenceDelta<IClassReference> compareClassReference( + IClassReference fromRef, IClassReference toRef) { + IClassDefinition from = fromRef.getClassDefinition(); + IClassDefinition to = toRef.getClassDefinition(); + + if (!sameClassDefinition(from, to)) { + return new SigClassReferenceDelta(fromRef, toRef); + } + return null; + } + + + private boolean sameClassDefinition(IClassDefinition from, + IClassDefinition to) { + boolean sameName = from.getName().equals(to.getName()); + boolean samePackage = from.getPackageName().equals(to.getPackageName()); + + Kind fromKind = from.getKind(); + Kind toKind = to.getKind(); + boolean sameKind = (fromKind == null || toKind == null) + || fromKind.equals(toKind); + + return sameName && samePackage && sameKind; + } + + private IPrimitiveTypeDelta comparePrimitiveType(IPrimitiveType from, + IPrimitiveType to) { + if (!from.equals(to)) { + return new SigPrimitiveTypeDelta(from, to); + } + return null; + } +} diff --git a/tools/signature-tools/src/signature/compare/IApiComparator.java b/tools/signature-tools/src/signature/compare/IApiComparator.java new file mode 100644 index 00000000000..08ed97fd963 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/IApiComparator.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare; + +import signature.compare.model.IApiDelta; +import signature.model.IApi; + +/** + * {@code IApiComparator} defines the functionality of a signature comparator. + */ +public interface IApiComparator { + + /** + * Returns a difference model which describes the differences from {@code + * fromApi} to {@code toApi}. + * + * @param fromApi + * differences are computed relative to {@code fromApi} + * @param toApi + * the target signature model + * @return a difference model which describes the differences from {@code + * fromApi} to {@code toApi} + */ + IApiDelta compare(IApi fromApi, IApi toApi); +} diff --git a/tools/signature-tools/src/signature/compare/Main.java b/tools/signature-tools/src/signature/compare/Main.java new file mode 100644 index 00000000000..80edb4536fd --- /dev/null +++ b/tools/signature-tools/src/signature/compare/Main.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare; + +import signature.UsageException; +import signature.compare.model.IApiDelta; +import signature.compare.model.IPackageDelta; +import signature.compare.model.impl.SigDelta; +import signature.converter.Visibility; +import signature.converter.dex.DexFactory; +import signature.converter.doclet.DocletFactory; +import signature.io.IApiDeltaExternalizer; +import signature.io.IApiLoader; +import signature.io.html.HtmlDeltaExternalizer; +import signature.io.impl.BinaryApi; +import signature.model.IApi; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Driver class for the --compare option. + */ +public class Main { + + /** + * <pre> + * --from=(doclet | dex | sig) <sourcefiles> + * --name <name> + * --to=(doclet | dex | sig) <sourcefiles> + * --name <name> + * --out directory + * --packages packageName{ packageName} + * </pre> + */ + public static void main(String[] args) throws IOException { + int at = 0; + + if (!"--from".equals(args[at])) { + throw new UsageException(); + } + String fromType = args[++at]; + + boolean hasName = false; + Set<String> fromFiles = new HashSet<String>(); + ++at; + for (/* at */; at < args.length; at++) { + if ("--name".equals(args[at])) { + hasName = true; + break; + } + if ("--to".equals(args[at])) { + break; + } + fromFiles.add(args[at]); + } + + String nameFrom = null; + if (hasName) { + nameFrom = ""; + if (!"--name".equals(args[at])) { + throw new UsageException(); + } + ++at; + for (/* at */; at < args.length; at++) { + if ("--to".equals(args[at])) { + break; + } + nameFrom += args[at]; + nameFrom += " "; + } + nameFrom = nameFrom.trim(); + } + + if (!"--to".equals(args[at])) { + throw new UsageException(); + } + String toType = args[++at]; + + hasName = false; + Set<String> toFiles = new HashSet<String>(); + ++at; + for (/* at */; at < args.length; at++) { + if ("--name".equals(args[at])) { + hasName = true; + break; + } + if ("--out".equals(args[at])) { + break; + } + toFiles.add(args[at]); + } + + String nameTo = null; + if (hasName) { + nameTo = ""; + if (!"--name".equals(args[at])) { + throw new UsageException(); + } + ++at; + for (/* at */; at < args.length; at++) { + if ("--out".equals(args[at])) { + break; + } + nameTo += args[at]; + nameTo += " "; + } + nameTo = nameTo.trim(); + } + + if (!"--out".equals(args[at])) { + throw new UsageException(); + } + String output = args[++at]; + + if (!"--packages".equals(args[++at])) { + throw new UsageException(); + } + Set<String> packages = new HashSet<String>(); + ++at; + for (/* at */; at < args.length; at++) { + packages.add(args[at]); + } + + IApiComparator comparator = new ApiComparator(); + IApi fromApi = getApi(fromType, nameFrom, fromFiles, packages); + IApi toApi = getApi(toType, nameTo, toFiles, packages); + + IApiDeltaExternalizer externalizer = new HtmlDeltaExternalizer(); + System.out.println("Writing delta report to " + output); + IApiDelta delta = comparator.compare(fromApi, toApi); + if (delta == null) { + delta = new EmptyDelta(fromApi, toApi); + } + + externalizer.externalize(output, delta); + } + + private static class EmptyDelta extends SigDelta<IApi> implements + IApiDelta { + public EmptyDelta(IApi from, IApi to) { + super(from, to); + } + + public Set<IPackageDelta> getPackageDeltas() { + return Collections.emptySet(); + } + } + + private static IApi getApi(String specType, String name, + Set<String> fileNames, Set<String> packageNames) throws + IOException { + System.out.println("Loading " + name + " of type " + specType + + " from " + fileNames); + IApiLoader factory = null; + if ("doclet".equals(specType)) { + checkName(name); + factory = new DocletFactory(); + } else if ("dex".equals(specType)) { + checkName(name); + factory = new DexFactory(); + } else if ("sig".equals(specType)) { + factory = new BinaryApi(); + } else { + throw new UsageException(); + } + return factory.loadApi(name, Visibility.PROTECTED, fileNames, + packageNames); + } + + private static void checkName(String name) { + if (name == null) { + throw new UsageException(); + } + } +} diff --git a/tools/signature-tools/src/signature/compare/model/DeltaType.java b/tools/signature-tools/src/signature/compare/model/DeltaType.java new file mode 100644 index 00000000000..a3aad2c0eb0 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/DeltaType.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +/** + * {@code DeltaType} defines the three possible types of a delta. + */ +public enum DeltaType { + /** + * States that an element was added to the toApi. + */ + ADDED, + /** + * States that an element was removed from the toApi. + */ + REMOVED, + /** + * States that an element changed. + */ + CHANGED +} diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java new file mode 100644 index 00000000000..dd41c601f47 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +/** + * {@code IAnnotatableElementDelta} is the common base interface for deltas + * which may have {@link IAnnotationDelta}s. + */ +public interface IAnnotatableElementDelta { + + /** + * Returns a set of annotation deltas or {@code null} if no deltas are + * available. + * + * @return a set of annotation deltas, maybe {@code null} + */ + Set<IAnnotationDelta> getAnnotationDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java new file mode 100644 index 00000000000..2e29358b6c4 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IAnnotation; + +/** + * {@code IAnnotationDelta} models the delta between two {@link IAnnotation} + * instances. + */ +public interface IAnnotationDelta extends IDelta<IAnnotation> { + + /** + * Returns a set of annotation element deltas or {@code null} if no deltas + * are available. + * + * @return a set of annotation element deltas, maybe {@code null} + */ + Set<IAnnotationElementDelta> getAnnotationElementDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java new file mode 100644 index 00000000000..4355fdb9049 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IAnnotationElement; + +/** + * {@code IAnnotationElementDelta} models the delta between two + * {@link IAnnotationElement} instances. + */ +public interface IAnnotationElementDelta extends IDelta<IAnnotationElement> { + + /** + * Returns a value delta or {@code null} if no delta is available. + * + * @return a value delta, maybe {@code null} + */ + IValueDelta getValueDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java new file mode 100644 index 00000000000..223072a3837 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IAnnotationField; + +/** + * {@code IAnnotationFieldDelta} models the delta between two + * {@link IAnnotationField} instances. + */ +public interface IAnnotationFieldDelta extends IMemberDelta<IAnnotationField> { + + /** + * Returns the default value delta or {@code null} if no delta is available. + * + * @return the default value delta, maybe {@code null} + */ + IValueDelta getDefaultValueDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IApiDelta.java b/tools/signature-tools/src/signature/compare/model/IApiDelta.java new file mode 100644 index 00000000000..78a8c34e2fd --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IApiDelta.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IApi; + +/** + * {@code IApiDelta} models the delta between two {@link IApi} instances. + */ +public interface IApiDelta extends IDelta<IApi> { + + /** + * Returns a set of package deltas or {@code null} if no deltas are + * available. + * + * @return a set of package deltas, maybe {@code null} + */ + Set<IPackageDelta> getPackageDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java new file mode 100644 index 00000000000..bb29bcda2aa --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IArrayType; + +/** + * {@code IArrayTypeDelta} models the delta between two {@link IArrayType} + * instances. + */ +public interface IArrayTypeDelta extends ITypeReferenceDelta<IArrayType> { + + /** + * Returns a component type delta or {@code null} if no delta is available. + * + * @return a component type delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getComponentTypeDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java new file mode 100644 index 00000000000..5cbaf9b283a --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IClassDefinition; + +/** + * {@code IClassDefinitionDelta} models the delta between two + * {@link IClassDefinition} instances. + */ +public interface IClassDefinitionDelta extends + ITypeDefinitionDelta<IClassDefinition>, IAnnotatableElementDelta, + ITypeVariableDeltas { + + /** + * Returns a set of field deltas or {@code null} if no deltas are available. + * + * @return a set of field deltas, maybe {@code null} + */ + Set<IFieldDelta> getFieldDeltas(); + + /** + * Returns a set of enum constant deltas or {@code null} if no deltas are + * available. + * + * @return a set of enum constant deltas, maybe {@code null} + */ + Set<IEnumConstantDelta> getEnumConstantDeltas(); + + /** + * Returns a set of annotation field deltas or {@code null} if no deltas are + * available. + * + * @return a set of annotation field deltas, maybe {@code null} + */ + Set<IAnnotationFieldDelta> getAnnotationFieldDeltas(); + + /** + * Returns a set of method deltas or {@code null} if no deltas are + * available. + * + * @return a set of method deltas, maybe {@code null} + */ + Set<IMethodDelta> getMethodDeltas(); + + /** + * Returns a set of constructor deltas or {@code null} if no deltas are + * available. + * + * @return a set of constructor deltas, maybe {@code null} + */ + Set<IConstructorDelta> getConstructorDeltas(); + + /** + * Returns a set of modifier deltas or {@code null} if no deltas are + * available. + * + * @return a set of modifier deltas, maybe {@code null} + */ + Set<IModifierDelta> getModifierDeltas(); + + /** + * Returns a super class delta or {@code null} if no delta is available. + * + * @return a super class delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getSuperClassDelta(); + + /** + * Returns a set of interface deltas or {@code null} if no deltas are + * available. + * + * @return a set of interface deltas, maybe {@code null} + */ + Set<ITypeReferenceDelta<?>> getInterfaceDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java b/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java new file mode 100644 index 00000000000..64ba993faa9 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IConstructor; + +/** + * {@code IConstructorDelta} models the delta between two {@link IConstructor} + * instances. + */ +public interface IConstructorDelta extends + IExecutableMemberDelta<IConstructor> { +} diff --git a/tools/signature-tools/src/signature/compare/model/IDelta.java b/tools/signature-tools/src/signature/compare/model/IDelta.java new file mode 100644 index 00000000000..bd94388fcd4 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IDelta.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +/** + * {@code IDelta} is the common base interface for all delta model elements. It + * describes a delta from a "from" element to a "to" element. + * + * @param <T> + * the type of the compared elements + */ +public interface IDelta<T> { + + /** + * Returns the type of this delta. + * + * @return the type of this delta + */ + DeltaType getType(); + + /** + * Returns the "from" element. Is null if type is {@link DeltaType#ADDED} + * + * @return the "from" element + */ + T getFrom(); + + /** + * Returns the "to" element. Is null if type is {@link DeltaType#REMOVED} + * + * @return the "to" element + */ + T getTo(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java b/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java new file mode 100644 index 00000000000..6590c5a8f86 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IEnumConstant; + +/** + * {@code IEnumConstantDelta} models the delta between two {@link IEnumConstant} + * instances. + */ +public interface IEnumConstantDelta extends IMemberDelta<IEnumConstant> { + IValueDelta getOrdinalDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java b/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java new file mode 100644 index 00000000000..30f7038ceec --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IExecutableMember; + +/** + * {@code IExecutableMemberDelta} models the delta between two + * {@link IExecutableMember} instances. + */ +public interface IExecutableMemberDelta<T extends IExecutableMember> extends + IDelta<T>, ITypeVariableDeltas, IAnnotatableElementDelta { + + /** + * Returns a set of modifier deltas or {@code null} if no deltas are + * available. + * + * @return a set of modifier deltas, maybe {@code null} + */ + Set<IModifierDelta> getModifierDeltas(); + + /** + * Returns a set of exception deltas or {@code null} if no deltas are + * available. + * + * @return a set of exception deltas, maybe {@code null} + */ + Set<ITypeReferenceDelta<?>> getExceptionDeltas(); + + /** + * Returns a set of parameter deltas or {@code null} if no deltas are + * available. + * + * @return a set of parameter deltas, maybe {@code null} + */ + Set<IParameterDelta> getParameterDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IFieldDelta.java b/tools/signature-tools/src/signature/compare/model/IFieldDelta.java new file mode 100644 index 00000000000..ab9bf766d73 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IFieldDelta.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IField; + +/** + * {@code IFieldDelta} models the delta between two {@link IField} instances. + */ +public interface IFieldDelta extends IMemberDelta<IField> { +} diff --git a/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java b/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java new file mode 100644 index 00000000000..5cd518c5ff3 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IGenericDeclaration; + +/** + * {@code IGenericDeclarationDelta} models the delta between two + * {@link IGenericDeclaration} instances. + */ +public interface IGenericDeclarationDelta extends IDelta<IGenericDeclaration> { +} diff --git a/tools/signature-tools/src/signature/compare/model/IMemberDelta.java b/tools/signature-tools/src/signature/compare/model/IMemberDelta.java new file mode 100644 index 00000000000..df78307f54a --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IMemberDelta.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IField; + +/** + * {@code IMemberDelta} models the delta between two {@link IField} subclass + * instances. + */ +public interface IMemberDelta<T extends IField> extends IDelta<T>, + IAnnotatableElementDelta { + + /** + * Returns a type delta or {@code null} if no delta is available. + * + * @return a type delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getTypeDelta(); + + /** + * Returns a set of modifier deltas or {@code null} if no deltas are + * available. + * + * @return a set of modifier deltas, maybe {@code null} + */ + Set<IModifierDelta> getModifierDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IMethodDelta.java b/tools/signature-tools/src/signature/compare/model/IMethodDelta.java new file mode 100644 index 00000000000..3e94d263045 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IMethodDelta.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IMethod; + +/** + * {@code IMethodDelta} models the delta between two {@link IMethod} subclass + * instances. + */ +public interface IMethodDelta extends IExecutableMemberDelta<IMethod> { + + /** + * Returns a return type delta or {@code null} if no delta is available. + * + * @return a return type delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getReturnTypeDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IModifierDelta.java b/tools/signature-tools/src/signature/compare/model/IModifierDelta.java new file mode 100644 index 00000000000..4553e1092e7 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IModifierDelta.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.Modifier; + +/** + * {@code IModifierDelta} models the delta between two {@link Modifier} + * instances. + */ +public interface IModifierDelta extends IDelta<Modifier> { +} diff --git a/tools/signature-tools/src/signature/compare/model/IPackageDelta.java b/tools/signature-tools/src/signature/compare/model/IPackageDelta.java new file mode 100644 index 00000000000..8c697c3d9ba --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IPackageDelta.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IPackage; + +/** + * {@code IPackageDelta} models the delta between two {@link IPackage} + * instances. + */ +public interface IPackageDelta extends IDelta<IPackage>, + IAnnotatableElementDelta { + + /** + * Returns a set of class definition deltas or {@code null} if no deltas are + * available. + * + * @return a set of class definition deltas, maybe {@code null} + */ + Set<IClassDefinitionDelta> getClassDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IParameterDelta.java b/tools/signature-tools/src/signature/compare/model/IParameterDelta.java new file mode 100644 index 00000000000..b2a6a80f041 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IParameterDelta.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IParameter; + +/** + * {@code IParameterDelta} models the delta between two {@link IParameter} + * instances. + */ +public interface IParameterDelta extends IDelta<IParameter>, + IAnnotatableElementDelta { + + /** + * Returns a parameter type delta or {@code null} if no delta is available. + * + * @return a parameter type delta, maybe {@code null} + */ + public ITypeReferenceDelta<?> getTypeDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java new file mode 100644 index 00000000000..be54a01b6e4 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +import signature.model.IParameterizedType; + +/** + * {@code IParameterizedTypeDelta} models the delta between two + * {@link IParameterizedType} instances. + */ +public interface IParameterizedTypeDelta extends + ITypeReferenceDelta<IParameterizedType> { + + /** + * Returns a raw type delta or {@code null} if no delta is available. + * + * @return a raw type delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getRawTypeDelta(); + + /** + * Returns a owner type delta or {@code null} if no delta is available. + * + * @return a owner type delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getOwnerTypeDelta(); + + /** + * Returns a set of argument type deltas or {@code null} if no deltas are + * available. + * + * @return a set of argument type deltas, maybe {@code null} + */ + Set<ITypeReferenceDelta<?>> getArgumentTypeDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java new file mode 100644 index 00000000000..f7294359dd2 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IPrimitiveType; + +/** + * {@code IPrimitiveTypeDelta} models the delta between two + * {@link IPrimitiveType} instances. + */ +public interface IPrimitiveTypeDelta extends + ITypeReferenceDelta<IPrimitiveType> { +} diff --git a/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java new file mode 100644 index 00000000000..932cc39be3c --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.ITypeDefinition; + +/** + * {@code ITypeDefinitionDelta} is the common base interface for deltas which + * model differences between type definitions. + */ +public interface ITypeDefinitionDelta<T extends ITypeDefinition> extends + IDelta<T> { +} diff --git a/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java new file mode 100644 index 00000000000..fba52f0a3c7 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.ITypeReference; + +/** + * {@code ITypeReferenceDelta} is the common base interface for deltas which + * model differences between type references. + */ +public interface ITypeReferenceDelta<T extends ITypeReference> extends + IDelta<T> { +} diff --git a/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java new file mode 100644 index 00000000000..1e8f3cd803e --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.ITypeVariableDefinition; + +/** + * {@code ITypeVariableDefinitionDelta} models the delta between two + * {@link ITypeVariableDefinition} instances. + */ +public interface ITypeVariableDefinitionDelta extends + ITypeDefinitionDelta<ITypeVariableDefinition> { + + /** + * Returns an upper bound delta or {@code null} if no delta is available. + * + * @return an upper bound delta, maybe {@code null} + */ + IUpperBoundsDelta getUpperBoundsDelta(); + + /** + * Returns a generic declaration delta or {@code null} if no delta is + * available. + * + * @return a generic declaration delta, maybe {@code null} + */ + IGenericDeclarationDelta getGenericDeclarationDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java b/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java new file mode 100644 index 00000000000..a88ea306126 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.Set; + +/** + * Common interface for all deltas which may have {@code + * ITypeVariableDefinitionDelta}s. Type variable deltas can occur, where type + * variables can be defined. On classes, constructors and methods. + * + * @see IClassDefinitionDelta + * @see IExecutableMemberDelta (common super interface of the following two + * interfaces) + * @see IConstructorDelta + * @see IMethodDelta + */ +public interface ITypeVariableDeltas { + + /** + * Returns a set of type variable deltas or {@code null} if no deltas are + * available. + * + * @return a set of type variable deltas, maybe {@code null} + */ + Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java b/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java new file mode 100644 index 00000000000..44bd39a9aba --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import java.util.List; +import java.util.Set; + +import signature.model.ITypeReference; + +/** + * {@code IUpperBoundsDelta} models the delta between two {@link List + * <ITypeReference>} instances. + * <p> + * This interface is aware, that for the first argument, the order of the upper + * bounds is relevant (for erasure). + */ +public interface IUpperBoundsDelta extends IDelta<List<ITypeReference>> { + + /** + * Returns the upper bound delta of the first upper bound or {@code null} if + * no delta is available. + * + * @return the upper bound delta of the first upper bound, maybe {@code + * null} + */ + ITypeReferenceDelta<?> getFirstUpperBoundDelta(); + + /** + * Returns a set of remaining upper bound deltas or {@code null} if no + * deltas are available. + * + * @return a set of remaining upper bound deltas, maybe {@code null} + */ + Set<ITypeReferenceDelta<?>> getRemainingUpperBoundDeltas(); +} diff --git a/tools/signature-tools/src/signature/compare/model/IValueDelta.java b/tools/signature-tools/src/signature/compare/model/IValueDelta.java new file mode 100644 index 00000000000..abd1f59fe61 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IValueDelta.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + + +/** + * {@code IValueDelta} models the delta between two + * {@link Object} instances. + */ +public interface IValueDelta extends IDelta<Object> {} diff --git a/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java new file mode 100644 index 00000000000..1fda09c180a --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model; + +import signature.model.IWildcardType; + +/** + * {@code IWildcardTypeDelta} models the delta between two + * {@link IWildcardType} instances. + */ +public interface IWildcardTypeDelta extends ITypeReferenceDelta<IWildcardType> { + + /** + * Returns the upper bound delta or {@code null} if no delta is available. + * + * @return the upper bound delta, maybe {@code null} + */ + IUpperBoundsDelta getUpperBoundDelta(); + + /** + * Returns the lower bound delta or {@code null} if no delta is available. + * + * @return the lower bound delta, maybe {@code null} + */ + ITypeReferenceDelta<?> getLowerBoundDelta(); +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java new file mode 100644 index 00000000000..78e515f2198 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.Set; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IAnnotationElementDelta; +import signature.model.IAnnotation; + +public class SigAnnotationDelta extends SigDelta<IAnnotation> implements + IAnnotationDelta { + + private Set<IAnnotationElementDelta> annotationElementDeltas; + + public SigAnnotationDelta(IAnnotation from, IAnnotation to) { + super(from, to); + } + + public Set<IAnnotationElementDelta> getAnnotationElementDeltas() { + return annotationElementDeltas; + } + + public void setAnnotationElementDeltas( + Set<IAnnotationElementDelta> annotationElementDeltas) { + this.annotationElementDeltas = annotationElementDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java new file mode 100644 index 00000000000..cc7a6fcc7f7 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IAnnotationElementDelta; +import signature.compare.model.IValueDelta; +import signature.model.IAnnotationElement; + +public class SigAnnotationElementDelta extends SigDelta<IAnnotationElement> + implements IAnnotationElementDelta { + + private IValueDelta valueDelta; + + public SigAnnotationElementDelta(IAnnotationElement from, + IAnnotationElement to) { + super(from, to); + } + + public IValueDelta getValueDelta() { + return valueDelta; + } + + public void setValueDelta(IValueDelta valueDelta) { + this.valueDelta = valueDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java new file mode 100644 index 00000000000..90fcd7b38a2 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IAnnotationFieldDelta; +import signature.compare.model.IValueDelta; +import signature.model.IAnnotationField; + +public class SigAnnotationFieldDelta extends SigMemberDelta<IAnnotationField> + implements IAnnotationFieldDelta { + + private IValueDelta defaultValueDelta; + + public SigAnnotationFieldDelta(IAnnotationField from, IAnnotationField to) { + super(from, to); + } + + public IValueDelta getDefaultValueDelta() { + return defaultValueDelta; + } + + public void setDefaultValueDelta(IValueDelta valueDelta) { + this.defaultValueDelta = valueDelta; + } + +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java new file mode 100644 index 00000000000..bc2bd56cae8 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IApiDelta; +import signature.compare.model.IPackageDelta; +import signature.model.IApi; + +import java.util.Set; + +public class SigApiDelta extends SigDelta<IApi> implements IApiDelta { + + private Set<IPackageDelta> packageDeltas; + + public SigApiDelta(IApi from, IApi to) { + super(from, to); + } + + public Set<IPackageDelta> getPackageDeltas() { + return packageDeltas; + } + + public void setPackageDeltas(Set<IPackageDelta> packageDeltas) { + this.packageDeltas = packageDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java new file mode 100644 index 00000000000..5d472933bf6 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IArrayTypeDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IArrayType; + +public class SigArrayTypeDelta extends SigTypeDelta<IArrayType> implements + IArrayTypeDelta { + + private ITypeReferenceDelta<?> componentTypeDelta; + + public SigArrayTypeDelta(IArrayType from, IArrayType to) { + super(from, to); + } + + public ITypeReferenceDelta<?> getComponentTypeDelta() { + return componentTypeDelta; + } + + public void setComponentTypeDelta( + ITypeReferenceDelta<?> componentTypeDelta) { + this.componentTypeDelta = componentTypeDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java new file mode 100644 index 00000000000..40343518781 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IAnnotationFieldDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IConstructorDelta; +import signature.compare.model.IEnumConstantDelta; +import signature.compare.model.IFieldDelta; +import signature.compare.model.IMethodDelta; +import signature.compare.model.IModifierDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.compare.model.ITypeVariableDefinitionDelta; +import signature.model.IClassDefinition; + +import java.util.Set; + +public class SigClassDefinitionDelta extends + SigTypeDefinitionDelta<IClassDefinition> implements + IClassDefinitionDelta { + + public SigClassDefinitionDelta(IClassDefinition from, IClassDefinition to) { + super(from, to); + } + + private Set<IAnnotationFieldDelta> annotationFieldDeltas; + private Set<IConstructorDelta> constructorDeltas; + private Set<IEnumConstantDelta> enumConstantDeltas; + private Set<IFieldDelta> fieldDeltas; + private Set<ITypeReferenceDelta<?>> interfaceDeltas; + private Set<IMethodDelta> methodDeltas; + private Set<IModifierDelta> modifierDeltas; + private ITypeReferenceDelta<?> superClassDelta; + private Set<IAnnotationDelta> annotationDeltas; + private Set<ITypeVariableDefinitionDelta> typeVariableDeltas; + + public Set<IAnnotationFieldDelta> getAnnotationFieldDeltas() { + return annotationFieldDeltas; + } + + public void setAnnotationFieldDeltas( + Set<IAnnotationFieldDelta> annotationFieldDeltas) { + this.annotationFieldDeltas = annotationFieldDeltas; + } + + public Set<IConstructorDelta> getConstructorDeltas() { + return constructorDeltas; + } + + public void setConstructorDeltas( + Set<IConstructorDelta> constructorDeltas) { + this.constructorDeltas = constructorDeltas; + } + + public Set<IEnumConstantDelta> getEnumConstantDeltas() { + return enumConstantDeltas; + } + + public void setEnumConstantDeltas( + Set<IEnumConstantDelta> enumConstantDeltas) { + this.enumConstantDeltas = enumConstantDeltas; + } + + public Set<IFieldDelta> getFieldDeltas() { + return fieldDeltas; + } + + public void setFieldDeltas(Set<IFieldDelta> fieldDeltas) { + this.fieldDeltas = fieldDeltas; + } + + public Set<ITypeReferenceDelta<?>> getInterfaceDeltas() { + return interfaceDeltas; + } + + public void setInterfaceDeltas( + Set<ITypeReferenceDelta<?>> interfaceDeltas) { + this.interfaceDeltas = interfaceDeltas; + } + + public Set<IMethodDelta> getMethodDeltas() { + return methodDeltas; + } + + public void setMethodDeltas(Set<IMethodDelta> methodDeltas) { + this.methodDeltas = methodDeltas; + } + + public Set<IModifierDelta> getModifierDeltas() { + return modifierDeltas; + } + + public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) { + this.modifierDeltas = modifierDeltas; + } + + public ITypeReferenceDelta<?> getSuperClassDelta() { + return superClassDelta; + } + + public void setSuperClassDelta(ITypeReferenceDelta<?> superClassDelta) { + this.superClassDelta = superClassDelta; + } + + public Set<IAnnotationDelta> getAnnotationDeltas() { + return annotationDeltas; + } + + public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) { + this.annotationDeltas = annotationDeltas; + } + + public Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas() { + return typeVariableDeltas; + } + + public void setTypeVariableDeltas( + Set<ITypeVariableDefinitionDelta> typeVariableDeltas) { + this.typeVariableDeltas = typeVariableDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java new file mode 100644 index 00000000000..18741ebea44 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IClassReference; + +public class SigClassReferenceDelta extends SigDelta<IClassReference> + implements ITypeReferenceDelta<IClassReference> { + + public SigClassReferenceDelta(IClassReference from, IClassReference to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java new file mode 100644 index 00000000000..9a7cf70ac77 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IConstructorDelta; +import signature.model.IConstructor; + +public class SigConstructorDelta extends SigExecutableMemberDelta<IConstructor> + implements IConstructorDelta { + + public SigConstructorDelta(IConstructor from, IConstructor to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java new file mode 100644 index 00000000000..933bf002035 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import signature.compare.model.IDelta; +import signature.compare.model.DeltaType; + +public abstract class SigDelta<T> implements IDelta<T> { + private T from; + private T to; + + public SigDelta(T from, T to) { + this.from = from; + this.to = to; + } + + public final T getFrom() { + return from; + } + + public final T getTo() { + return to; + } + + public final DeltaType getType() { + if (from == null && to != null) { + return DeltaType.ADDED; + } + if (from != null && to == null) { + return DeltaType.REMOVED; + } + return DeltaType.CHANGED; + } + + private static <T extends IDelta<?>> Set<T> getDeltas(Set<T> deltas, + DeltaType type) { + Set<T> addedElements = new HashSet<T>(); + for (T delta : deltas) { + if (type.equals(delta.getType())) { + addedElements.add(delta); + } + } + return addedElements; + } + + public static <T extends IDelta<?>> Set<T> getAdded(Set<T> deltas) { + return getDeltas(deltas, DeltaType.ADDED); + } + + public static <T extends IDelta<?>> Set<T> getRemoved(Set<T> deltas) { + return getDeltas(deltas, DeltaType.REMOVED); + } + + public static <T extends IDelta<?>> Set<T> getChanged(Set<T> deltas) { + return getDeltas(deltas, DeltaType.CHANGED); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getClass().getSimpleName()); + builder.append(":\n"); + + List<Field> allFields = new LinkedList<Field>(); + + Class<?> actualClass = getClass(); + + // add all fields / super classes also + do { + allFields.addAll(Arrays.asList(actualClass.getDeclaredFields())); + actualClass = actualClass.getSuperclass(); + } while (actualClass != Object.class); + + builder.append("from: "); + builder.append(from); + builder.append("\nto: "); + builder.append(to); + builder.append("\n"); + try { + for (Field field : allFields) { + if (!ignore.contains(field.getName())) { + field.setAccessible(true); + Object delta = field.get(this); + if (delta != null) { + builder.append(field.getName()); + builder.append(":\n"); + builder.append(delta); + } + } + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + return builder.toString(); + } + + private static Set<String> ignore = new HashSet<String>(); + { + ignore.add("from"); + ignore.add("to"); + ignore.add("reason"); + ignore.add("ignore"); // =) + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java new file mode 100644 index 00000000000..3a7f9e72d70 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IEnumConstantDelta; +import signature.compare.model.IValueDelta; +import signature.model.IEnumConstant; + +public class SigEnumConstantDelta extends SigMemberDelta<IEnumConstant> + implements IEnumConstantDelta { + + private IValueDelta ordinalDelta; + + public SigEnumConstantDelta(IEnumConstant from, IEnumConstant to) { + super(from, to); + } + + public IValueDelta getOrdinalDelta() { + return ordinalDelta; + } + + public void setOrdinalDelta(IValueDelta ordinalDelta) { + this.ordinalDelta = ordinalDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java new file mode 100644 index 00000000000..1d871e41e46 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IExecutableMemberDelta; +import signature.compare.model.IModifierDelta; +import signature.compare.model.IParameterDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.compare.model.ITypeVariableDefinitionDelta; +import signature.model.IExecutableMember; + +import java.util.Set; + +public abstract class SigExecutableMemberDelta<T extends IExecutableMember> + extends SigDelta<T> implements IExecutableMemberDelta<T> { + + private Set<ITypeReferenceDelta<?>> exceptionDeltas; + private Set<IModifierDelta> modifierDeltas; + private Set<ITypeVariableDefinitionDelta> typeVariableDeltas; + private Set<IAnnotationDelta> annotationDeltas; + private Set<IParameterDelta> parameterDeltas; + + public SigExecutableMemberDelta(T from, T to) { + super(from, to); + } + + public Set<ITypeReferenceDelta<?>> getExceptionDeltas() { + return exceptionDeltas; + } + + public void setExceptionDeltas( + Set<ITypeReferenceDelta<?>> exceptionDeltas) { + this.exceptionDeltas = exceptionDeltas; + } + + public Set<IModifierDelta> getModifierDeltas() { + return modifierDeltas; + } + + public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) { + this.modifierDeltas = modifierDeltas; + } + + public Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas() { + return typeVariableDeltas; + } + + public void setTypeVariableDeltas( + Set<ITypeVariableDefinitionDelta> typeVariableDeltas) { + this.typeVariableDeltas = typeVariableDeltas; + } + + public Set<IAnnotationDelta> getAnnotationDeltas() { + return annotationDeltas; + } + + public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) { + this.annotationDeltas = annotationDeltas; + } + + public Set<IParameterDelta> getParameterDeltas() { + return parameterDeltas; + } + + public void setParameterDeltas(Set<IParameterDelta> parameterDeltas) { + this.parameterDeltas = parameterDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java new file mode 100644 index 00000000000..6807eea8db0 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IFieldDelta; +import signature.model.IField; + +public class SigFieldDelta extends SigMemberDelta<IField> implements + IFieldDelta { + + public SigFieldDelta(IField from, IField to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java new file mode 100644 index 00000000000..d377b9501cd --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IGenericDeclarationDelta; +import signature.model.IGenericDeclaration; + +public class SigGenericDeclarationDelta extends SigDelta<IGenericDeclaration> + implements IGenericDeclarationDelta { + + public SigGenericDeclarationDelta(IGenericDeclaration from, + IGenericDeclaration to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java new file mode 100644 index 00000000000..2c5e9cb57b1 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.Set; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IMemberDelta; +import signature.compare.model.IModifierDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IField; + +public abstract class SigMemberDelta<T extends IField> extends SigDelta<T> + implements IMemberDelta<T> { + + private Set<IModifierDelta> modifierDeltas; + private ITypeReferenceDelta<?> typeDelta; + private Set<IAnnotationDelta> annotationDeltas; + + + public SigMemberDelta(T from, T to) { + super(from, to); + } + + public Set<IModifierDelta> getModifierDeltas() { + return modifierDeltas; + } + + public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) { + this.modifierDeltas = modifierDeltas; + } + + public ITypeReferenceDelta<?> getTypeDelta() { + return typeDelta; + } + + public void setTypeDelta(ITypeReferenceDelta<?> typeDelta) { + this.typeDelta = typeDelta; + } + + public Set<IAnnotationDelta> getAnnotationDeltas() { + return annotationDeltas; + } + + public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) { + this.annotationDeltas = annotationDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java new file mode 100644 index 00000000000..0a3fb2fc70f --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IMethodDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IMethod; + +public class SigMethodDelta extends SigExecutableMemberDelta<IMethod> implements + IMethodDelta { + + private ITypeReferenceDelta<?> returnTypeDelta; + + public SigMethodDelta(IMethod from, IMethod to) { + super(from, to); + } + + public ITypeReferenceDelta<?> getReturnTypeDelta() { + return returnTypeDelta; + } + + public void setReturnTypeDelta(ITypeReferenceDelta<?> returnTypeDelta) { + this.returnTypeDelta = returnTypeDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java new file mode 100644 index 00000000000..aa5e380b137 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IModifierDelta; +import signature.model.Modifier; + +public class SigModifierDelta extends SigDelta<Modifier> implements + IModifierDelta { + + public SigModifierDelta(Modifier from, Modifier to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java new file mode 100644 index 00000000000..0f368f6e685 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.Set; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IPackageDelta; +import signature.model.IPackage; + +public class SigPackageDelta extends SigDelta<IPackage> implements + IPackageDelta { + + private Set<IClassDefinitionDelta> classDeltas; + private Set<IAnnotationDelta> annotationDeltas; + + public SigPackageDelta(IPackage from, IPackage to) { + super(from, to); + } + + public Set<IClassDefinitionDelta> getClassDeltas() { + return classDeltas; + } + + public void setClassDeltas(Set<IClassDefinitionDelta> classDeltas) { + this.classDeltas = classDeltas; + } + + public Set<IAnnotationDelta> getAnnotationDeltas() { + return annotationDeltas; + } + + public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) { + this.annotationDeltas = annotationDeltas; + } + +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java new file mode 100644 index 00000000000..aee6466e88a --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.Set; + +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IParameterDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IParameter; + +public class SigParameterDelta extends SigDelta<IParameter> implements + IParameterDelta { + + private ITypeReferenceDelta<?> typeDelta; + private Set<IAnnotationDelta> annotationDeltas; + + public SigParameterDelta(IParameter from, IParameter to) { + super(from, to); + } + + public ITypeReferenceDelta<?> getTypeDelta() { + return typeDelta; + } + + public void setTypeDelta(ITypeReferenceDelta<?> typeDelta) { + this.typeDelta = typeDelta; + } + + public Set<IAnnotationDelta> getAnnotationDeltas() { + return annotationDeltas; + } + + public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) { + this.annotationDeltas = annotationDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java new file mode 100644 index 00000000000..08fbc219502 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.Set; + +import signature.compare.model.IParameterizedTypeDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.IParameterizedType; + +public class SigParameterizedTypeDelta extends SigTypeDelta<IParameterizedType> + implements IParameterizedTypeDelta { + + private ITypeReferenceDelta<?> ownerTypeDelta; + private ITypeReferenceDelta<?> rawTypeDelta; + private Set<ITypeReferenceDelta<?>> argumentTypeDeltas; + + public SigParameterizedTypeDelta(IParameterizedType from, + IParameterizedType to) { + super(from, to); + } + + public ITypeReferenceDelta<?> getOwnerTypeDelta() { + return ownerTypeDelta; + } + + public void setOwnerTypeDelta(ITypeReferenceDelta<?> ownerTypeDelta) { + this.ownerTypeDelta = ownerTypeDelta; + } + + public ITypeReferenceDelta<?> getRawTypeDelta() { + return rawTypeDelta; + } + + public void setRawTypeDelta(ITypeReferenceDelta<?> rawTypeDelta) { + this.rawTypeDelta = rawTypeDelta; + } + + public Set<ITypeReferenceDelta<?>> getArgumentTypeDeltas() { + return argumentTypeDeltas; + } + + public void setArgumentTypeDeltas( + Set<ITypeReferenceDelta<?>> argumentTypeDeltas) { + this.argumentTypeDeltas = argumentTypeDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java new file mode 100644 index 00000000000..03be8fa307b --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IPrimitiveTypeDelta; +import signature.model.IPrimitiveType; + +public class SigPrimitiveTypeDelta extends SigTypeDelta<IPrimitiveType> + implements IPrimitiveTypeDelta { + + public SigPrimitiveTypeDelta(IPrimitiveType from, IPrimitiveType to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java new file mode 100644 index 00000000000..c0bff8e53dc --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.ITypeDefinitionDelta; +import signature.model.ITypeDefinition; + +public abstract class SigTypeDefinitionDelta<T extends ITypeDefinition> extends + SigDelta<T> implements ITypeDefinitionDelta<T> { + + public SigTypeDefinitionDelta(T from, T to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java new file mode 100644 index 00000000000..718258ca994 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.ITypeReferenceDelta; +import signature.model.ITypeReference; + +public class SigTypeDelta<T extends ITypeReference> extends SigDelta<T> + implements ITypeReferenceDelta<T> { + + public SigTypeDelta(T from, T to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java new file mode 100644 index 00000000000..348c728c09b --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IGenericDeclarationDelta; +import signature.compare.model.ITypeVariableDefinitionDelta; +import signature.compare.model.IUpperBoundsDelta; +import signature.model.ITypeVariableDefinition; + +public class SigTypeVariableDefinitionDelta extends + SigDelta<ITypeVariableDefinition> implements + ITypeVariableDefinitionDelta { + + private IUpperBoundsDelta upperBoundsDelta; + private IGenericDeclarationDelta genericDeclarationDelta; + + public SigTypeVariableDefinitionDelta(ITypeVariableDefinition from, + ITypeVariableDefinition to) { + super(from, to); + } + + public IUpperBoundsDelta getUpperBoundsDelta() { + return upperBoundsDelta; + } + + public void setUpperBoundsDelta(IUpperBoundsDelta upperBoundsDelta) { + this.upperBoundsDelta = upperBoundsDelta; + } + + public IGenericDeclarationDelta getGenericDeclarationDelta() { + return genericDeclarationDelta; + } + + public void setGenericDeclarationDelta( + IGenericDeclarationDelta genericDeclarationDelta) { + this.genericDeclarationDelta = genericDeclarationDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java new file mode 100644 index 00000000000..4414a16ecd7 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IGenericDeclarationDelta; +import signature.compare.model.ITypeReferenceDelta; +import signature.model.ITypeVariableReference; + +public class SigTypeVariableReferenceDelta extends + SigDelta<ITypeVariableReference> implements + ITypeReferenceDelta<ITypeVariableReference> { + + private IGenericDeclarationDelta genericDeclarationDelta; + + public SigTypeVariableReferenceDelta(ITypeVariableReference from, + ITypeVariableReference to) { + super(from, to); + } + + public IGenericDeclarationDelta getGenericDeclarationDelta() { + return genericDeclarationDelta; + } + + public void setGenericDeclarationDelta( + IGenericDeclarationDelta genericDeclarationDelta) { + this.genericDeclarationDelta = genericDeclarationDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java new file mode 100644 index 00000000000..8822b260715 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import java.util.List; +import java.util.Set; + +import signature.compare.model.ITypeReferenceDelta; +import signature.compare.model.IUpperBoundsDelta; +import signature.model.ITypeReference; + +public class SigUpperBoundsDelta extends SigDelta<List<ITypeReference>> + implements IUpperBoundsDelta { + + private ITypeReferenceDelta<?> firstUpperBoundDelta; + private Set<ITypeReferenceDelta<?>> remainingUpperBoundDeltas; + + public SigUpperBoundsDelta(List<ITypeReference> from, + List<ITypeReference> to) { + super(from, to); + } + + + public ITypeReferenceDelta<?> getFirstUpperBoundDelta() { + return firstUpperBoundDelta; + } + + public void setFirstUpperBoundDelta( + ITypeReferenceDelta<?> firstUpperBoundDelta) { + this.firstUpperBoundDelta = firstUpperBoundDelta; + } + + public Set<ITypeReferenceDelta<?>> getRemainingUpperBoundDeltas() { + return remainingUpperBoundDeltas; + } + + public void setRemainingUpperBoundDeltas( + Set<ITypeReferenceDelta<?>> remainingUpperBoundDeltas) { + this.remainingUpperBoundDeltas = remainingUpperBoundDeltas; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java new file mode 100644 index 00000000000..9521f0e2786 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.IValueDelta; + +public class SigValueDelta extends SigDelta<Object> implements IValueDelta { + + public SigValueDelta(Object from, Object to) { + super(from, to); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java new file mode 100644 index 00000000000..e6cafcba33f --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.impl; + +import signature.compare.model.ITypeReferenceDelta; +import signature.compare.model.IUpperBoundsDelta; +import signature.compare.model.IWildcardTypeDelta; +import signature.model.IWildcardType; + +public class SigWildcardTypeDelta extends SigTypeDelta<IWildcardType> + implements IWildcardTypeDelta { + + private ITypeReferenceDelta<?> lowerBoundDelta; + private IUpperBoundsDelta upperBoundDelta; + + public SigWildcardTypeDelta(IWildcardType from, IWildcardType to) { + super(from, to); + } + + public ITypeReferenceDelta<?> getLowerBoundDelta() { + return lowerBoundDelta; + } + + public void setLowerBoundDelta(ITypeReferenceDelta<?> lowerBoundDelta) { + this.lowerBoundDelta = lowerBoundDelta; + } + + public IUpperBoundsDelta getUpperBoundDelta() { + return upperBoundDelta; + } + + public void setUpperBoundDelta(IUpperBoundsDelta upperBoundDelta) { + this.upperBoundDelta = upperBoundDelta; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java new file mode 100644 index 00000000000..428146e7ed8 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import java.util.Map; + +import signature.model.IArrayType; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.impl.SigArrayType; + +public class ArrayTypeProjection implements IArrayType { + + private final IArrayType original; + private final Map<ITypeVariableDefinition, ITypeReference> mappings; + + public ArrayTypeProjection(IArrayType original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public ITypeReference getComponentType() { + return ViewpointAdapter.substitutedTypeReference(original + .getComponentType(), mappings); + } + + @Override + public int hashCode() { + return SigArrayType.hashCode(this); + } + + @Override + public boolean equals(Object obj) { + return SigArrayType.equals(this, obj); + } + + @Override + public String toString() { + return "(" + SigArrayType.toString(this) + " : " + mappings + " )"; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java new file mode 100644 index 00000000000..630d1027401 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import signature.model.IAnnotation; +import signature.model.IAnnotationField; +import signature.model.IClassDefinition; +import signature.model.IConstructor; +import signature.model.IEnumConstant; +import signature.model.IField; +import signature.model.IMethod; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.impl.SigClassDefinition; + +public class ClassProjection implements IClassDefinition { + + private final IClassDefinition original; + private final Map<ITypeVariableDefinition, ITypeReference> substitutions; + + public ClassProjection(IClassDefinition original, + Map<ITypeVariableDefinition, ITypeReference> mapping) { + this.original = original; + this.substitutions = mapping; + } + + public Set<IAnnotationField> getAnnotationFields() { + throw new UnsupportedOperationException(); + } + + public Set<IAnnotation> getAnnotations() { + throw new UnsupportedOperationException(); + } + + public Set<IConstructor> getConstructors() { + throw new UnsupportedOperationException(); + } + + public IClassDefinition getDeclaringClass() { + throw new UnsupportedOperationException(); + } + + public Set<IEnumConstant> getEnumConstants() { + throw new UnsupportedOperationException(); + } + + public Set<IField> getFields() { + throw new UnsupportedOperationException(); + } + + public Set<IClassDefinition> getInnerClasses() { + throw new UnsupportedOperationException(); + } + + Set<ITypeReference> interfaces = null; + + public Set<ITypeReference> getInterfaces() { + if (interfaces == null) { + Set<ITypeReference> originalInterfaces = original.getInterfaces(); + if (originalInterfaces == null) { + interfaces = Collections.emptySet(); + } else { + interfaces = new HashSet<ITypeReference>(); + for (ITypeReference interfaze : originalInterfaces) { + interfaces.add(ViewpointAdapter.substitutedTypeReference( + interfaze, substitutions)); + } + interfaces = Collections.unmodifiableSet(interfaces); + } + } + return interfaces; + } + + public Kind getKind() { + return original.getKind(); + } + + + Set<IMethod> methods = null; + + public Set<IMethod> getMethods() { + if (methods == null) { + Set<IMethod> originalMethods = original.getMethods(); + if (originalMethods == null) { + methods = Collections.emptySet(); + } else { + methods = new HashSet<IMethod>(); + for (IMethod m : original.getMethods()) { + methods.add(new MethodProjection(m, substitutions)); + } + methods = Collections.unmodifiableSet(methods); + } + } + return methods; + } + + public Set<Modifier> getModifiers() { + return original.getModifiers(); + } + + public String getName() { + return original.getName(); + } + + public List<String> getPackageFragments() { + return original.getPackageFragments(); + } + + public String getPackageName() { + return original.getPackageName(); + } + + public String getQualifiedName() { + return original.getQualifiedName(); + } + + private boolean superClassInit = false; + private ITypeReference superClass = null; + + public ITypeReference getSuperClass() { + if (!superClassInit) { + ITypeReference originalSuperClass = original.getSuperClass(); + if (originalSuperClass != null) { + superClass = ViewpointAdapter.substitutedTypeReference(original + .getSuperClass(), substitutions); + } + superClassInit = true; + } + return superClass; + } + + // Definitions of type variables are not substituted + public List<ITypeVariableDefinition> getTypeParameters() { + return original.getTypeParameters(); + } + + @Override + public int hashCode() { + return SigClassDefinition.hashCode(this); + } + + @Override + public boolean equals(Object obj) { + return SigClassDefinition.equals(this, obj); + } + + @Override + public String toString() { + return "(" + SigClassDefinition.toString(this) + " : " + substitutions + + " )"; + } + +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java new file mode 100644 index 00000000000..648ccf85f40 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.impl.SigClassReference; + +import java.util.Map; + +public class ClassReferenceProjection implements IClassReference { + + private final IClassReference original; + private final Map<ITypeVariableDefinition, ITypeReference> mappings; + + public ClassReferenceProjection(IClassReference original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public IClassDefinition getClassDefinition() { + return new ClassProjection(original.getClassDefinition(), mappings); + } + + @Override + public boolean equals(Object obj) { + return SigClassReference.equals(this, obj); + } + + @Override + public int hashCode() { + return SigClassReference.hashCode(this); + } + + @Override + public String toString() { + return "(" + SigClassReference.toString(this) + " : " + mappings + " )"; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java new file mode 100644 index 00000000000..1ffd61671f8 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IConstructor; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; + +import java.util.Map; + +public class ConstructorProjection extends ExecutableMemberProjection implements + IConstructor { + + public ConstructorProjection(IConstructor original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + super(original, mappings); + } + +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java new file mode 100644 index 00000000000..f96ac543fb1 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IAnnotation; +import signature.model.IClassDefinition; +import signature.model.IExecutableMember; +import signature.model.IParameter; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.Modifier; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public abstract class ExecutableMemberProjection implements IExecutableMember { + + private final IExecutableMember original; + private final Map<ITypeVariableDefinition, ITypeReference> mappings; + + public ExecutableMemberProjection(IExecutableMember original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public Set<IAnnotation> getAnnotations() { + return original.getAnnotations(); + } + + public IClassDefinition getDeclaringClass() { + throw new UnsupportedOperationException(); + } + + public Set<ITypeReference> getExceptions() { + return ViewpointAdapter.substitutedTypeReferences(original + .getExceptions(), mappings); + } + + public Set<Modifier> getModifiers() { + return original.getModifiers(); + } + + public String getName() { + return original.getName(); + } + + public List<IParameter> getParameters() { + List<IParameter> result = new LinkedList<IParameter>(); + for (IParameter parameter : original.getParameters()) { + result.add(new ParameterProjection(parameter, mappings)); + } + return result; + } + + public List<ITypeVariableDefinition> getTypeParameters() { + // FIXME bounds need to be substituted ? + return original.getTypeParameters(); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java b/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java new file mode 100644 index 00000000000..c98fb09bd53 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IMethod; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.impl.SigMethod; + +import java.util.Map; + +public class MethodProjection extends ExecutableMemberProjection implements + IMethod { + + private final IMethod original; + private Map<ITypeVariableDefinition, ITypeReference> mappings; + + public MethodProjection(IMethod original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + super(original, mappings); + this.mappings = mappings; + this.original = original; + } + + public ITypeReference getReturnType() { + return ViewpointAdapter.substitutedTypeReference(original + .getReturnType(), mappings); + } + + @Override + public String toString() { + return "(" + SigMethod.toString(this) + " : " + mappings + " )"; + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java new file mode 100644 index 00000000000..9c48ab7d032 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IAnnotation; +import signature.model.IParameter; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; + +import java.util.Map; +import java.util.Set; + +public class ParameterProjection implements IParameter { + private IParameter original; + private Map<ITypeVariableDefinition, ITypeReference> mappings; + + public ParameterProjection(IParameter original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public Set<IAnnotation> getAnnotations() { + return original.getAnnotations(); + } + + public ITypeReference getType() { + return ViewpointAdapter.substitutedTypeReference(original.getType(), + mappings); + } + + @Override + public String toString() { + return getType().toString(); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java new file mode 100644 index 00000000000..59836db1ea7 --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IClassReference; +import signature.model.IParameterizedType; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.impl.SigParameterizedType; + +import java.util.List; +import java.util.Map; + +public class ParameterizedTypeProjection implements IParameterizedType { + + private final IParameterizedType original; + + private final Map<ITypeVariableDefinition, ITypeReference> mappings; + + public ParameterizedTypeProjection(IParameterizedType original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public ITypeReference getOwnerType() { + ITypeReference ownerType = original.getOwnerType(); + if (ownerType == null) { + return null; + } + return ViewpointAdapter.substitutedTypeReference(ownerType, mappings); + } + + private IClassReference rawType = null; + + /** + * Returns the raw type with substituted type variables. + * + * @return the raw type with substituted type variables + */ + public IClassReference getRawType() { + if (rawType == null) { + rawType = (IClassReference) ViewpointAdapter + .substitutedTypeReference(original.getRawType(), + ViewpointAdapter.createTypeMapping(this, original + .getRawType().getClassDefinition())); + } + return rawType; + } + + private List<ITypeReference> arguments = null; + + public List<ITypeReference> getTypeArguments() { + if (arguments == null) { + arguments = ViewpointAdapter.substitutedTypeReferences(original + .getTypeArguments(), mappings); + } + return arguments; + } + + @Override + public int hashCode() { + return SigParameterizedType.hashCode(this); + } + + @Override + public boolean equals(Object obj) { + return SigParameterizedType.equals(this, obj); + } + + @Override + public String toString() { + return SigParameterizedType.toString(this); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java b/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java new file mode 100644 index 00000000000..88f457fc6ba --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.IArrayType; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IParameterizedType; +import signature.model.IPrimitiveType; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; +import signature.model.IWildcardType; +import signature.model.impl.SigClassReference; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ViewpointAdapter { + + static Map<ITypeVariableDefinition, ITypeReference> createTypeMapping( + IParameterizedType paramameterizedType, + IClassDefinition parameterizedTypeDefinition) { + List<ITypeVariableDefinition> typeParameters = + parameterizedTypeDefinition.getTypeParameters(); + List<ITypeReference> actualTypeArguments = paramameterizedType + .getTypeArguments(); + if (actualTypeArguments == null || typeParameters == null) { + return Collections.emptyMap(); + } + Map<ITypeVariableDefinition, ITypeReference> substitution = + new HashMap<ITypeVariableDefinition, ITypeReference>(); + Iterator<ITypeVariableDefinition> paramsIterator = typeParameters + .iterator(); + Iterator<ITypeReference> argumentsIterator = actualTypeArguments + .iterator(); + while (paramsIterator.hasNext() && argumentsIterator.hasNext()) { + substitution.put(paramsIterator.next(), argumentsIterator.next()); + } + return substitution; + } + + public static Set<ITypeReference> substitutedTypeReferences( + Set<ITypeReference> original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + List<ITypeReference> result = new ArrayList<ITypeReference>(original); + return new HashSet<ITypeReference>(substitutedTypeReferences(result, + mappings)); + } + + public static List<ITypeReference> substitutedTypeReferences( + List<ITypeReference> original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + List<ITypeReference> result = new ArrayList<ITypeReference>(original + .size()); + for (ITypeReference typeReference : original) { + result.add(substitutedTypeReference(typeReference, mappings)); + } + return result; + } + + public static ITypeReference substitutedTypeReference( + ITypeReference original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + ITypeReference type = original; + if (type instanceof IClassReference) { + return new ClassReferenceProjection((IClassReference) original, + mappings); + } else if (type instanceof IPrimitiveType) { + return type; + } else if (type instanceof IArrayType) { + return new ArrayTypeProjection((IArrayType) type, mappings); + } else if (type instanceof IParameterizedType) { + return new ParameterizedTypeProjection((IParameterizedType) type, + mappings); + } else if (type instanceof IWildcardType) { + return new WildcardTypeProjection((IWildcardType) type, mappings); + } else if (type instanceof ITypeVariableReference) { + // here happens the substitution + ITypeReference subst = mappings.get(((ITypeVariableReference) type) + .getTypeVariableDefinition()); + return subst != null ? subst : type; + } + throw new IllegalStateException(); + } + + public static IClassReference getReferenceTo(IClassDefinition definition) { + return new SigClassReference(new ClassProjection(definition, + new HashMap<ITypeVariableDefinition, ITypeReference>())); + } +} diff --git a/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java new file mode 100644 index 00000000000..a59873cdb0a --- /dev/null +++ b/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.compare.model.subst; + +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.IWildcardType; +import signature.model.impl.SigWildcardType; + +import java.util.List; +import java.util.Map; + +public class WildcardTypeProjection implements IWildcardType { + + private final IWildcardType original; + + private final Map<ITypeVariableDefinition, ITypeReference> mappings; + + public WildcardTypeProjection(IWildcardType original, + Map<ITypeVariableDefinition, ITypeReference> mappings) { + this.original = original; + this.mappings = mappings; + } + + public ITypeReference getLowerBound() { + return ViewpointAdapter.substitutedTypeReference(original + .getLowerBound(), mappings); + } + + public List<ITypeReference> getUpperBounds() { + return ViewpointAdapter.substitutedTypeReferences(original + .getUpperBounds(), mappings); + } + + @Override + public int hashCode() { + return SigWildcardType.hashCode(this); + } + + @Override + public boolean equals(Object obj) { + return SigWildcardType.equals(this, obj); + } + + @Override + public String toString() { + return SigWildcardType.toString(this); + } +} diff --git a/tools/signature-tools/src/signature/converter/Main.java b/tools/signature-tools/src/signature/converter/Main.java new file mode 100644 index 00000000000..f426877272d --- /dev/null +++ b/tools/signature-tools/src/signature/converter/Main.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import signature.UsageException; +import signature.converter.dex.DexFactory; +import signature.converter.doclet.DocletFactory; +import signature.io.IApiLoader; +import signature.io.IApiExternalizer; +import signature.io.impl.BinaryApi; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +public class Main { + // (doclet | dex) sourcefiles --out file --name name --packages packageName{ + // packageName}" + + public static void main(String[] args) throws IOException { + String type = args[0]; + Set<String> sources = new HashSet<String>(); + int at = 1; + for (/* at */; at < args.length; at++) { + if ("--out".equals(args[at])) { + break; + } + sources.add(args[at]); + } + + if (!"--out".equals(args[at])) { + throw new UsageException(); + } + String targetFile = args[++at]; + + if (!"--name".equals(args[++at])) { + throw new UsageException(); + } + String name = args[++at]; + + if (!"--packages".equals(args[++at])) { + throw new UsageException(); + } + Set<String> packages = new HashSet<String>(); + ++at; + for (/* at */; at < args.length; at++) { + packages.add(args[at]); + } + + IApiExternalizer externalizer = new BinaryApi(); + IApiLoader factory = null; + + if ("doclet".equals(type)) { + factory = new DocletFactory(); + } else if ("dex".equals(type)) { + factory = new DexFactory(); + } else { + throw new UsageException(); + } + + externalizer.externalizeApi(targetFile, factory.loadApi(name, + Visibility.PROTECTED, sources, packages)); + } +} diff --git a/tools/signature-tools/src/signature/converter/Visibility.java b/tools/signature-tools/src/signature/converter/Visibility.java new file mode 100644 index 00000000000..653c61798d3 --- /dev/null +++ b/tools/signature-tools/src/signature/converter/Visibility.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +/** + * This enum defines which members are part of the API. + * + * <ul> + * <li><code>PUBLIC</code> only the public classes and members are included. + * <li><code>PROTECTED</code> the public and protected classes members are + * included. + * <li><code>PACKAGE</code> the public, protected and package visible classes + * and members are included. + * <li><code>PRIVATE</code> all classes and members are included. + * </ul> + * <p> + * The default visibility mode is <code>PROTECTED</code>. + * + */ +public enum Visibility { + PUBLIC, PROTECTED, PACKAGE, PRIVATE; +} diff --git a/tools/signature-tools/src/signature/converter/dex/DexFactory.java b/tools/signature-tools/src/signature/converter/dex/DexFactory.java new file mode 100644 index 00000000000..b7cc00ea1d5 --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/DexFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import dex.structure.DexFile; +import signature.converter.Visibility; +import signature.io.IApiLoader; +import signature.model.IApi; +import signature.model.IPackage; +import signature.model.impl.SigApi; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Set; + +public class DexFactory implements IApiLoader { + + public IApi loadApi(String name, Visibility visibility, + Set<String> fileNames, Set<String> packageNames) throws + IOException { + DexToSigConverter converter = new DexToSigConverter(); + Set<DexFile> files = DexUtil.getDexFiles(fileNames); + SigApi api = converter.convertApi(name, files, visibility); + + Iterator<IPackage> it = api.getPackages().iterator(); + while (it.hasNext()) { + IPackage aPackage = it.next(); + boolean found = false; + for (String packageName : packageNames) { + if (aPackage.getName().equals(packageName)) { + found = true; + } + } + if (!found) { + it.remove(); + } + } + return api; + } +} diff --git a/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java b/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java new file mode 100644 index 00000000000..13312bdbf2c --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java @@ -0,0 +1,938 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import static signature.converter.dex.DexUtil.convertAnyWay; +import static signature.converter.dex.DexUtil.declaresExceptions; +import static signature.converter.dex.DexUtil.declaresMemberClasses; +import static signature.converter.dex.DexUtil.findPackageInfo; +import static signature.converter.dex.DexUtil.getClassModifiers; +import static signature.converter.dex.DexUtil.getClassName; +import static signature.converter.dex.DexUtil.getDefaultMappingsAnnotation; +import static signature.converter.dex.DexUtil.getDexName; +import static signature.converter.dex.DexUtil.getEnclosingClassName; +import static signature.converter.dex.DexUtil.getExceptionSignature; +import static signature.converter.dex.DexUtil.getGenericSignature; +import static signature.converter.dex.DexUtil.getKind; +import static signature.converter.dex.DexUtil.getMemberClassNames; +import static signature.converter.dex.DexUtil.getModifier; +import static signature.converter.dex.DexUtil.getPackageName; +import static signature.converter.dex.DexUtil.getQualifiedName; +import static signature.converter.dex.DexUtil.hasAnnotationDefaultSignature; +import static signature.converter.dex.DexUtil.hasGenericSignature; +import static signature.converter.dex.DexUtil.isAnnotation; +import static signature.converter.dex.DexUtil.isConstructor; +import static signature.converter.dex.DexUtil.isEnclosingClass; +import static signature.converter.dex.DexUtil.isEnum; +import static signature.converter.dex.DexUtil.isInternalAnnotation; +import static signature.converter.dex.DexUtil.isJavaLangObject; +import static signature.converter.dex.DexUtil.isMethod; +import static signature.converter.dex.DexUtil.isVisible; +import static signature.converter.dex.DexUtil.splitTypeList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IAnnotation; +import signature.model.IAnnotationElement; +import signature.model.IAnnotationField; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IConstructor; +import signature.model.IEnumConstant; +import signature.model.IField; +import signature.model.IMethod; +import signature.model.IPackage; +import signature.model.IParameter; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.impl.SigAnnotation; +import signature.model.impl.SigAnnotationElement; +import signature.model.impl.SigAnnotationField; +import signature.model.impl.SigApi; +import signature.model.impl.SigClassDefinition; +import signature.model.impl.SigClassReference; +import signature.model.impl.SigConstructor; +import signature.model.impl.SigEnumConstant; +import signature.model.impl.SigExecutableMember; +import signature.model.impl.SigField; +import signature.model.impl.SigMethod; +import signature.model.impl.SigPackage; +import signature.model.impl.SigParameter; +import signature.model.impl.Uninitialized; +import signature.model.util.TypePool; +import dex.structure.DexAnnotation; +import dex.structure.DexAnnotationAttribute; +import dex.structure.DexClass; +import dex.structure.DexEncodedAnnotation; +import dex.structure.DexEncodedValue; +import dex.structure.DexField; +import dex.structure.DexFile; +import dex.structure.DexMethod; +import dex.structure.DexParameter; + +/** + * Converts a set of dex files to the signature compare api. + */ +public final class DexToSigConverter implements IClassInitializer { + + private final FieldPool elementPool; + private final TypePool factory; + private static final Set<IField> EMPTY_FIELDS = Collections.emptySet(); + private static final Set<IEnumConstant> EMPTY_ENUM_CONSTANTS = Collections + .emptySet(); + private static final Set<IAnnotationField> EMPTY_ANNOTATION_FIELDS = + Collections.emptySet(); + private static final List<ITypeVariableDefinition> EMPTY_TYPE_VARIABLES = + Collections.emptyList(); + private static final Set<IClassDefinition> EMPTY_INNER_CLASSES = + Collections.emptySet(); + private static final Set<ITypeReference> EMPTY_EXCEPTIONS = Collections + .emptySet(); + private Visibility visibility; + private Map<String, DexClass> dexNameToDexClass; + + + /** + * Creates a new instance of {@link DexToSigConverter}. + */ + public DexToSigConverter() { + factory = new TypePool(); + elementPool = new FieldPool(); + } + + + public SigApi convertApi(String apiName, Set<DexFile> dexFiles, + Visibility visibility) { + this.visibility = visibility; + SigApi api = new SigApi(apiName, visibility); + api.setPackages(convertPackages(dexFiles)); + factory.replaceAllUninitialiezWithNull(); + return api; + } + + /** + * Converts the given {@link DexFile}s into the corresponding (packages + * including their (classes and their members, etc.))E + * + * @param parsedFiles + * the dex files to convert + * @return the converted packages + */ + /* package */Set<IPackage> convertPackages(Set<DexFile> parsedFiles) { + Map<String, SigPackage> packageNameToPackage = + new HashMap<String, SigPackage>(); + Map<SigPackage, Set<DexClass>> packageToDexClasses = + new HashMap<SigPackage, Set<DexClass>>(); + + dexNameToDexClass = new HashMap<String, DexClass>(); + + for (DexFile dexFile : parsedFiles) { + List<DexClass> definedClasses = dexFile.getDefinedClasses(); + for (DexClass dexClass : definedClasses) { + + dexNameToDexClass.put(dexClass.getName(), dexClass); + + String dexName = dexClass.getName(); + String packageName = getPackageName(dexName); + SigPackage aPackage = packageNameToPackage.get(packageName); + if (aPackage == null) { + aPackage = convertPackage(packageName); + packageNameToPackage.put(packageName, aPackage); + + Set<DexClass> classes = new HashSet<DexClass>(); + packageToDexClasses.put(aPackage, classes); + } + Set<DexClass> classes = packageToDexClasses.get(aPackage); + classes.add(dexClass); + } + } + + Set<SigClassDefinition> allClasses = new HashSet<SigClassDefinition>(); + + for (SigPackage aPackage : packageToDexClasses.keySet()) { + Set<SigClassDefinition> classes = convertClasses(packageToDexClasses + .get(aPackage)); + allClasses.addAll(classes); + aPackage.setClasses(new HashSet<IClassDefinition>(classes)); + } + + // remove package info + for (SigPackage aPackage : packageToDexClasses.keySet()) { + IClassDefinition packageInfo = findPackageInfo(aPackage); + if (packageInfo != null) { + aPackage.setAnnotations(packageInfo.getAnnotations()); + aPackage.getClasses().remove(packageInfo); + } + } + + // link enclosed classes only if they are part of visible api + for (SigClassDefinition sigClass : allClasses) { + String dexName = getDexName(sigClass); + DexClass dexClass = dexNameToDexClass.get(dexName); + + if (declaresMemberClasses(dexClass)) { + Set<String> enclosedClassesNames = + getMemberClassNames(dexClass); + Set<IClassDefinition> memberClasses = + new HashSet<IClassDefinition>(); + for (String enclosedClassName : enclosedClassesNames) { + SigClassDefinition memberClass = factory.getClass( + getPackageName(enclosedClassName), + getClassName(enclosedClassName)); + // add inner class only if parsed + if (allClasses.contains(memberClass)) { + memberClasses.add(memberClass); + } + } + sigClass.setInnerClasses(memberClasses); + } else { + sigClass.setInnerClasses(EMPTY_INNER_CLASSES); + } + } + + // remove inner classes, is outer class is not visible + for (SigClassDefinition sigClass : allClasses) { + if (hasInvisibleParent(sigClass, dexNameToDexClass)) { + SigPackage sigPackage = packageNameToPackage.get(sigClass + .getPackageName()); + sigPackage.getClasses().remove(sigClass); + } + } + return new HashSet<IPackage>(packageToDexClasses.keySet()); + } + + private boolean hasInvisibleParent(IClassDefinition sigClass, + Map<String, DexClass> dexNameToDexClass) { + + do { + String dexName = getDexName(sigClass); + DexClass dexClass = dexNameToDexClass.get(dexName); + if (isEnclosingClass(dexClass)) { + IClassDefinition declaringClass = sigClass.getDeclaringClass(); + DexClass declaringDexClass = dexNameToDexClass + .get(getDexName(declaringClass)); + if (!isVisible(declaringDexClass, visibility)) { + return true; + } + } + } while ((sigClass = sigClass.getDeclaringClass()) != null); + return false; + } + + /** + * Converts a simple string to the corresponding {@link SigPackage}.<br> + * Format: "a.b.c" + * + * @param packageName + * the name of the package + * @return the package + */ + protected SigPackage convertPackage(String packageName) { + SigPackage sigPackage = new SigPackage(packageName); + return sigPackage; + } + + /** + * Converts a set of {@link DexClass} objects to a set of the corresponding + * {@link SigClassDefinition} objects. + * + * @param dexClasses + * the {@link DexClass} objects + * @return a set of {@link DexClass} objects + */ + protected Set<SigClassDefinition> convertClasses(Set<DexClass> dexClasses) { + Set<SigClassDefinition> classes = new HashSet<SigClassDefinition>(); + for (DexClass dexClass : dexClasses) { + // convert all classes but synthetic, return only initialized + if (convertAnyWay(dexClass)) { + SigClassDefinition sigCLass = convertClass(dexClass); + if (isVisible(dexClass, visibility)) { + classes.add(sigCLass); + } + } + } + return classes; + } + + /** + * Converts a {@link DexClass} to the corresponding + * {@link SigClassDefinition}. + * + * @param dexClass + * the {@link DexClass} to convert + * @return the corresponding {@link SigClassDefinition} + */ + protected SigClassDefinition convertClass(DexClass dexClass) { + assert dexClass != null; + + String packageName = getPackageName(dexClass.getName()); + String className = getClassName(dexClass.getName()); + SigClassDefinition sigClass = factory.getClass(packageName, className); + // Kind + sigClass.setKind(getKind(dexClass)); + // modifiers + Set<Modifier> modifiers = getModifier(getClassModifiers(dexClass)); + sigClass.setModifiers(modifiers); + + if (isEnclosingClass(dexClass)) { + String declaringClassDexName = getEnclosingClassName(dexClass); + declaringClassDexName = getClassName(declaringClassDexName); + // declaring class is in same package + sigClass.setDeclaringClass(factory.getClass(sigClass + .getPackageName(), declaringClassDexName)); + } else { + sigClass.setDeclaringClass(null); + } + + if (hasGenericSignature(dexClass)) { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + parser.parseForClass(sigClass, getGenericSignature(dexClass)); + sigClass.setTypeParameters(parser.formalTypeParameters); + + if (Kind.INTERFACE.equals(sigClass.getKind())) { + sigClass.setSuperClass(null); + } else { + sigClass.setSuperClass(parser.superclassType); + } + + sigClass.setInterfaces(new HashSet<ITypeReference>( + parser.interfaceTypes)); + } else { + + // Type parameters + sigClass.setTypeParameters(EMPTY_TYPE_VARIABLES); + + // java.lang.Object has no super class + if (isJavaLangObject(dexClass)) { + sigClass.setSuperClass(null); + } else { + + if (Kind.INTERFACE.equals(sigClass.getKind()) + || Kind.ANNOTATION.equals(sigClass.getKind())) { + sigClass.setSuperClass(null); + } else { + String superClassPackageName = getPackageName(dexClass + .getSuperClass()); + String superClassName = getClassName(dexClass + .getSuperClass()); + sigClass.setSuperClass(factory.getClassReference( + superClassPackageName, superClassName)); + } + } + + List<String> interfaceDexNames = dexClass.getInterfaces(); + Set<ITypeReference> interfaces = new HashSet<ITypeReference>(); + for (String interfaceDexName : interfaceDexNames) { + String interfacePackageName = getPackageName(interfaceDexName); + String interfaceName = getClassName(interfaceDexName); + SigClassDefinition interfaze = factory.getClass( + interfacePackageName, interfaceName); + interfaze.setKind(Kind.INTERFACE); + interfaces.add(new SigClassReference(interfaze)); + } + sigClass.setInterfaces(interfaces); + } + + // constructors + Set<SigConstructor> constructors = convertConstructors(dexClass + .getMethods()); + for (SigConstructor constructor : constructors) { + constructor.setDeclaringClass(sigClass); + } + sigClass.setConstructors(new HashSet<IConstructor>(constructors)); + + // methods + Set<SigMethod> methods = Collections.emptySet(); + + + if (isAnnotation(dexClass)) { + Map<String, Object> mappings = getDefaultValueMapping(dexClass); + Set<SigAnnotationField> annotationFields = convertAnnotationFields( + dexClass.getMethods(), mappings); + sigClass.setAnnotationFields(new HashSet<IAnnotationField>( + annotationFields)); + addAnnotationsToAnnotationFields(dexClass.getMethods(), + annotationFields); + + sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS); + sigClass.setFields(EMPTY_FIELDS); + + // sigClass.setAnnotationFields(new + // HashSet<IAnnotationField>(convertAnnotationFields(dexClass))); + } else if (isEnum(dexClass)) { + Set<IField> fields = new HashSet<IField>(); + Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>(); + + for (DexField dexField : dexClass.getFields()) { + if (isVisible(dexField, visibility)) { + if (dexField.isEnumConstant()) { + enumConstants.add(convertEnumConstant(dexField)); + } else { + fields.add(convertField(dexField)); + } + } + } + + sigClass.setFields(fields); + sigClass.setEnumConstants(enumConstants); + sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS); + methods = convertMethods(dexClass.getMethods()); + } else { + // fields + sigClass.setFields(new HashSet<IField>(convertFields(dexClass + .getFields()))); + sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS); + sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS); + methods = convertMethods(dexClass.getMethods()); + } + + for (SigMethod method : methods) { + method.setDeclaringClass(sigClass); + } + sigClass.setMethods(new HashSet<IMethod>(methods)); + + // Annotations + sigClass.setAnnotations(convertAnnotations(dexClass.getAnnotations())); + + return sigClass; + } + + @SuppressWarnings("unchecked") + private Map<String, Object> getDefaultValueMapping(DexClass dexClass) { + HashMap<String, Object> mappings = new HashMap<String, Object>(); + if (hasAnnotationDefaultSignature(dexClass)) { + // read mapping to defaults from annotation + DexAnnotation annotation = getDefaultMappingsAnnotation(dexClass); + DexAnnotationAttribute dexAnnotationAttribute = annotation + .getAttributes().get(0); + if ("value".equals(dexAnnotationAttribute.getName())) { + DexEncodedValue encodedValue = dexAnnotationAttribute + .getEncodedValue(); + DexEncodedValue value = (DexEncodedValue) encodedValue + .getValue(); + List<DexAnnotationAttribute> defaults = + (List<DexAnnotationAttribute>) value.getValue(); + for (DexAnnotationAttribute defaultAttribute : defaults) { + mappings.put(defaultAttribute.getName(), + convertEncodedValue(defaultAttribute + .getEncodedValue())); + } + } + } + return mappings; + } + + + private void addAnnotationsToAnnotationFields(List<DexMethod> methods, + Set<SigAnnotationField> annotationFields) { + Map<String, SigAnnotationField> nameToAnnotationField = + new HashMap<String, SigAnnotationField>(); + + for (SigAnnotationField annotationField : annotationFields) { + nameToAnnotationField.put(annotationField.getName(), + annotationField); + } + + for (DexMethod method : methods) { + SigAnnotationField annotationField = nameToAnnotationField + .get(method.getName()); + annotationField.setAnnotations(convertAnnotations(method + .getAnnotations())); + } + } + + + private Set<SigAnnotationField> convertAnnotationFields( + List<DexMethod> list, Map<String, Object> mappings) { + Set<SigAnnotationField> annotationfields = + new HashSet<SigAnnotationField>(); + for (DexMethod dexMethod : list) { + if (isVisible(dexMethod, visibility)) { + annotationfields.add(convertAnnotationField(dexMethod, mappings + .get(dexMethod.getName()))); + } + } + return annotationfields; + } + + private SigAnnotationField convertAnnotationField(DexMethod dexMethod, + Object defaultValue) { + SigAnnotationField annotationField = new SigAnnotationField(dexMethod + .getName()); + annotationField.setDefaultValue(defaultValue); + annotationField.setModifiers(getModifier(dexMethod.getModifiers())); + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + annotationField.setType(parser.parseNonGenericType(dexMethod + .getReturnType())); + return annotationField; + } + + private IEnumConstant convertEnumConstant(DexField dexField) { + String qualifiedTypeName = getQualifiedName(dexField + .getDeclaringClass().getName()); + SigEnumConstant enumConstant = elementPool.getEnumConstant( + qualifiedTypeName, dexField.getName()); + Set<Modifier> modifiers = getModifier(dexField.getModifiers()); + modifiers.add(Modifier.STATIC); + enumConstant.setModifiers(modifiers); + + String typePackageName = getPackageName(dexField.getType()); + String typeName = getClassName(dexField.getType()); + enumConstant.setType(factory.getClassReference(typePackageName, + typeName)); + enumConstant.setAnnotations(convertAnnotations(dexField + .getAnnotations())); + return enumConstant; + } + + private Set<SigField> convertFields(List<DexField> dexFields) { + Set<SigField> fields = new HashSet<SigField>(); + for (DexField dexField : dexFields) { + if (isVisible(dexField, visibility)) { + fields.add(convertField(dexField)); + } + } + return fields; + } + + private SigField convertField(DexField dexField) { + String qualTypeName = getQualifiedName(dexField.getDeclaringClass() + .getName()); + SigField field = elementPool.getField(qualTypeName, dexField.getName()); + + field.setModifiers(getModifier(dexField.getModifiers())); + + field.setAnnotations(convertAnnotations(dexField.getAnnotations())); + + if (hasGenericSignature(dexField)) { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + String declaringClassPackageName = getPackageName(dexField + .getDeclaringClass().getName()); + String declaringClassName = getClassName(dexField + .getDeclaringClass().getName()); + + parser.parseForField(factory.getClass(declaringClassPackageName, + declaringClassName), getGenericSignature(dexField)); + field.setType(parser.fieldType); + } else { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + field.setType(parser.parseNonGenericType(dexField.getType())); + } + + return field; + } + + /** + * Converts a set of {@link DexMethod} to a set of corresponding + * {@link IConstructor}. This method ignores methods which are not + * constructors. + * + * @param methods + * the {@link DexMethod}s to convert + * @return the corresponding {@link IConstructor}s + */ + private Set<SigConstructor> convertConstructors(List<DexMethod> methods) { + Set<SigConstructor> constructors = new HashSet<SigConstructor>(); + for (DexMethod method : methods) { + if (isConstructor(method) && isVisible(method, visibility)) { + constructors.add(convertConstructor(method)); + } + } + return constructors; + } + + /** + * Converts a set of {@link DexMethod} to a set of corresponding + * {@link DexMethod}. This method ignores methods which are constructors. + * + * @param methods + * the {@link DexMethod}s to convert + * @return the corresponding {@link IConstructor}s + */ + private Set<SigMethod> convertMethods(List<DexMethod> methods) { + Set<SigMethod> sigMethods = new HashSet<SigMethod>(); + for (DexMethod method : methods) { + if (isMethod(method) && isVisible(method, visibility)) { + sigMethods.add(convertMethod(method)); + } + } + return sigMethods; + } + + /** + * Converts a dexMethod which must be a constructor to the corresponding + * {@link SigConstructor} instance. + * + * @param dexMethod + * the dex constructor to convert + * @return the corresponding {@link SigConstructor} + */ + public SigConstructor convertConstructor(DexMethod dexMethod) { + String declaringClassName = getClassName(dexMethod.getDeclaringClass() + .getName()); + + SigConstructor constructor = new SigConstructor(declaringClassName); + constructor.setModifiers(getModifier(dexMethod.getModifiers())); + String declaringClassPackageName = getPackageName(dexMethod + .getDeclaringClass().getName()); + + + SigClassDefinition declaringClass = factory.getClass( + declaringClassPackageName, declaringClassName); + constructor.setDeclaringClass(declaringClass); + + // Annotations + constructor.setAnnotations(convertAnnotations(dexMethod + .getAnnotations())); + + if (hasGenericSignature(dexMethod)) { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + parser.parseForConstructor(constructor, + getGenericSignature(dexMethod)); + + // type parameters + constructor.setTypeParameters(parser.formalTypeParameters); + + // parameters + // generic parameter types parameters + List<DexParameter> dexParameters = dexMethod.getParameters(); + List<IParameter> parameters = new ArrayList<IParameter>( + parser.parameterTypes.size()); + Iterator<DexParameter> iterator = dexParameters.iterator(); + for (ITypeReference parameterType : parser.parameterTypes) { + SigParameter parameter = new SigParameter(parameterType); + iterator.hasNext(); + DexParameter dexParam = iterator.next(); + parameter.setAnnotations(convertAnnotations(dexParam + .getAnnotations())); + parameters.add(parameter); + } + + constructor.setParameters(parameters); + + // exceptions + constructor.setExceptions(new HashSet<ITypeReference>( + parser.exceptionTypes)); + + } else { + convertNonGenericExecutableMember(constructor, dexMethod); + + // remove first parameter of non static inner class constructors + // implicit outer.this reference + if (declaringClass.getDeclaringClass() != null) { + if (!declaringClass.getModifiers().contains(Modifier.STATIC)) { + if (constructor.getParameters().isEmpty()) { + throw new IllegalStateException( + "Expected at least one parameter!"); + } + IParameter first = constructor.getParameters().remove(0); + String enclosingName = declaringClass.getDeclaringClass() + .getName(); + String firstParameterTypeName = ((IClassReference) first + .getType()).getClassDefinition().getName(); + if (!enclosingName.equals(firstParameterTypeName)) + throw new IllegalStateException( + "Expected first constructor parameter of type " + + enclosingName); + } + } + } + + addExceptions(constructor, dexMethod); + return constructor; + } + + public SigMethod convertMethod(DexMethod dexMethod) { + SigMethod method = new SigMethod(dexMethod.getName()); + method.setModifiers(getModifier(dexMethod.getModifiers())); + + String declaringClassPackageName = getPackageName(dexMethod + .getDeclaringClass().getName()); + String declaringClassName = getClassName(dexMethod.getDeclaringClass() + .getName()); + + method.setDeclaringClass(factory.getClass(declaringClassPackageName, + declaringClassName)); + + // Annotations + method.setAnnotations(convertAnnotations(dexMethod.getAnnotations())); + + if (hasGenericSignature(dexMethod)) { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + parser.parseForMethod(method, getGenericSignature(dexMethod)); + + // type parameters + method.setTypeParameters(parser.formalTypeParameters); + + // generic parameter types parameters + List<DexParameter> dexParameters = dexMethod.getParameters(); + List<IParameter> parameters = new ArrayList<IParameter>( + parser.parameterTypes.size()); + Iterator<DexParameter> iterator = dexParameters.iterator(); + for (ITypeReference parameterType : parser.parameterTypes) { + SigParameter parameter = new SigParameter(parameterType); + iterator.hasNext(); + DexParameter dexParam = iterator.next(); + parameter.setAnnotations(convertAnnotations(dexParam + .getAnnotations())); + parameters.add(parameter); + } + method.setParameters(parameters); + + // exceptions + method.setExceptions(new HashSet<ITypeReference>( + parser.exceptionTypes)); + method.setReturnType(parser.returnType); + + } else { + convertNonGenericExecutableMember(method, dexMethod); + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + ITypeReference type = parser.parseNonGenericReturnType(dexMethod + .getReturnType()); + method.setReturnType(type); + } + addExceptions(method, dexMethod); + return method; + } + + private void addExceptions(SigExecutableMember member, + DexMethod dexMethod) { + if (declaresExceptions(dexMethod)) { + String exceptionSignature = getExceptionSignature(dexMethod); + Set<String> exceptionTypeNames = splitTypeList(exceptionSignature); + Set<ITypeReference> exceptions = new HashSet<ITypeReference>(); + + for (String exTypeName : exceptionTypeNames) { + String packageName = getPackageName(exTypeName); + String className = getClassName(exTypeName); + exceptions.add(factory + .getClassReference(packageName, className)); + } + member.setExceptions(exceptions); + } else { + member.setExceptions(EMPTY_EXCEPTIONS); + } + } + + private void convertNonGenericExecutableMember(SigExecutableMember member, + DexMethod dexMethod) { + List<DexParameter> dexParameters = dexMethod.getParameters(); + List<IParameter> parameters = new ArrayList<IParameter>(dexParameters + .size()); + + for (DexParameter dexParameter : dexParameters) { + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + ITypeReference type = parser.parseNonGenericType(dexParameter + .getTypeName()); + SigParameter parameter = new SigParameter(type); + parameters.add(parameter); + // Annotations + parameter.setAnnotations(convertAnnotations(dexParameter + .getAnnotations())); + } + member.setParameters(parameters); + + member.setTypeParameters(EMPTY_TYPE_VARIABLES); + + // if (declaresExceptions(dexMethod)) { + // String exceptionSignature = getExceptionSignature(dexMethod); + // Set<String> exceptionTypeNames = splitTypeList(exceptionSignature); + // Set<IType> exceptions = new HashSet<IType>(); + // + // for (String exTypeName : exceptionTypeNames) { + // String packageName = getPackageName(exTypeName); + // String className = getClassName(exTypeName); + // exceptions.add(factory.getClass(packageName, className)); + // } + // member.setExceptions(exceptions); + // } else { + // member.setExceptions(EMPTY_EXCEPTIONS); + // } + } + + /** + * Converts a set of {@link DexAnnotation} to a set of corresponding + * {@link SigAnnotation}. + * + * @param dexAnnotations + * the {@link DexAnnotation}s to convert + * @return the corresponding {@link SigAnnotation}s + */ + private Set<IAnnotation> convertAnnotations( + Set<DexAnnotation> dexAnnotations) { + Set<IAnnotation> annotations = new HashSet<IAnnotation>(); + for (DexAnnotation dexAnnotation : dexAnnotations) { + if (!isInternalAnnotation(dexAnnotation)) { + annotations.add(convertAnnotation(dexAnnotation)); + } + } + return annotations; + } + + /** + * Converts a {@link DexAnnotation} to the corresponding + * {@link SigAnnotation}. + * + * @param dexAnnotation + * the {@link DexAnnotation} to convert + * @return the corresponding {@link SigAnnotation} + */ + protected SigAnnotation convertAnnotation(DexAnnotation dexAnnotation) { + SigAnnotation sigAnnotation = new SigAnnotation(); + String packageName = getPackageName(dexAnnotation.getTypeName()); + String className = getClassName(dexAnnotation.getTypeName()); + sigAnnotation + .setType(factory.getClassReference(packageName, className)); + sigAnnotation.setElements(convertAnnotationElements(dexAnnotation + .getAttributes())); + return sigAnnotation; + } + + private Set<IAnnotationElement> convertAnnotationElements( + List<DexAnnotationAttribute> attributes) { + Set<IAnnotationElement> annotationAttributes = + new HashSet<IAnnotationElement>(); + for (DexAnnotationAttribute dexAnnotationAttribute : attributes) { + annotationAttributes + .add(convertAnnotationAttribute(dexAnnotationAttribute)); + } + return annotationAttributes; + } + + private IAnnotationElement convertAnnotationAttribute( + DexAnnotationAttribute dexAnnotationAttribute) { + + SigAnnotationElement sigElement = new SigAnnotationElement(); + String nameOfField = dexAnnotationAttribute.getName(); + + + String typeName = dexAnnotationAttribute.getAnnotation().getTypeName(); + SigClassDefinition annotationClass = factory.getClass( + getPackageName(typeName), getClassName(typeName)); + if (!Uninitialized.isInitialized( + annotationClass.getAnnotationFields())) { + initializeClass(getPackageName(typeName), getClassName(typeName)); + } + for (IAnnotationField field : annotationClass.getAnnotationFields()) { + if (nameOfField.equals(field.getName())) { + sigElement.setDeclaringField(field); + } + } + + sigElement.setValue(convertEncodedValue(dexAnnotationAttribute + .getEncodedValue())); + return sigElement; + } + + @SuppressWarnings("unchecked") + private Object convertEncodedValue(DexEncodedValue dexEnodedValue) { + Object value = null; + switch (dexEnodedValue.getType()) { + case VALUE_INT: + case VALUE_BOOLEAN: + case VALUE_BYTE: + case VALUE_CHAR: + case VALUE_DOUBLE: + case VALUE_FLOAT: + case VALUE_LONG: + case VALUE_NULL: + case VALUE_STRING: + case VALUE_SHORT: + value = dexEnodedValue.getValue(); + break; + case VALUE_ARRAY: { + List<DexEncodedValue> dexValues = + (List<DexEncodedValue>) dexEnodedValue.getValue(); + Object[] arrayValues = new Object[dexValues.size()]; + int i = 0; + for (DexEncodedValue dexValue : dexValues) { + arrayValues[i++] = convertEncodedValue(dexValue); + } + value = arrayValues; + break; + } + case VALUE_ANNOTATION: { + DexEncodedAnnotation annotation = + (DexEncodedAnnotation) dexEnodedValue.getValue(); + SigAnnotation sigAnnotation = new SigAnnotation(); + String packageName = getPackageName(annotation.getTypeName()); + String className = getClassName(annotation.getTypeName()); + sigAnnotation.setType(factory.getClassReference(packageName, + className)); + + sigAnnotation.setElements(convertAnnotationElements(annotation + .getValue())); + value = sigAnnotation; + break; + } + case VALUE_FIELD: { + String fieldDesc = (String) dexEnodedValue.getValue(); + // FORMAT La/b/E;!CONSTANT + String[] typeAndFieldName = fieldDesc.split("!"); + String typeName = typeAndFieldName[0]; + String fieldName = typeAndFieldName[1]; + value = elementPool.getField(getQualifiedName(typeName), fieldName); + break; + } + case VALUE_ENUM: { + String fieldDesc = (String) dexEnodedValue.getValue(); + // FORMAT La/b/E;!CONSTANT + String[] typeAndFieldName = fieldDesc.split("!"); + String typeName = typeAndFieldName[0]; + String fieldName = typeAndFieldName[1]; + value = elementPool.getEnumConstant(getQualifiedName(typeName), + fieldName); + break; + } + case VALUE_TYPE: { + String typeName = (String) dexEnodedValue.getValue(); + GenericSignatureParser parser = new GenericSignatureParser(factory, + this); + value = parser.parseNonGenericReturnType(typeName); + break; + } + default: + throw new IllegalStateException(); + } + return value; + } + + public IClassDefinition initializeClass(String packageName, + String className) { + String dexName = getDexName(packageName, className); + DexClass dexClass = dexNameToDexClass.get(dexName); + return convertClass(dexClass); + } +} diff --git a/tools/signature-tools/src/signature/converter/dex/DexUtil.java b/tools/signature-tools/src/signature/converter/dex/DexUtil.java new file mode 100644 index 00000000000..f661af2ae42 --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/DexUtil.java @@ -0,0 +1,600 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import java.io.IOException; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IClassDefinition; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.impl.SigPackage; +import signature.model.util.ModelUtil; +import dex.reader.DexBuffer; +import dex.reader.DexFileReader; +import dex.structure.DexAnnotatedElement; +import dex.structure.DexAnnotation; +import dex.structure.DexAnnotationAttribute; +import dex.structure.DexClass; +import dex.structure.DexEncodedValue; +import dex.structure.DexField; +import dex.structure.DexFile; +import dex.structure.DexMethod; + + +public class DexUtil { + + private static final String PACKAGE_INFO = "package-info"; + private static final String THROWS_ANNOTATION = + "Ldalvik/annotation/Throws;"; + private static final String SIGNATURE_ANNOTATION = + "Ldalvik/annotation/Signature;"; + private static final String ANNOTATION_DEFAULT_ANNOTATION = + "Ldalvik/annotation/AnnotationDefault;"; + private static final String ENCLOSING_CLASS_ANNOTATION = + "Ldalvik/annotation/EnclosingClass;"; + private static final String ENCLOSING_METHOD_ANNOTATION = + "Ldalvik/annotation/EnclosingMethod;"; + private static final String INNER_CLASS_ANNOTATION = + "Ldalvik/annotation/InnerClass;"; + private static final String MEMBER_CLASS_ANNOTATION = + "Ldalvik/annotation/MemberClasses;"; + private static final String JAVA_LANG_OBJECT = "Ljava/lang/Object;"; + + private static final Set<String> INTERNAL_ANNOTATION_NAMES; + + static { + Set<String> tmp = new HashSet<String>(); + tmp.add(THROWS_ANNOTATION); + tmp.add(SIGNATURE_ANNOTATION); + tmp.add(ANNOTATION_DEFAULT_ANNOTATION); + tmp.add(ENCLOSING_CLASS_ANNOTATION); + tmp.add(ENCLOSING_METHOD_ANNOTATION); + tmp.add(INNER_CLASS_ANNOTATION); + tmp.add(MEMBER_CLASS_ANNOTATION); + INTERNAL_ANNOTATION_NAMES = Collections.unmodifiableSet(tmp); + } + + private DexUtil() { + // not constructable from outside + } + + /** + * "La/b/c/A;" -> "a.b.c" "LA;" -> "" empty string + * + * @param classIdentifier + * @return the package name + */ + public static String getPackageName(String classIdentifier) { + String name = removeTrailingSemicolon(removeHeadingL(classIdentifier)); + return ModelUtil.getPackageName(name.replace("/", ".")); + } + + /** + * "La/b/c/A;" -> "A" "LA;" -> "A" + * + * @param classIdentifier + * the dalvik internal identifier + * @return the class name + */ + public static String getClassName(String classIdentifier) { + String name = removeTrailingSemicolon(removeHeadingL(classIdentifier)); + return ModelUtil.getClassName(name.replace("/", ".")).replace('$', '.'); + } + + public static String getQualifiedName(String classIdentifier) { + String name = removeTrailingSemicolon(removeHeadingL(classIdentifier)); + return name.replace('/', '.'); + } + + private static String removeHeadingL(String className) { + assert className.startsWith("L"); + return className.substring(1); + } + + private static String removeTrailingSemicolon(String className) { + assert className.endsWith(";"); + return className.substring(0, className.length() - 1); + } + + public static String getDexName(String packageName, String className) { + return "L" + packageName.replace('.', '/') + "/" + + className.replace('.', '$') + ";"; + } + + public static String getDexName(IClassDefinition sigClass) { + return getDexName(sigClass.getPackageName(), sigClass.getName()); + } + + /** + * Returns correct modifiers for inner classes + */ + public static int getClassModifiers(DexClass clazz) { + int modifiers = 0; + if (isInnerClass(clazz)) { + Integer accessFlags = (Integer) getAnnotationAttributeValue( + getAnnotation(clazz, INNER_CLASS_ANNOTATION), + "accessFlags"); + modifiers = accessFlags.intValue(); + } else { + modifiers = clazz.getModifiers(); + } + return modifiers; + } + + /** + * Returns a set containing all modifiers for the given int. + * + * @param mod + * the original bit coded modifiers as specified by + * {@link java.lang.reflect.Modifier} + * @return a set containing {@link signature.model.Modifier} elements + */ + public static Set<Modifier> getModifier(int mod) { + Set<Modifier> modifiers = EnumSet.noneOf(Modifier.class); + if (java.lang.reflect.Modifier.isAbstract(mod)) + modifiers.add(Modifier.ABSTRACT); + if (java.lang.reflect.Modifier.isFinal(mod)) + modifiers.add(Modifier.FINAL); + // if (java.lang.reflect.Modifier.isNative(mod)) + // modifiers.add(Modifier.NATIVE); + if (java.lang.reflect.Modifier.isPrivate(mod)) + modifiers.add(Modifier.PRIVATE); + if (java.lang.reflect.Modifier.isProtected(mod)) + modifiers.add(Modifier.PROTECTED); + if (java.lang.reflect.Modifier.isPublic(mod)) + modifiers.add(Modifier.PUBLIC); + if (java.lang.reflect.Modifier.isStatic(mod)) + modifiers.add(Modifier.STATIC); + // if (java.lang.reflect.Modifier.isStrict(mod)) + // modifiers.add(Modifier.STRICT); + // if (java.lang.reflect.Modifier.isSynchronized(mod)) + // modifiers.add(Modifier.SYNCHRONIZED); + // if (java.lang.reflect.Modifier.isTransient(mod)) + // modifiers.add(Modifier.TRANSIENT); + if (java.lang.reflect.Modifier.isVolatile(mod)) + modifiers.add(Modifier.VOLATILE); + + return modifiers; + } + + /** + * Returns true if the given class is an enumeration, false otherwise. + * + * @param dexClass + * the DexClass under test + * @return true if the given class is an enumeration, false otherwise + */ + public static boolean isEnum(DexClass dexClass) { + return (getClassModifiers(dexClass) & 0x4000) > 0; + } + + /** + * Returns true if the given class is an interface, false otherwise. + * + * @param dexClass + * the DexClass under test + * @return true if the given class is an interface, false otherwise + */ + public static boolean isInterface(DexClass dexClass) { + int modifiers = getClassModifiers(dexClass); + return java.lang.reflect.Modifier.isInterface(modifiers); + } + + /** + * Returns true if the given class is an annotation, false otherwise. + * + * @param dexClass + * the DexClass under test + * @return true if the given class is an annotation, false otherwise + */ + public static boolean isAnnotation(DexClass dexClass) { + return (getClassModifiers(dexClass) & 0x2000) > 0; + } + + public static boolean isSynthetic(int modifier) { + return (modifier & 0x1000) > 0; + } + + /** + * Returns the Kind of the given DexClass. + * + * @param dexClass + * the DexClass under test + * @return the Kind of the given class + */ + public static Kind getKind(DexClass dexClass) { + // order of branches is crucial since a annotation is also an interface + if (isEnum(dexClass)) { + return Kind.ENUM; + } else if (isAnnotation(dexClass)) { + return Kind.ANNOTATION; + } else if (isInterface(dexClass)) { + return Kind.INTERFACE; + } else { + return Kind.CLASS; + } + } + + /** + * Returns whether the specified annotated element has an annotation with + * type "Ldalvik/annotation/Throws;". + * + * @param annotatedElement + * the annotated element to check + * @return <code>true</code> if the given annotated element has the + * mentioned annotation, false otherwise + */ + public static boolean declaresExceptions( + DexAnnotatedElement annotatedElement) { + return getAnnotation(annotatedElement, THROWS_ANNOTATION) != null; + } + + /** + * Returns the throws signature if the given element has such an annotation, + * null otherwise. + * + * @param annotatedElement + * the annotated element + * @return he generic signature if the given element has such an annotation, + * null otherwise + */ + @SuppressWarnings("unchecked") + public static String getExceptionSignature( + DexAnnotatedElement annotatedElement) { + DexAnnotation annotation = getAnnotation(annotatedElement, + THROWS_ANNOTATION); + if (annotation != null) { + List<DexEncodedValue> value = + (List<DexEncodedValue>) getAnnotationAttributeValue( + annotation, "value"); + return concatEncodedValues(value); + } + return null; + } + + /** + * Splits a list of types: + * "Ljava/io/IOException;Ljava/lang/IllegalStateException;" <br> + * into separate type designators: <br> + * "Ljava/io/IOException;" , "Ljava/lang/IllegalStateException;" + * + * @param typeList + * the type list + * @return a set of type designators + */ + public static Set<String> splitTypeList(String typeList) { + String[] split = typeList.split(";"); + Set<String> separateTypes = new HashSet<String>(); + for (String string : split) { + separateTypes.add(string + ";");// add semicolon again + } + return separateTypes; + } + + /** + * Returns whether the specified annotated element has an annotation with + * type "Ldalvik/annotation/Signature;". + * + * @param annotatedElement + * the annotated element to check + * @return <code>true</code> if the given annotated element has the + * mentioned annotation, false otherwise + */ + public static boolean hasGenericSignature( + DexAnnotatedElement annotatedElement) { + return getAnnotation(annotatedElement, SIGNATURE_ANNOTATION) != null; + } + + /** + * Returns the generic signature if the given element has such an + * annotation, null otherwise. + * + * @param annotatedElement + * the annotated element + * @return he generic signature if the given element has such an annotation, + * null otherwise + */ + @SuppressWarnings("unchecked") + public static String getGenericSignature( + DexAnnotatedElement annotatedElement) { + DexAnnotation annotation = getAnnotation(annotatedElement, + SIGNATURE_ANNOTATION); + if (annotation != null) { + List<DexEncodedValue> value = + (List<DexEncodedValue>) getAnnotationAttributeValue( + annotation, "value"); + return concatEncodedValues(value); + } + return null; + } + + /** + * Returns whether the specified annotated element has an annotation with + * type "Ldalvik/annotation/AnnotationDefault;". + * + * @param annotatedElement + * the annotated element to check + * @return <code>true</code> if the given annotated element has the + * mentioned annotation, false otherwise + */ + public static boolean hasAnnotationDefaultSignature( + DexAnnotatedElement annotatedElement) { + return getAnnotation( + annotatedElement, ANNOTATION_DEFAULT_ANNOTATION)!= null; + } + + /** + * Returns a mapping form annotation attribute name to its default value. + * + * @param dexClass + * the class defining a annotation + * @return a mapping form annotation attribute name to its default value + */ + public static DexAnnotation getDefaultMappingsAnnotation( + DexClass dexClass) { + return getAnnotation(dexClass, ANNOTATION_DEFAULT_ANNOTATION); + } + + /** + * Returns the annotation with the specified type from the given element or + * null if no such annotation is available. + * + * @param element + * the annotated element + * @param annotationType + * the dex internal name of the annotation type + * @return the annotation with the specified type or null if not present + */ + public static DexAnnotation getAnnotation(DexAnnotatedElement element, + String annotationType) { + assert element != null; + assert annotationType != null; + + for (DexAnnotation anno : element.getAnnotations()) { + if (annotationType.equals(anno.getTypeName())) { + return anno; + } + } + return null; + } + + /** + * Returns the value for the specified attribute name of the given + * annotation or null if not present. + * + * @param annotation + * the annotation + * @param attributeName + * the name of the attribute + * @return the value for the specified attribute + */ + public static Object getAnnotationAttributeValue(DexAnnotation annotation, + String attributeName) { + for (DexAnnotationAttribute dexAnnotationAttribute : annotation + .getAttributes()) { + if (attributeName.equals(dexAnnotationAttribute.getName())) { + return dexAnnotationAttribute.getEncodedValue().getValue(); + } + } + return null; + } + + private static String concatEncodedValues(List<DexEncodedValue> values) { + StringBuilder builder = new StringBuilder(); + for (DexEncodedValue string : values) { + builder.append(string.getValue()); + } + return builder.toString(); + } + + /** + * Returns true if the given method is a constructor, false otherwise. + * + * @param method + * the method to test + * @return true if the given method is a constructor, false otherwise + */ + public static boolean isConstructor(DexMethod method) { + return "<init>".equals(method.getName()); + } + + /** + * Returns true if the given method is a static constructor, false + * otherwise. + * + * @param method + * the method to test + * @return true if the given method is a static constructor, false otherwise + */ + public static boolean isStaticConstructor(DexMethod method) { + return "<clinit>".equals(method.getName()); + } + + public static boolean isMethod(DexMethod method) { + return !isConstructor(method) && !isStaticConstructor(method); + } + + /** + * Returns the package-info class for the given package. + * + * @param aPackage + * the package + * @return the class called "package-info" or null, if not available + */ + public static IClassDefinition findPackageInfo(SigPackage aPackage) { + for (IClassDefinition clazz : aPackage.getClasses()) { + if (PACKAGE_INFO.equals(clazz.getName())) { + return clazz; + } + } + return null; + } + + public static boolean isPackageInfo(DexClass clazz) { + return PACKAGE_INFO.equals(getClassName(clazz.getName())); + } + + public static boolean isInternalAnnotation(DexAnnotation dexAnnotation) { + return INTERNAL_ANNOTATION_NAMES.contains(dexAnnotation.getTypeName()); + } + + /** + * An InnerClass annotation is attached to each class which is defined in + * the lexical scope of another class's definition. Any class which has this + * annotation must also have either an EnclosingClass annotation or an + * EnclosingMethod annotation. + */ + public static boolean isInnerClass(DexClass clazz) { + return getAnnotation(clazz, INNER_CLASS_ANNOTATION) != null; + } + + /** + * An EnclosingClass annotation is attached to each class which is either + * defined as a member of another class, per se, or is anonymous but not + * defined within a method body (e.g., a synthetic inner class). Every class + * that has this annotation must also have an InnerClass annotation. + * Additionally, a class may not have both an EnclosingClass and an + * EnclosingMethod annotation. + */ + public static boolean isEnclosingClass(DexClass clazz) { + return getAnnotation(clazz, ENCLOSING_CLASS_ANNOTATION) != null; + } + + public static boolean declaresMemberClasses(DexClass dexClass) { + return getAnnotation(dexClass, MEMBER_CLASS_ANNOTATION) != null; + } + + @SuppressWarnings("unchecked") + public static Set<String> getMemberClassNames(DexClass dexClass) { + DexAnnotation annotation = getAnnotation(dexClass, + MEMBER_CLASS_ANNOTATION); + List<DexEncodedValue> enclosedClasses = + (List<DexEncodedValue>) getAnnotationAttributeValue( + annotation, "value"); + Set<String> enclosedClassesNames = new HashSet<String>(); + for (DexEncodedValue string : enclosedClasses) { + enclosedClassesNames.add((String) string.getValue()); + } + return enclosedClassesNames; + } + + + public static String getEnclosingClassName(DexClass dexClass) { + DexAnnotation annotation = getAnnotation(dexClass, + ENCLOSING_CLASS_ANNOTATION); + String value = (String) getAnnotationAttributeValue(annotation, + "value"); + return value; + } + + public static boolean convertAnyWay(DexClass dexClass) { + return !isSynthetic(getClassModifiers(dexClass)) + && !isAnonymousClassName(dexClass.getName()) + || isPackageInfo(dexClass); + } + + public static boolean isVisible(DexClass dexClass, Visibility visibility) { + // package info is always visible + if (isPackageInfo(dexClass)) { + return true; + } + + if (isDeclaredInMethod(dexClass)) { + return false; + } + + if (isAnonymousClassName(dexClass.getName())) { + return false; + } + + int modifiers = getClassModifiers(dexClass); + + return isVisible(modifiers, visibility); + } + + private static boolean isDeclaredInMethod(DexClass dexClass) { + return getAnnotation(dexClass, ENCLOSING_METHOD_ANNOTATION) != null; + } + + /** + * Returns whether the given dex identifier is an anonymous class name. + * Format: La/b/C$1; + * + * @param dexName + * the name to analyze + * @return whether the given dex identifier is an anonymous class name + */ + public static boolean isAnonymousClassName(String dexName) { + int index = dexName.lastIndexOf('$'); + return (index != 0) ? Character.isDigit(dexName.charAt(index + 1)) + : false; + } + + public static boolean isVisible(DexField dexField, Visibility visibility) { + return isVisible(dexField.getModifiers(), visibility); + } + + public static boolean isVisible(DexMethod dexMethod, + Visibility visibility) { + return isVisible(dexMethod.getModifiers(), visibility); + } + + private static boolean isVisible(int modifiers, Visibility visibility) { + + if (isSynthetic(modifiers)) { + return false; + } + + Set<Modifier> elementModifiers = getModifier(modifiers); + if (elementModifiers.contains(Modifier.PUBLIC)) { + return true; + } else if (elementModifiers.contains(Modifier.PROTECTED)) { + return visibility == Visibility.PROTECTED + || visibility == Visibility.PACKAGE + || visibility == Visibility.PRIVATE; + } else if (elementModifiers.contains(Modifier.PRIVATE)) { + return visibility == Visibility.PRIVATE; + } else { + return visibility == Visibility.PACKAGE + || visibility == Visibility.PRIVATE; + } + } + + public static Set<DexFile> getDexFiles(Set<String> fileNames) + throws IOException { + Set<DexFile> parsedFiles = new HashSet<DexFile>(); + + for (String dexFile : fileNames) { + DexFileReader reader = new DexFileReader(); + DexBuffer dexBuffer = new DexBuffer(dexFile); + parsedFiles.add(reader.read(dexBuffer)); + } + return parsedFiles; + } + + + public static boolean isJavaLangObject(DexClass dexClass) { + assert dexClass != null; + return JAVA_LANG_OBJECT.equals(dexClass.getName()); + } +} diff --git a/tools/signature-tools/src/signature/converter/dex/FieldPool.java b/tools/signature-tools/src/signature/converter/dex/FieldPool.java new file mode 100644 index 00000000000..6587820b8ab --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/FieldPool.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import java.util.HashMap; +import java.util.Map; + +import signature.model.impl.SigEnumConstant; +import signature.model.impl.SigField; + +public class FieldPool { + + private Map<FieldKey, SigField> fieldStore; + private Map<FieldKey, SigEnumConstant> constantStore; + + public FieldPool() { + fieldStore = new HashMap<FieldKey, SigField>(); + constantStore = new HashMap<FieldKey, SigEnumConstant>(); + } + + private static class FieldKey { + private final String qualifiedClassName; + private final String fieldName; + + public FieldKey(String qualifiedClassName, String fieldName) { + this.qualifiedClassName = qualifiedClassName; + this.fieldName = fieldName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = prime * fieldName.hashCode(); + result = prime * result + qualifiedClassName.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + FieldKey other = (FieldKey) obj; + if (!fieldName.equals(other.fieldName)) { + return false; + } + if (!qualifiedClassName.equals(other.qualifiedClassName)) { + return false; + } + return true; + } + } + + public SigField getField(String qualifiedClassName, String fieldName) { + FieldKey key = new FieldKey(qualifiedClassName, fieldName); + SigField sigField = fieldStore.get(key); + if (sigField == null) { + sigField = new SigField(fieldName); + fieldStore.put(key, sigField); + } + return sigField; + } + + public SigEnumConstant getEnumConstant(String qualifiedName, + String fieldName) { + FieldKey key = new FieldKey(qualifiedName, fieldName); + SigEnumConstant sigField = constantStore.get(key); + if (sigField == null) { + sigField = new SigEnumConstant(fieldName); + constantStore.put(key, sigField); + } + return sigField; + } + +} diff --git a/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java b/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java new file mode 100644 index 00000000000..773e2fc72ff --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import static signature.converter.dex.DexUtil.getClassName; +import static signature.converter.dex.DexUtil.getPackageName; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IConstructor; +import signature.model.IGenericDeclaration; +import signature.model.IMethod; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; +import signature.model.impl.SigArrayType; +import signature.model.impl.SigParameterizedType; +import signature.model.impl.SigPrimitiveType; +import signature.model.impl.SigTypeVariableDefinition; +import signature.model.impl.SigWildcardType; +import signature.model.impl.Uninitialized; +import signature.model.util.ITypeFactory; + +import java.lang.reflect.GenericSignatureFormatError; +import java.util.ArrayList; +import java.util.List; + +/** + * Implements a parser for the generics signature attribute. Uses a top-down, + * recursive descent parsing approach for the following grammar: + * + * <pre> + * ClassSignature ::= + * OptFormalTypeParams SuperclassSignature {SuperinterfaceSignature}. + * SuperclassSignature ::= ClassTypeSignature. + * SuperinterfaceSignature ::= ClassTypeSignature. + * + * OptFormalTypeParams ::= + * ["<" FormalTypeParameter {FormalTypeParameter} ">"]. + * + * FormalTypeParameter ::= Ident ClassBound {InterfaceBound}. + * ClassBound ::= ":" [FieldTypeSignature]. + * InterfaceBound ::= ":" FieldTypeSignature. + * + * FieldTypeSignature ::= + * ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature. + * ArrayTypeSignature ::= "[" TypSignature. + * + * ClassTypeSignature ::= + * "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments} ";". + * + * OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">". + * + * TypeArgument ::= ([WildcardIndicator] FieldTypeSignature) | "*". + * WildcardIndicator ::= "+" | "-". + * + * TypeVariableSignature ::= "T" Ident ";". + * + * TypSignature ::= FieldTypeSignature | BaseType. + * BaseType ::= "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z". + * + * MethodTypeSignature ::= + * OptFormalTypeParams "(" {TypeSignature} ")" ReturnType {ThrowsSignature}. + * ThrowsSignature ::= ("^" ClassTypeSignature) | ("^" TypeVariableSignature). + * + * ReturnType ::= TypSignature | VoidDescriptor. + * VoidDescriptor ::= "V". + * </pre> + */ +public class GenericSignatureParser { + + public List<ITypeReference> exceptionTypes; + public List<ITypeReference> parameterTypes; + public List<ITypeVariableDefinition> formalTypeParameters; + public ITypeReference returnType; + public ITypeReference fieldType; + public List<ITypeReference> interfaceTypes; + public ITypeReference superclassType; + + private IGenericDeclaration genericDecl; + + /* + * Parser: + */ + private char symbol; // 0: eof; else valid term symbol or first char of + // identifier. + private String identifier; + + + /* + * Scanner: eof is private to the scan methods and it's set only when a scan + * is issued at the end of the buffer. + */ + private boolean eof; + + private char[] buffer; + private int pos; + + private final ITypeFactory factory; + private final IClassInitializer classFinder; + private boolean parseForField; + + + public GenericSignatureParser(ITypeFactory factory, + IClassInitializer classFinder) { + this.factory = factory; + this.classFinder = classFinder; + } + + private void setInput(IGenericDeclaration genericDecl, String input) { + if (input != null) { + this.genericDecl = genericDecl; + this.buffer = input.toCharArray(); + this.eof = false; + scanSymbol(); + } else { + this.eof = true; + } + } + + public ITypeReference parseNonGenericType(String typeSignature) { + setInput(null, typeSignature); + ITypeReference type = parsePrimitiveType(); + if (type == null) { + type = parseFieldTypeSignature(); + } + return type; + } + + public ITypeReference parseNonGenericReturnType(String typeSignature) { + setInput(null, typeSignature); + ITypeReference returnType = parsePrimitiveType(); + if (returnType == null) { + returnType = parseReturnType(); + } + return returnType; + } + + private ITypeReference parsePrimitiveType() { + switch (symbol) { + case 'B': + scanSymbol(); + return SigPrimitiveType.BYTE_TYPE; + case 'C': + scanSymbol(); + return SigPrimitiveType.CHAR_TYPE; + case 'D': + scanSymbol(); + return SigPrimitiveType.DOUBLE_TYPE; + case 'F': + scanSymbol(); + return SigPrimitiveType.FLOAT_TYPE; + case 'I': + scanSymbol(); + return SigPrimitiveType.INT_TYPE; + case 'J': + scanSymbol(); + return SigPrimitiveType.LONG_TYPE; + case 'S': + scanSymbol(); + return SigPrimitiveType.SHORT_TYPE; + case 'Z': + scanSymbol(); + return SigPrimitiveType.BOOLEAN_TYPE; + default: + return null; + } + } + + /** + * Parses the generic signature of a class and creates the data structure + * representing the signature. + * + * @param classToProcess + * the GenericDeclaration calling this method + * @param signature + * the generic signature of the class + */ + public void parseForClass(IClassDefinition classToProcess, + String signature) { + setInput(classToProcess, signature); + if (!eof) { + parseClassSignature(); + } else { + throw new IllegalStateException("Generic signature is invalid!"); + } + } + + /** + * Parses the generic signature of a method and creates the data structure + * representing the signature. + * + * @param genericDecl + * the GenericDeclaration calling this method + * @param signature + * the generic signature of the class + */ + public void parseForMethod(IMethod genericDecl, String signature) { + setInput(genericDecl, signature); + if (!eof) { + parseMethodTypeSignature(); + } else { + throw new IllegalStateException("Generic signature is invalid!"); + } + } + + /** + * Parses the generic signature of a constructor and creates the data + * structure representing the signature. + * + * @param genericDecl + * the GenericDeclaration calling this method + * @param signature + * the generic signature of the class + */ + public void parseForConstructor(IConstructor genericDecl, + String signature) { + setInput(genericDecl, signature); + if (!eof) { + parseMethodTypeSignature(); + } else { + throw new IllegalStateException("Generic signature is invalid!"); + } + } + + /** + * Parses the generic signature of a field and creates the data structure + * representing the signature. + * + * @param genericDecl + * the GenericDeclaration calling this method + * @param signature + * the generic signature of the class + */ + public void parseForField(IClassDefinition genericDecl, String signature) { + parseForField = true; + setInput(genericDecl, signature); + try { + if (!eof) { + this.fieldType = parseFieldTypeSignature(); + } else { + throw new IllegalStateException( + "Generic signature is invalid!"); + } + } finally { + parseForField = false; + } + } + + private void parseClassSignature() { + // ClassSignature ::= + // OptFormalTypeParameters SuperclassSignature + // {SuperinterfaceSignature}. + + parseOptFormalTypeParameters(); + + // SuperclassSignature ::= ClassTypeSignature. + this.superclassType = parseClassTypeSignature(); + + interfaceTypes = new ArrayList<ITypeReference>(16); + while (symbol > 0) { + // SuperinterfaceSignature ::= ClassTypeSignature. + interfaceTypes.add(parseClassTypeSignature()); + } + } + + private void parseOptFormalTypeParameters() { + // OptFormalTypeParameters ::= + // ["<" FormalTypeParameter {FormalTypeParameter} ">"]. + + List<ITypeVariableDefinition> typeParameters = + new ArrayList<ITypeVariableDefinition>(); + + if (symbol == '<') { + scanSymbol(); + typeParameters.add(parseFormalTypeParameter()); + while ((symbol != '>') && (symbol > 0)) { + typeParameters.add(parseFormalTypeParameter()); + } + expect('>'); + } + + formalTypeParameters = typeParameters; + } + + private SigTypeVariableDefinition parseFormalTypeParameter() { + // FormalTypeParameter ::= Ident ClassBound {InterfaceBound}. + + scanIdentifier(); + String name = identifier.intern(); + SigTypeVariableDefinition typeVariable = factory.getTypeVariable(name, + genericDecl); + + List<ITypeReference> bounds = new ArrayList<ITypeReference>(); + + // ClassBound ::= ":" [FieldTypeSignature]. + expect(':'); + if (symbol == 'L' || symbol == '[' || symbol == 'T') { + bounds.add(parseFieldTypeSignature()); + } + + while (symbol == ':') { + // InterfaceBound ::= ":" FieldTypeSignature. + scanSymbol(); + bounds.add(parseFieldTypeSignature()); + } + typeVariable.setUpperBounds(bounds); + return typeVariable; + } + + /** + * Returns the generic declaration for the type variable with the specified + * name. + * + * @param variableName + * the name of the type variable + * @param declaration + * the declaration to start searching + * @return the declaration which defines the specified type variable + */ + private IGenericDeclaration getDeclarationOfTypeVariable( + String variableName, IClassDefinition declaration) { + assert variableName != null; + assert declaration != null; + + if (!Uninitialized.isInitialized(declaration.getTypeParameters())) { + declaration = classFinder.initializeClass(declaration + .getPackageName(), declaration.getName()); + } + + for (ITypeVariableDefinition typeVariable : declaration + .getTypeParameters()) { + if (variableName.equals(typeVariable.getName())) { + return declaration; + } + } + return getDeclarationOfTypeVariable(variableName, declaration + .getDeclaringClass()); + } + + private ITypeReference parseFieldTypeSignature() { + // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature + // | TypeVariableSignature. + + switch (symbol) { + case 'L': + return parseClassTypeSignature(); + case '[': + // ArrayTypeSignature ::= "[" TypSignature. + scanSymbol(); + SigArrayType arrayType = factory.getArrayType(parseTypeSignature()); + return arrayType; + case 'T': + return parseTypeVariableSignature(); + default: + throw new GenericSignatureFormatError(); + } + } + + private ITypeReference parseClassTypeSignature() { + // ClassTypeSignature ::= "L" {Ident "/"} Ident + // OptTypeArguments {"." Ident OptTypeArguments} ";". + + expect('L'); + + StringBuilder qualIdent = new StringBuilder("L"); + scanIdentifier(); + while (symbol == '/') { + scanSymbol(); + qualIdent.append(identifier).append("/"); + scanIdentifier(); + } + + qualIdent.append(this.identifier); + + + List<ITypeReference> typeArgs = parseOptTypeArguments(); + + ITypeReference parentType = null; + + String packageName = getPackageName(qualIdent.toString() + ";"); + String className = getClassName(qualIdent.toString() + ";"); + + if (typeArgs.isEmpty()) { + parentType = factory.getClassReference(packageName, className); + } else { + IClassReference rawType = factory.getClassReference(packageName, + className); + SigParameterizedType parameterizedType = factory + .getParameterizedType(null, rawType, typeArgs); + parentType = parameterizedType; + } + + ITypeReference typeToReturn = parentType; + + + // if owner type is a parameterized type, the types are separated by '.' + while (symbol == '.') { + // Deal with Member Classes: + scanSymbol(); + scanIdentifier(); + qualIdent.append("$").append(identifier); + typeArgs = parseOptTypeArguments(); + ITypeReference memberType = null; + + packageName = getPackageName(qualIdent.toString() + ";"); + className = getClassName(qualIdent.toString() + ";"); + + if (typeArgs.isEmpty()) { + memberType = factory.getClassReference(packageName, className); + } else { + IClassReference rawType = factory.getClassReference( + packageName, className); + SigParameterizedType parameterizedType = factory + .getParameterizedType(parentType, rawType, typeArgs); + memberType = parameterizedType; + } + typeToReturn = memberType; + } + + expect(';'); + + return typeToReturn; + } + + private List<ITypeReference> parseOptTypeArguments() { + // OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">". + + List<ITypeReference> typeArgs = new ArrayList<ITypeReference>(8); + if (symbol == '<') { + scanSymbol(); + + typeArgs.add(parseTypeArgument()); + while ((symbol != '>') && (symbol > 0)) { + typeArgs.add(parseTypeArgument()); + } + expect('>'); + } + return typeArgs; + } + + private ITypeReference parseTypeArgument() { + // TypeArgument ::= (["+" | "-"] FieldTypeSignature) | "*". + List<ITypeReference> extendsBound = new ArrayList<ITypeReference>(1); + ITypeReference superBound = null; + if (symbol == '*') { + scanSymbol(); + extendsBound.add(factory.getClassReference("java.lang", "Object")); + SigWildcardType wildcardType = factory.getWildcardType(superBound, + extendsBound); + return wildcardType; + } else if (symbol == '+') { + scanSymbol(); + extendsBound.add(parseFieldTypeSignature()); + SigWildcardType wildcardType = factory.getWildcardType(superBound, + extendsBound); + return wildcardType; + } else if (symbol == '-') { + scanSymbol(); + superBound = parseFieldTypeSignature(); + extendsBound.add(factory.getClassReference("java.lang", "Object")); + SigWildcardType wildcardType = factory.getWildcardType(superBound, + extendsBound); + return wildcardType; + } else { + return parseFieldTypeSignature(); + } + } + + private ITypeVariableReference parseTypeVariableSignature() { + // TypeVariableSignature ::= "T" Ident ";". + expect('T'); + scanIdentifier(); + expect(';'); + + IGenericDeclaration declaration = genericDecl; + + if (!factory.containsTypeVariableDefinition(identifier, declaration)) { + // since a field is not a generic declaration, i need to treat it + // differently. + // the generic declaration + if (parseForField) { + declaration = getDeclarationOfTypeVariable(identifier, + (IClassDefinition) genericDecl); + } else { + declaration = getDeclarationOfTypeVariable(identifier, + genericDecl.getDeclaringClass()); + } + // just create type variable + factory.getTypeVariable(identifier, declaration); + } + + return factory.getTypeVariableReference(identifier, declaration); + } + + private ITypeReference parseTypeSignature() { + switch (symbol) { + case 'B': + scanSymbol(); + return SigPrimitiveType.BYTE_TYPE; + case 'C': + scanSymbol(); + return SigPrimitiveType.CHAR_TYPE; + case 'D': + scanSymbol(); + return SigPrimitiveType.DOUBLE_TYPE; + case 'F': + scanSymbol(); + return SigPrimitiveType.FLOAT_TYPE; + case 'I': + scanSymbol(); + return SigPrimitiveType.INT_TYPE; + case 'J': + scanSymbol(); + return SigPrimitiveType.LONG_TYPE; + case 'S': + scanSymbol(); + return SigPrimitiveType.SHORT_TYPE; + case 'Z': + scanSymbol(); + return SigPrimitiveType.BOOLEAN_TYPE; + default: + // Not an elementary type, but a FieldTypeSignature. + return parseFieldTypeSignature(); + } + } + + private void parseMethodTypeSignature() { + // MethodTypeSignature ::= [FormalTypeParameters] + // "(" {TypeSignature} ")" ReturnType {ThrowsSignature}. + + parseOptFormalTypeParameters(); + + parameterTypes = new ArrayList<ITypeReference>(16); + expect('('); + while (symbol != ')' && (symbol > 0)) { + parameterTypes.add(parseTypeSignature()); + } + expect(')'); + + returnType = parseReturnType(); + + exceptionTypes = new ArrayList<ITypeReference>(8); + while (symbol == '^') { + scanSymbol(); + + // ThrowsSignature ::= ("^" ClassTypeSignature) | + // ("^" TypeVariableSignature). + if (symbol == 'T') { + exceptionTypes.add(parseTypeVariableSignature()); + } else { + exceptionTypes.add(parseClassTypeSignature()); + } + } + } + + private ITypeReference parseReturnType() { + // ReturnType ::= TypeSignature | "V". + if (symbol != 'V') { + return parseTypeSignature(); + } else { + scanSymbol(); + return SigPrimitiveType.VOID_TYPE; + } + } + + + // + // Scanner: + // + + private void scanSymbol() { + if (!eof) { + if (pos < buffer.length) { + symbol = buffer[pos]; + pos++; + } else { + symbol = 0; + eof = true; + } + } else { + throw new GenericSignatureFormatError(); + } + } + + private void expect(char c) { + if (symbol == c) { + scanSymbol(); + } else { + throw new GenericSignatureFormatError(); + } + } + + private boolean isStopSymbol(char ch) { + switch (ch) { + case ':': + case '/': + case ';': + case '<': + case '.': + return true; + } + return false; + } + + // PRE: symbol is the first char of the identifier. + // POST: symbol = the next symbol AFTER the identifier. + private void scanIdentifier() { + if (!eof) { + StringBuilder identBuf = new StringBuilder(32); + if (!isStopSymbol(symbol)) { + identBuf.append(symbol); + do { + char ch = buffer[pos]; + if ((ch >= 'a') && (ch <= 'z') || (ch >= 'A') + && (ch <= 'Z') || !isStopSymbol(ch)) { + identBuf.append(buffer[pos]); + pos++; + } else { + identifier = identBuf.toString(); + scanSymbol(); + return; + } + } while (pos != buffer.length); + identifier = identBuf.toString(); + symbol = 0; + eof = true; + } else { + // Ident starts with incorrect char. + symbol = 0; + eof = true; + throw new GenericSignatureFormatError(); + } + } else { + throw new GenericSignatureFormatError(); + } + } +} diff --git a/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java b/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java new file mode 100644 index 00000000000..935ca49aef2 --- /dev/null +++ b/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import signature.model.IClassDefinition; + +public interface IClassInitializer { + IClassDefinition initializeClass(String packageName, String className); +} diff --git a/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java b/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java new file mode 100644 index 00000000000..ea757dbedde --- /dev/null +++ b/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java @@ -0,0 +1,124 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter.doclet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.io.IApiLoader;
+import signature.model.IApi;
+
+import com.sun.javadoc.RootDoc;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Options;
+import com.sun.tools.javadoc.JavadocTool;
+import com.sun.tools.javadoc.Messager;
+import com.sun.tools.javadoc.ModifierFilter;
+import com.sun.tools.javadoc.RootDocImpl;
+
+public class DocletFactory implements IApiLoader {
+
+ public IApi loadApi(String name, Visibility visibility,
+ Set<String> fileNames, Set<String> packageNames) throws
+ IOException {
+ for (String packageName : packageNames) {
+ if (packageName.length() == 0)
+ throw new IllegalArgumentException(
+ "default package not supported by DocletFactory");
+ }
+ StringBuffer buf = new StringBuffer();
+ for (String filename : fileNames) {
+ buf.append(filename);
+ buf.append(":");
+ }
+ String sourcepath = buf.substring(0, buf.length() - 1);
+ RootDoc root = getRootDoc(visibility, sourcepath, packageNames);
+ DocletToSigConverter converter = new DocletToSigConverter();
+ IApi api = converter.convertDocletRoot(name, root, visibility,
+ packageNames);
+ return api;
+ }
+
+ private static RootDoc getRootDoc(Visibility visibility, String sourcepath,
+ java.util.Set<String> packages) throws IOException {
+ long accessModifier = 0;
+ switch (visibility) {
+ case PRIVATE:
+ accessModifier |= com.sun.tools.javac.code.Flags.PRIVATE; // 0x2
+ case PACKAGE: // 0x80000000
+ accessModifier |= com.sun.tools.javadoc.ModifierFilter.PACKAGE;
+ case PROTECTED:
+ accessModifier |= com.sun.tools.javac.code.Flags.PROTECTED; // 0x4
+ case PUBLIC:
+ accessModifier |= com.sun.tools.javac.code.Flags.PUBLIC; // 0x1
+ }
+
+ ModifierFilter showAccess = new ModifierFilter(accessModifier);
+ boolean breakiterator = false;
+ boolean quiet = false;
+ boolean legacy = false;
+ boolean docClasses = false;
+
+ String docLocale = "";
+ String encoding = null;
+ ListBuffer<String> javaNames = new ListBuffer<String>();
+ for (String p : packages)
+ javaNames.append(p);
+
+ ListBuffer<String[]> options = new ListBuffer<String[]>();
+
+ options.append(new String[] {"-sourcepath", sourcepath});
+
+ ListBuffer<String> subPackages = new ListBuffer<String>();
+ ListBuffer<String> excludedPackages = new ListBuffer<String>();
+
+ Context context = new Context();
+ Options compOpts = Options.instance(context);
+ compOpts.put("-sourcepath", sourcepath);
+
+ Constructor<Messager> c;
+ try {
+ // c = Messager.class.getDeclaredConstructor(Context.class,
+ // String.class);
+ // c.setAccessible(true);
+ // c.newInstance(context, "SigTest");
+ c = Messager.class.getDeclaredConstructor(Context.class,
+ String.class, PrintWriter.class, PrintWriter.class,
+ PrintWriter.class);
+ c.setAccessible(true);
+ PrintWriter err = new PrintWriter(new StringWriter());
+ PrintWriter warn = new PrintWriter(new StringWriter());
+ PrintWriter notice = new PrintWriter(new StringWriter());
+ c.newInstance(context, "SigTest", err, warn, notice);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ JavadocTool comp = JavadocTool.make0(context);
+ RootDocImpl root = comp.getRootDocImpl(docLocale, encoding, showAccess,
+ javaNames.toList(), options.toList(), breakiterator,
+ subPackages.toList(), excludedPackages.toList(), docClasses,
+ legacy, quiet);
+ return root;
+ }
+
+}
diff --git a/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java b/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java new file mode 100644 index 00000000000..f9ebe77545c --- /dev/null +++ b/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java @@ -0,0 +1,636 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter.doclet;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.Map.Entry;
+
+import signature.converter.Visibility;
+import signature.model.IAnnotation;
+import signature.model.IAnnotationElement;
+import signature.model.IAnnotationField;
+import signature.model.IApi;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IField;
+import signature.model.IGenericDeclaration;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigAnnotation;
+import signature.model.impl.SigAnnotationElement;
+import signature.model.impl.SigAnnotationField;
+import signature.model.impl.SigApi;
+import signature.model.impl.SigClassDefinition;
+import signature.model.impl.SigClassReference;
+import signature.model.impl.SigConstructor;
+import signature.model.impl.SigEnumConstant;
+import signature.model.impl.SigExecutableMember;
+import signature.model.impl.SigField;
+import signature.model.impl.SigMethod;
+import signature.model.impl.SigPackage;
+import signature.model.impl.SigParameter;
+import signature.model.impl.SigPrimitiveType;
+import signature.model.impl.SigTypeVariableDefinition;
+import signature.model.impl.SigTypeVariableReference;
+import signature.model.util.TypePool;
+
+import com.sun.javadoc.AnnotationDesc;
+import com.sun.javadoc.AnnotationTypeDoc;
+import com.sun.javadoc.AnnotationTypeElementDoc;
+import com.sun.javadoc.AnnotationValue;
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.ConstructorDoc;
+import com.sun.javadoc.ExecutableMemberDoc;
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.MethodDoc;
+import com.sun.javadoc.PackageDoc;
+import com.sun.javadoc.Parameter;
+import com.sun.javadoc.ParameterizedType;
+import com.sun.javadoc.ProgramElementDoc;
+import com.sun.javadoc.RootDoc;
+import com.sun.javadoc.Type;
+import com.sun.javadoc.TypeVariable;
+import com.sun.javadoc.WildcardType;
+import com.sun.javadoc.AnnotationDesc.ElementValuePair;
+
+public class DocletToSigConverter {
+
+ TypePool pool;
+ Set<String> packageNames;
+
+ /**
+ * Converts the signature information javadoc knows about into a
+ * signature.model.ISources structure.
+ */
+ public IApi convertDocletRoot(String name, RootDoc root,
+ Visibility visibility, Set<String> packageNames) {
+ this.pool = new TypePool();
+ this.packageNames = packageNames;
+
+ Set<IPackage> packages = new HashSet<IPackage>();
+
+ for (PackageDoc pack : root.specifiedPackages()) {
+ assert packageNames.contains(pack.name());
+ packages.add(convertPackage(pack));
+ }
+
+ SigApi sources = new SigApi(name, visibility);
+ sources.setPackages(packages);
+ return sources;
+ }
+
+ private IPackage convertPackage(PackageDoc packageDoc) {
+ Set<IClassDefinition> classes = new HashSet<IClassDefinition>();
+ for (ClassDoc clazz : packageDoc.allClasses()) {
+ // classes.add((IClass)convertType(clazz));
+ classes.add(convertClass(clazz));
+ }
+
+ SigPackage p = new SigPackage(packageDoc.name());
+ p.setClasses(classes);
+ p.setAnnotations(convertAnnotations(packageDoc.annotations()));
+ return p;
+ }
+
+ private SigClassDefinition convertClass(ClassDoc classDoc) {
+
+ SigClassDefinition c = pool.getClass(classDoc.containingPackage()
+ .name(), classDoc.name());
+ if (c.getKind() != Kind.UNINITIALIZED) return c;
+
+ if (classDoc.isEnum())
+ c.setKind(Kind.ENUM);
+ else if (classDoc.isInterface())
+ c.setKind(Kind.INTERFACE);
+ else if (classDoc.isClass())
+ c.setKind(Kind.CLASS);
+ else if (classDoc.isAnnotationType()) c.setKind(Kind.ANNOTATION);
+
+ if (!packageNames.contains(c.getPackageName())) {
+ // no additional conversion for this class is necessary
+ initializeClass(c);
+ return c;
+ }
+
+ c.setModifiers(convertModifiers(classDoc.modifierSpecifier()));
+ if (Kind.INTERFACE.equals(c.getKind())
+ || Kind.ANNOTATION.equals(c.getKind())) {
+ c.getModifiers().add(Modifier.ABSTRACT);
+ }
+
+ // superclass may be a class or a parameterized type (e.g. extends
+ // List<String>),
+ // may also be null if classDoc is an interface
+ Type superclassType = classDoc.superclassType();
+ if (superclassType != null) {
+ c.setSuperClass(convertTypeReference(classDoc.superclassType()));
+ } else {
+ c.setSuperClass(null);
+ }
+
+ Set<ITypeReference> interfaces = new HashSet<ITypeReference>();
+ for (Type interfaceType : classDoc.interfaceTypes()) {
+ interfaces.add(convertTypeReference(interfaceType));
+ }
+ c.setInterfaces(interfaces);
+
+ ClassDoc containingClass = classDoc.containingClass();
+ if (containingClass != null)
+ c.setDeclaringClass(convertClass(containingClass));
+ else
+ c.setDeclaringClass(null);
+
+ Set<IClassDefinition> innerClasses = new HashSet<IClassDefinition>();
+ for (ClassDoc innerClass : classDoc.innerClasses()) {
+ innerClasses.add(convertClass(innerClass));
+ }
+ c.setInnerClasses(innerClasses);
+
+ Set<IConstructor> constructors = new HashSet<IConstructor>();
+ for (ConstructorDoc constructor : classDoc.constructors()) {
+ constructors.add(convertConstructor(constructor));
+ }
+ c.setConstructors(constructors);
+
+ Set<IMethod> methods = new HashSet<IMethod>();
+ for (MethodDoc method : classDoc.methods()) {
+ methods.add(convertMethod(method));
+ }
+ c.setMethods(methods);
+
+ Set<IField> fields = new HashSet<IField>();
+ for (FieldDoc field : classDoc.fields()) {
+ fields.add(convertField(field));
+ }
+ c.setFields(fields);
+
+ Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>();
+ int ordinal = 0;
+ for (FieldDoc enumConstant : classDoc.enumConstants()) {
+ enumConstants.add(convertEnumConstant(enumConstant, ordinal++));
+ }
+ c.setEnumConstants(enumConstants);
+
+ List<ITypeVariableDefinition> typeParameters =
+ new LinkedList<ITypeVariableDefinition>();
+ for (TypeVariable typeVariable : classDoc.typeParameters()) {
+ typeParameters
+ .add(((ITypeVariableReference) convertTypeReference(
+ typeVariable)).getTypeVariableDefinition());
+ }
+ c.setTypeParameters(typeParameters);
+
+ if (classDoc.isAnnotationType()) {
+ Map<SigAnnotationField, AnnotationTypeElementDoc> annotationFieldAnnotations =
+ new HashMap<SigAnnotationField, AnnotationTypeElementDoc>();
+
+ // AnnotationTypeDoc annotationType =
+ // classDoc.asAnnotationTypeDoc(); // bug in Doclet Implementation,
+ // has been reported to sun
+ AnnotationTypeDoc annotationType = (AnnotationTypeDoc) classDoc;
+
+ Set<IAnnotationField> annotationFields =
+ new HashSet<IAnnotationField>();
+ for (AnnotationTypeElementDoc annotationElement : annotationType
+ .elements()) {
+ SigAnnotationField annotationField = new SigAnnotationField(
+ annotationElement.name());
+ annotationField.setModifiers(convertModifiers(annotationElement
+ .modifierSpecifier()));
+ annotationField.setType(convertTypeReference(annotationElement
+ .returnType()));
+ annotationField
+ .setDefaultValue(convertAnnotationValue(
+ annotationElement.defaultValue()));
+
+ // the annotations on fields are set later because these
+ // annotations may be of
+ // the same type and may use fields which are not yet defined
+ annotationFieldAnnotations.put(annotationField,
+ annotationElement);
+
+ annotationFields.add(annotationField);
+ }
+ c.setAnnotationFields(annotationFields);
+
+ // set annotation field annotations
+ for (Entry<SigAnnotationField, AnnotationTypeElementDoc> entry :
+ annotationFieldAnnotations.entrySet()) {
+ entry.getKey().setAnnotations(
+ convertAnnotations(entry.getValue().annotations()));
+ }
+ } else { // no annotation type
+ c.setAnnotationFields(null);
+ }
+
+ // set class annotations
+ c.setAnnotations(convertAnnotations(classDoc.annotations()));
+
+ return c;
+
+ }
+
+ private Object convertAnnotationValue(AnnotationValue annotationValue) {
+ if (annotationValue == null) {
+ return null;
+ }
+ Object value = annotationValue.value();
+ if (value instanceof Type) {
+ // Type contains primitive types as well, e.g. void.class
+ return convertTypeReference((Type) value);
+ } else if (value instanceof String) {
+ return value;
+ } else if (value instanceof Double || value instanceof Float
+ || value instanceof Long || value instanceof Integer
+ || value instanceof Short || value instanceof Byte
+ || value instanceof Character || value instanceof Boolean) {
+ return value;
+ } else if (value instanceof FieldDoc) {
+ FieldDoc field = (FieldDoc) value;
+ String name = field.name();
+ ITypeReference fieldType = convertTypeReference(field.type());
+ IClassReference fieldClassRef = (IClassReference) fieldType;
+ IClassDefinition fieldClass = fieldClassRef.getClassDefinition();
+
+ assert fieldClass.getKind() == Kind.ENUM;
+ Set<IEnumConstant> constants = fieldClass.getEnumConstants();
+ for (IEnumConstant enumConstant : constants) {
+ if (enumConstant.getName().equals(name)) value = enumConstant;
+ }
+ assert value instanceof IEnumConstant;
+ return value;
+ } else if (value instanceof AnnotationDesc) {
+ return convertAnnotation((AnnotationDesc) value);
+ } else if (value instanceof AnnotationValue) {
+ return convertAnnotationValue((AnnotationValue) value);
+ } else if (value instanceof AnnotationValue[]) {
+ AnnotationValue[] arr = (AnnotationValue[]) value;
+ int length = arr.length;
+ Object[] annotationArray = new Object[length];
+ for (int i = 0; i < length; i++) {
+ annotationArray[i] = convertAnnotationValue(arr[i]);
+ }
+ return annotationArray;
+ } else {
+ throw new RuntimeException("not expected case");
+ }
+ }
+
+ private ITypeReference convertArrayType(Type type) {
+ assert type.asWildcardType() == null;
+ assert type.asAnnotationTypeDoc() == null;
+
+ ITypeReference baseType = null;
+ if (type.asTypeVariable() != null) {
+ baseType = convertTypeReference(type.asTypeVariable());
+ } else if (type.asParameterizedType() != null) {
+ baseType = convertTypeReference(type.asParameterizedType());
+ } else if (type.asClassDoc() != null) {
+ baseType = new SigClassReference(convertClass(type.asClassDoc()));
+ } else if (type.isPrimitive()) {
+ baseType = SigPrimitiveType.valueOfTypeName(type.typeName());
+ } else {
+ throw new RuntimeException(type.toString());
+ }
+
+ ITypeReference arrayType = baseType;
+ int dimension = type.dimension().length() / 2;
+ while (dimension > 0) {
+ arrayType = pool.getArrayType(arrayType);
+ dimension--;
+ }
+
+ return arrayType;
+ }
+
+ private SigTypeVariableDefinition currentTypeVariableDefinition = null;
+
+ private ITypeReference convertTypeReference(Type type) {
+ assert type != null;
+
+ if (!"".equals(type.dimension())) {
+ return convertArrayType(type);
+ }
+
+ ParameterizedType pType = type.asParameterizedType();
+ if (pType != null) {
+ ITypeReference ownerType = null;
+ Type containingType = pType.containingType();
+ if (containingType != null)
+ ownerType = convertTypeReference(containingType);
+ IClassReference rawType = new SigClassReference(convertClass(pType
+ .asClassDoc()));
+
+ List<ITypeReference> typeArguments =
+ new LinkedList<ITypeReference>();
+ for (Type typeArgument : pType.typeArguments()) {
+ typeArguments.add(convertTypeReference(typeArgument));
+ }
+
+ if (typeArguments.size() > 0) {
+ return pool.getParameterizedType(ownerType, rawType,
+ typeArguments);
+ } else {
+ return rawType;
+ }
+ }
+
+ TypeVariable tv = type.asTypeVariable();
+ if (tv != null) {
+ String name = tv.typeName();
+
+ if (currentTypeVariableDefinition != null
+ && name.equals(currentTypeVariableDefinition.getName()))
+ return new SigTypeVariableReference(
+ currentTypeVariableDefinition);
+
+ IGenericDeclaration genericDeclaration = null;
+ ProgramElementDoc programElement = tv.owner();
+ if (programElement instanceof ClassDoc) {
+ genericDeclaration = convertClass((ClassDoc) programElement);
+ } else if (programElement instanceof MethodDoc
+ && currentMethod.size() > 0) {
+ genericDeclaration = currentMethod.peek();
+ } else if (programElement instanceof ConstructorDoc
+ && currentConstructor.size() > 0) {
+ genericDeclaration = currentConstructor.peek();
+ } else {
+ throw new IllegalStateException("situation not expected");
+ }
+ SigTypeVariableDefinition typeVariable = pool.getTypeVariable(name,
+ genericDeclaration);
+
+ List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
+ for (Type upperBound : tv.bounds()) {
+ // we are converting a type variable declaration which is stored
+ // in the
+ // field currentTypeVariableDefinition
+ assert currentTypeVariableDefinition == null;
+ currentTypeVariableDefinition = typeVariable;
+ upperBounds.add(convertTypeReference(upperBound));
+ currentTypeVariableDefinition = null;
+ }
+ if (upperBounds.size() == 0) {
+ // no explicit bounds, use java.lang.Object
+ upperBounds.add(pool.getClassReference("java.lang", "Object"));
+ }
+ typeVariable.setUpperBounds(upperBounds);
+
+ return new SigTypeVariableReference(typeVariable);
+ }
+
+ WildcardType wt = type.asWildcardType();
+ if (wt != null) {
+ ITypeReference lowerBound = null;
+ for (Type superBound : wt.superBounds()) {
+ lowerBound = convertTypeReference(superBound);
+ }
+
+ List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
+ for (Type upperBound : wt.extendsBounds()) {
+ upperBounds.add(convertTypeReference(upperBound));
+ }
+ if (upperBounds.size() == 0) {
+ // no explicit bounds, use java.lang.Object
+ upperBounds.add(pool.getClassReference("java.lang", "Object"));
+ }
+
+ return pool.getWildcardType(lowerBound, upperBounds);
+ }
+
+ ClassDoc c = type.asClassDoc();
+ if (c != null) {
+ return new SigClassReference(convertClass(c));
+ }
+
+ if (type.isPrimitive()) {
+ return SigPrimitiveType.valueOfTypeName(type.typeName());
+ }
+
+ throw new IllegalStateException(type.toString());
+ }
+
+ private void convertExecutableMember(ExecutableMemberDoc member,
+ SigExecutableMember m) {
+ Set<Modifier> modifiers = convertModifiers(member.modifierSpecifier());
+
+ // Doclet Bug: final values method is not considered as final
+ if (member.containingClass().isEnum() && member.name().equals("values")
+ && member.parameters().length == 0) {
+ modifiers.add(Modifier.FINAL);
+ }
+
+ if (member.containingClass().isInterface()) {
+ modifiers.add(Modifier.ABSTRACT);
+ }
+
+ m.setModifiers(modifiers);
+ m.setAnnotations(convertAnnotations(member.annotations()));
+ m.setDeclaringClass(convertClass(member.containingClass()));
+
+ List<ITypeVariableDefinition> typeParameters =
+ new LinkedList<ITypeVariableDefinition>();
+ for (TypeVariable typeParameter : member.typeParameters()) {
+ String name = typeParameter.typeName();
+ IGenericDeclaration genericDeclaration = null;
+ if (currentMethod.size() > 0)
+ genericDeclaration = currentMethod.peek();
+ else if (currentConstructor.size() > 0)
+ genericDeclaration = currentConstructor.peek();
+ else
+ throw new RuntimeException();
+ SigTypeVariableDefinition p = pool.getTypeVariable(name,
+ genericDeclaration);
+
+ List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
+ for (Type u : typeParameter.bounds()) {
+ upperBounds.add(convertTypeReference(u));
+ }
+ p.setUpperBounds(upperBounds);
+ typeParameters.add(p);
+ }
+ m.setTypeParameters(typeParameters);
+
+ List<IParameter> parameters = new LinkedList<IParameter>();
+ for (Parameter parameter : member.parameters()) {
+ SigParameter p = new SigParameter(convertTypeReference(parameter
+ .type()));
+ p.setAnnotations(convertAnnotations(parameter.annotations()));
+ parameters.add(p);
+ }
+ m.setParameters(parameters);
+
+ Set<ITypeReference> exceptions = new HashSet<ITypeReference>();
+ for (Type exceptionType : member.thrownExceptionTypes()) {
+ exceptions.add(convertTypeReference(exceptionType));
+ }
+ m.setExceptions(exceptions);
+ }
+
+ private Stack<SigMethod> currentMethod = new Stack<SigMethod>();
+
+ private IMethod convertMethod(MethodDoc method) {
+ SigMethod m = new SigMethod(method.name());
+ currentMethod.push(m);
+ convertExecutableMember(method, m);
+ m.setReturnType(convertTypeReference(method.returnType()));
+ currentMethod.pop();
+ return m;
+ }
+
+ private Stack<SigConstructor> currentConstructor =
+ new Stack<SigConstructor>();
+
+ private IConstructor convertConstructor(ConstructorDoc constructor) {
+ SigConstructor c = new SigConstructor(constructor.name());
+ currentConstructor.push(c);
+ convertExecutableMember(constructor, c);
+ currentConstructor.pop();
+ return c;
+ }
+
+ private IField convertField(FieldDoc field) {
+ SigField f = new SigField(field.name());
+ f.setAnnotations(convertAnnotations(field.annotations()));
+ f.setModifiers(convertModifiers(field.modifierSpecifier()));
+ f.setType(convertTypeReference(field.type()));
+ return f;
+ }
+
+ private IEnumConstant convertEnumConstant(FieldDoc enumConstant,
+ int ordinal) {
+ SigEnumConstant ec = new SigEnumConstant(enumConstant.name());
+ ec.setOrdinal(ordinal);
+ ec.setAnnotations(convertAnnotations(enumConstant.annotations()));
+ ec.setModifiers(convertModifiers(enumConstant.modifierSpecifier()));
+ ec.setType(convertTypeReference(enumConstant.type()));
+ return ec;
+ }
+
+ private Set<IAnnotation> convertAnnotations(
+ AnnotationDesc[] annotationDescs) {
+ Set<IAnnotation> annotations = new HashSet<IAnnotation>();
+ for (AnnotationDesc annotationDesc : annotationDescs) {
+ if (!annotationRetentionIsSource(annotationDesc))
+ annotations.add(convertAnnotation(annotationDesc));
+ }
+ return annotations;
+ }
+
+ private boolean annotationRetentionIsSource(AnnotationDesc annotationDesc) {
+ AnnotationTypeDoc type = annotationDesc.annotationType();
+ AnnotationDesc[] annotations = type.annotations();
+ for (AnnotationDesc d : annotations) {
+ if ("java.lang.annotation.Retention".equals(d.annotationType()
+ .qualifiedName())) {
+ for (ElementValuePair value : d.elementValues()) {
+ if ("value".equals(value.element().name())) {
+ return "java.lang.annotation.RetentionPolicy.SOURCE"
+ .equals(value.value().value().toString());
+ }
+ }
+ }
+ }
+ // default retention policy is CLASS
+ return false;
+ }
+
+ private IAnnotation convertAnnotation(AnnotationDesc annotationDesc) {
+ SigAnnotation a = new SigAnnotation();
+
+ IClassReference annotationType = (IClassReference) convertTypeReference(
+ annotationDesc.annotationType());
+ a.setType(annotationType);
+
+ Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>();
+ for (AnnotationDesc.ElementValuePair pair : annotationDesc
+ .elementValues()) {
+ SigAnnotationElement element = new SigAnnotationElement();
+ elements.add(element);
+
+ element.setValue(convertAnnotationValue(pair.value()));
+ String name = pair.element().name();
+ for (IAnnotationField field : annotationType.getClassDefinition()
+ .getAnnotationFields()) {
+ if (field.getName().equals(name)) {
+ element.setDeclaringField(field);
+ }
+ }
+ }
+ a.setElements(elements);
+ return a;
+ }
+
+ private void initializeClass(SigClassDefinition c) {
+ c.setAnnotationFields(null);
+ c.setAnnotations(null);
+ c.setConstructors(null);
+ c.setDeclaringClass(null);
+ c.setEnumConstants(null);
+ c.setFields(null);
+ c.setInnerClasses(null);
+ c.setInterfaces(null);
+ c.setMethods(null);
+ c.setModifiers(null);
+ c.setSuperClass(null);
+ c.setTypeParameters(null);
+ }
+
+ private Set<Modifier> convertModifiers(int mod) {
+ Set<Modifier> modifiers = EnumSet.noneOf(Modifier.class);
+ if (java.lang.reflect.Modifier.isAbstract(mod))
+ modifiers.add(Modifier.ABSTRACT);
+ if (java.lang.reflect.Modifier.isFinal(mod))
+ modifiers.add(Modifier.FINAL);
+ // if (java.lang.reflect.Modifier.isNative(mod))
+ // modifiers.add(Modifier.NATIVE);
+ if (java.lang.reflect.Modifier.isPrivate(mod))
+ modifiers.add(Modifier.PRIVATE);
+ if (java.lang.reflect.Modifier.isProtected(mod))
+ modifiers.add(Modifier.PROTECTED);
+ if (java.lang.reflect.Modifier.isPublic(mod))
+ modifiers.add(Modifier.PUBLIC);
+ if (java.lang.reflect.Modifier.isStatic(mod))
+ modifiers.add(Modifier.STATIC);
+ // if (java.lang.reflect.Modifier.isStrict(mod))
+ // modifiers.add(Modifier.STRICT);
+ // if (java.lang.reflect.Modifier.isSynchronized(mod))
+ // modifiers.add(Modifier.SYNCHRONIZED);
+ // if (java.lang.reflect.Modifier.isTransient(mod))
+ // modifiers.add(Modifier.TRANSIENT);
+ if (java.lang.reflect.Modifier.isVolatile(mod))
+ modifiers.add(Modifier.VOLATILE);
+
+ return modifiers;
+ }
+
+}
diff --git a/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java b/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java new file mode 100644 index 00000000000..bf3cb8b2328 --- /dev/null +++ b/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io; + +import java.io.IOException; + +import signature.compare.model.IApiDelta; + +public interface IApiDeltaExternalizer { + void externalize(String location, IApiDelta delta) throws IOException; +} diff --git a/tools/signature-tools/src/signature/io/IApiExternalizer.java b/tools/signature-tools/src/signature/io/IApiExternalizer.java new file mode 100644 index 00000000000..3bbfbe5b37e --- /dev/null +++ b/tools/signature-tools/src/signature/io/IApiExternalizer.java @@ -0,0 +1,30 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.io;
+
+import signature.model.IApi;
+
+import java.io.IOException;
+
+/**
+ * This interface is used to write API definitions. Possible implementations of
+ * this interface use Java serialization to store the API in binary form on the
+ * disk. An alternative implementation can use ASCII files.
+ */
+public interface IApiExternalizer {
+ void externalizeApi(String loacation, IApi signature) throws IOException;
+}
diff --git a/tools/signature-tools/src/signature/io/IApiLoader.java b/tools/signature-tools/src/signature/io/IApiLoader.java new file mode 100644 index 00000000000..a38fa1a473f --- /dev/null +++ b/tools/signature-tools/src/signature/io/IApiLoader.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io; + +import java.io.IOException; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IApi; + +public interface IApiLoader { + IApi loadApi(String name, Visibility visibility, Set<String> fileNames, + Set<String> packageNames) throws IOException; +} diff --git a/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java b/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java new file mode 100644 index 00000000000..d97c0924a19 --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import org.antlr.stringtemplate.StringTemplate; + +import signature.compare.model.IApiDelta; +import signature.compare.model.IPackageDelta; +import signature.compare.model.impl.SigDelta; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class ApiOverviewPage implements IEmitter { + + private final IApiDelta apiDelta; + + private List<IPackageDelta> removedPackages; + private List<IPackageDelta> addedPackages; + private List<IPackageDelta> changedPackages; + private Map<String, String> commonInfos; + + public ApiOverviewPage(IApiDelta apiDelta, + Map<String, String> commonInfos) { + this.apiDelta = apiDelta; + this.commonInfos = commonInfos; + prepareData(); + } + + private void prepareData() { + if (apiDelta.getPackageDeltas().isEmpty()) { + commonInfos.put("no_delta", "no_delta"); + } + removedPackages = new ArrayList<IPackageDelta>(SigDelta + .getRemoved(apiDelta.getPackageDeltas())); + Collections.sort(removedPackages, new PackageByNameComparator()); + + addedPackages = new ArrayList<IPackageDelta>(SigDelta.getAdded(apiDelta + .getPackageDeltas())); + Collections.sort(addedPackages, new PackageByNameComparator()); + + changedPackages = new ArrayList<IPackageDelta>(SigDelta + .getChanged(apiDelta.getPackageDeltas())); + Collections.sort(changedPackages, new PackageByNameComparator()); + } + + public void writeTo(StringBuilder b) { + StringTemplate template = TemplateStore + .getStringTemplate("ApiOverviewPage"); + template.setArgumentContext(commonInfos); + template.setAttribute("removed_packages", removedPackages); + template.setAttribute("added_packages", addedPackages); + template.setAttribute("changed_packages", changedPackages); + b.append(template.toString()); + } +} diff --git a/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java b/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java new file mode 100644 index 00000000000..8e2343453af --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import signature.compare.model.IClassDefinitionDelta; + +import java.util.Comparator; + +public class ClassByNameComparator implements + Comparator<IClassDefinitionDelta> { + + public int compare(IClassDefinitionDelta a, IClassDefinitionDelta b) { + assert a.getType() == b.getType(); + if (a.getFrom() != null) { + return a.getFrom().getName().compareTo(b.getFrom().getName()); + } else { + return a.getTo().getName().compareTo(b.getTo().getName()); + } + } +} diff --git a/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java b/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java new file mode 100644 index 00000000000..6951fb33a89 --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; + +import org.antlr.stringtemplate.StringTemplate; + +import signature.compare.model.IAnnotationFieldDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IConstructorDelta; +import signature.compare.model.IEnumConstantDelta; +import signature.compare.model.IFieldDelta; +import signature.compare.model.IMethodDelta; +import signature.compare.model.impl.SigDelta; + +public class ClassOverviewPage implements IEmitter { + + private static final String PAGE = "ClassOverviewPage"; + + private final IClassDefinitionDelta classDelta; + + private FieldByNameComparator<IFieldDelta> fieldComparator = + new FieldByNameComparator<IFieldDelta>(); + private ArrayList<IFieldDelta> removedFields; + private ArrayList<IFieldDelta> addedFields; + private ArrayList<IFieldDelta> changedFields; + + private FieldByNameComparator<IAnnotationFieldDelta> annotationfieldComparator = + new FieldByNameComparator<IAnnotationFieldDelta>(); + private ArrayList<IAnnotationFieldDelta> removedAnnotationFields; + private ArrayList<IAnnotationFieldDelta> addedAnnotationFields; + private ArrayList<IAnnotationFieldDelta> changedAnnotationFields; + + private FieldByNameComparator<IEnumConstantDelta> enumConstantComparator = + new FieldByNameComparator<IEnumConstantDelta>(); + private ArrayList<IEnumConstantDelta> removedEnumConstants; + private ArrayList<IEnumConstantDelta> addedEnumConstants; + private ArrayList<IEnumConstantDelta> changedEnumConstants; + + private ExecutableMemberComparator constructorComparator = + new ExecutableMemberComparator(); + private ArrayList<IConstructorDelta> removedConstructors; + private ArrayList<IConstructorDelta> addedConstructors; + private ArrayList<IConstructorDelta> changedConstructors; + + private ExecutableMemberComparator methodComparator = + new ExecutableMemberComparator(); + private ArrayList<IMethodDelta> removedMethods; + private ArrayList<IMethodDelta> addedMethods; + private ArrayList<IMethodDelta> changedMethods; + + private final Map<String, String> commonInfos; + + public ClassOverviewPage(IClassDefinitionDelta classDelta, + Map<String, String> commonInfos) { + this.classDelta = classDelta; + this.commonInfos = commonInfos; + prepareData(); + } + + private void prepareData() { + if (classDelta.getFieldDeltas() != null) { + prepareFieldDeltas(); + } + if (classDelta.getAnnotationFieldDeltas() != null) { + prepareAnnotationFieldDeltas(); + } + if (classDelta.getEnumConstantDeltas() != null) { + prepareEnumConstantDeltas(); + } + if (classDelta.getConstructorDeltas() != null) { + prepareConstructorDeltas(); + } + if (classDelta.getMethodDeltas() != null) { + prepareMethodDeltas(); + } + } + + private void prepareFieldDeltas() { + removedFields = new ArrayList<IFieldDelta>(SigDelta + .getRemoved(classDelta.getFieldDeltas())); + Collections.sort(removedFields, fieldComparator); + + addedFields = new ArrayList<IFieldDelta>(SigDelta.getAdded(classDelta + .getFieldDeltas())); + Collections.sort(addedFields, fieldComparator); + + changedFields = new ArrayList<IFieldDelta>(SigDelta + .getChanged(classDelta.getFieldDeltas())); + Collections.sort(changedFields, fieldComparator); + } + + private void prepareAnnotationFieldDeltas() { + removedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta + .getRemoved(classDelta.getAnnotationFieldDeltas())); + Collections.sort(removedAnnotationFields, annotationfieldComparator); + + addedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta + .getAdded(classDelta.getAnnotationFieldDeltas())); + Collections.sort(addedAnnotationFields, annotationfieldComparator); + + changedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta + .getChanged(classDelta.getAnnotationFieldDeltas())); + Collections.sort(changedAnnotationFields, annotationfieldComparator); + } + + private void prepareEnumConstantDeltas() { + removedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta + .getRemoved(classDelta.getEnumConstantDeltas())); + Collections.sort(removedEnumConstants, enumConstantComparator); + + addedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta + .getAdded(classDelta.getEnumConstantDeltas())); + Collections.sort(addedEnumConstants, enumConstantComparator); + + changedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta + .getChanged(classDelta.getEnumConstantDeltas())); + Collections.sort(changedEnumConstants, enumConstantComparator); + } + + private void prepareConstructorDeltas() { + removedConstructors = new ArrayList<IConstructorDelta>(SigDelta + .getRemoved(classDelta.getConstructorDeltas())); + Collections.sort(removedConstructors, constructorComparator); + + addedConstructors = new ArrayList<IConstructorDelta>(SigDelta + .getAdded(classDelta.getConstructorDeltas())); + Collections.sort(addedConstructors, constructorComparator); + + changedConstructors = new ArrayList<IConstructorDelta>(SigDelta + .getChanged(classDelta.getConstructorDeltas())); + Collections.sort(changedConstructors, constructorComparator); + } + + private void prepareMethodDeltas() { + removedMethods = new ArrayList<IMethodDelta>(SigDelta + .getRemoved(classDelta.getMethodDeltas())); + Collections.sort(removedMethods, methodComparator); + + addedMethods = new ArrayList<IMethodDelta>(SigDelta.getAdded(classDelta + .getMethodDeltas())); + Collections.sort(addedMethods, methodComparator); + + changedMethods = new ArrayList<IMethodDelta>(SigDelta + .getChanged(classDelta.getMethodDeltas())); + Collections.sort(changedMethods, methodComparator); + } + + public void writeTo(StringBuilder b) { + StringTemplate template = TemplateStore.getStringTemplate(PAGE); + + template.setAttribute("class_delta", classDelta); + boolean annotationDelta = classDelta.getAnnotationDeltas() != null; + boolean modifierDelta = classDelta.getModifierDeltas() != null; + boolean typeVariableDelta = classDelta.getTypeVariableDeltas() != null; + boolean superClassDelta = classDelta.getSuperClassDelta() != null; + boolean interfaceDelta = classDelta.getInterfaceDeltas() != null; + boolean hasSignatureDelta = annotationDelta || modifierDelta + || typeVariableDelta || superClassDelta || interfaceDelta; + + template.setAttribute("has_class_signature_delta", hasSignatureDelta); + + template.setAttribute("removed_fields", removedFields); + template.setAttribute("added_fields", addedFields); + template.setAttribute("changed_fields", changedFields); + + template.setAttribute("removed_annotation_fields", + removedAnnotationFields); + template.setAttribute("added_annotation_fields", addedAnnotationFields); + template.setAttribute("changed_annotation_fields", + changedAnnotationFields); + + template.setAttribute("removed_enum_constants", removedEnumConstants); + template.setAttribute("added_enum_constants", addedEnumConstants); + template.setAttribute("changed_enum_constants", changedEnumConstants); + + template.setAttribute("removed_constructors", removedConstructors); + template.setAttribute("added_constructors", addedConstructors); + template.setAttribute("changed_constructors", changedConstructors); + + template.setAttribute("removed_methods", removedMethods); + template.setAttribute("added_methods", addedMethods); + template.setAttribute("changed_methods", changedMethods); + + template.setArgumentContext(commonInfos); + b.append(template.toString()); + } +} diff --git a/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java b/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java new file mode 100644 index 00000000000..e3423421543 --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import signature.compare.model.IExecutableMemberDelta; +import signature.model.IArrayType; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IExecutableMember; +import signature.model.IParameter; +import signature.model.IParameterizedType; +import signature.model.IPrimitiveType; +import signature.model.ITypeDefinition; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +public class ExecutableMemberComparator implements + Comparator<IExecutableMemberDelta<? extends IExecutableMember>> { + + public int compare(IExecutableMemberDelta<? extends IExecutableMember> a, + IExecutableMemberDelta<? extends IExecutableMember> b) { + assert a.getType() == b.getType(); + IExecutableMember aMember = null; + IExecutableMember bMember = null; + + if (a.getFrom() != null) { + aMember = a.getFrom(); + bMember = b.getFrom(); + } else { + aMember = a.getTo(); + bMember = b.getTo(); + } + + int returnValue = aMember.getName().compareTo(bMember.getName()); + return returnValue != 0 ? returnValue : compareParameterLists(aMember + .getParameters(), bMember.getParameters()); + } + + private int compareParameterLists(List<IParameter> a, List<IParameter> b) { + if (a.size() != b.size()) { + return a.size() - b.size(); + } + Iterator<IParameter> aIt = a.iterator(); + Iterator<IParameter> bIt = b.iterator(); + int returnValue = 0; + while (aIt.hasNext() && bIt.hasNext()) { + returnValue += getTypeName(aIt.next().getType()).compareTo( + getTypeName(bIt.next().getType())); + } + return returnValue; + } + + private String getTypeName(ITypeReference type) { + if (type instanceof IClassReference) { + return getTypeName(((IClassReference) type).getClassDefinition()); + } + if (type instanceof ITypeVariableReference) { + return getTypeName(((ITypeVariableReference) type) + .getTypeVariableDefinition()); + } + if (type instanceof IParameterizedType) { + return getTypeName(((IParameterizedType) type).getRawType()); + } + if (type instanceof IArrayType) { + return getTypeName(((IArrayType) type).getComponentType()); + } + if (type instanceof IPrimitiveType) { + return ((IPrimitiveType) type).getName(); + } + return type.toString(); + } + + private String getTypeName(ITypeDefinition type) { + if (type instanceof IClassDefinition) { + return ((IClassDefinition) type).getName(); + } + if (type instanceof ITypeVariableDefinition) { + return ((ITypeVariableDefinition) type).getName(); + } + return type.toString(); + } + +} diff --git a/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java b/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java new file mode 100644 index 00000000000..9aaf1f8871c --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import java.util.Comparator; + +import signature.compare.model.IMemberDelta; +import signature.model.IField; + +public class FieldByNameComparator<T extends IMemberDelta<?>> implements + Comparator<T> { + + public int compare(T a, T b) { + assert a.getType() == b.getType(); + IField aField = null; + IField bField = null; + + // FIXME File javac or jdt bug. + // Note: Casts are required by javac 1.5.0_16. + if (a.getFrom() != null) { + aField = (IField) a.getFrom(); + bField = (IField) b.getFrom(); + } else { + aField = (IField) a.getTo(); + bField = (IField) b.getTo(); + } + return aField.getName().compareTo(bField.getName()); + } +} diff --git a/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java b/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java new file mode 100644 index 00000000000..1ba5cba2c8f --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import org.antlr.stringtemplate.StringTemplate; + +import signature.Version; +import signature.compare.model.IApiDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IDelta; +import signature.compare.model.IPackageDelta; +import signature.compare.model.impl.SigDelta; +import signature.io.IApiDeltaExternalizer; +import signature.model.IClassDefinition; +import signature.model.IPackage; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.DateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class HtmlDeltaExternalizer implements IApiDeltaExternalizer { + + private static final String OVERVIEW_PAGE_NAME = "changes.html"; + private static final String STYLE_SHEET_NAME = "styles.css"; + private static final String DELTA_FOLDER = "changes" + File.separator; + + public void externalize(String location, IApiDelta apiDelta) + throws IOException { + if (!location.endsWith(File.separator)) { + location += File.separator; + } + + File directory = new File(location); + if (!directory.exists()) { + directory.mkdirs(); + } + + copyStyleSheet(location); + + Map<String, String> commonInfos = new HashMap<String, String>(); + commonInfos.put("creation_time", DateFormat.getDateTimeInstance() + .format(new Date())); + commonInfos.put("from_desc", apiDelta.getFrom().getName()); + commonInfos.put("to_desc", apiDelta.getTo().getName()); + + // write overview page + StringBuilder content = new StringBuilder(); + ApiOverviewPage apiOverviewPage = new ApiOverviewPage(apiDelta, + commonInfos); + apiOverviewPage.writeTo(content); + writeToFile(location + OVERVIEW_PAGE_NAME, content.toString()); + + // write package overview + Set<IPackageDelta> changedPackages = SigDelta.getChanged(apiDelta + .getPackageDeltas()); + if (!changedPackages.isEmpty()) { + + File file = new File(location + DELTA_FOLDER); + if (!file.exists()) { + file.mkdir(); + } + + for (IPackageDelta packageDelta : changedPackages) { + content = new StringBuilder(); + PackageOverviewPage packagePage = new PackageOverviewPage( + packageDelta, commonInfos); + packagePage.writeTo(content); + IPackage aPackage = getAnElement(packageDelta); + String packageOverviewFileName = location + DELTA_FOLDER + + "pkg_" + aPackage.getName() + ".html"; + writeToFile(packageOverviewFileName, content.toString()); + + // write class overviews + for (IClassDefinitionDelta classDelta : packageDelta + .getClassDeltas()) { + content = new StringBuilder(); + ClassOverviewPage classPage = new ClassOverviewPage( + classDelta, commonInfos); + classPage.writeTo(content); + IClassDefinition aClass = getAnElement(classDelta); + String classOverviewFileName = location + DELTA_FOLDER + + aPackage.getName() + "." + aClass.getName() + + ".html"; + writeToFile(classOverviewFileName, content.toString()); + } + } + } + // write class overview + } + + private static <T> T getAnElement(IDelta<T> delta) { + if (delta.getFrom() != null) { + return delta.getFrom(); + } else { + return delta.getTo(); + } + } + + private void copyStyleSheet(String directory) throws IOException { + StringTemplate template = TemplateStore.getStringTemplate("Styles"); + template.setAttribute("version", Version.VERSION); + writeToFile(directory + STYLE_SHEET_NAME, template.toString()); + } + + private void writeToFile(String fileName, String content) + throws IOException { + FileOutputStream fileOutputStream = new FileOutputStream(fileName); + fileOutputStream.write(content.getBytes()); + fileOutputStream.flush(); + fileOutputStream.close(); + } +} diff --git a/tools/signature-tools/src/signature/io/html/IEmitter.java b/tools/signature-tools/src/signature/io/html/IEmitter.java new file mode 100644 index 00000000000..db73e6617e1 --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/IEmitter.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +public interface IEmitter { + void writeTo(StringBuilder b); +} diff --git a/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java b/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java new file mode 100644 index 00000000000..3bbff71d29b --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import signature.compare.model.IPackageDelta; +import signature.model.IPackage; + +import java.util.Comparator; + +public class PackageByNameComparator implements Comparator<IPackageDelta> { + + public int compare(IPackageDelta a, IPackageDelta b) { + assert a.getType() == b.getType(); + IPackage aPackage = null; + IPackage bPackage = null; + + if (a.getFrom() != null) { + aPackage = a.getFrom(); + bPackage = b.getFrom(); + } else { + aPackage = a.getTo(); + bPackage = b.getTo(); + } + return aPackage.getName().compareTo(bPackage.getName()); + } +} diff --git a/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java b/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java new file mode 100644 index 00000000000..ccfe3cc7caf --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import org.antlr.stringtemplate.StringTemplate; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IPackageDelta; +import signature.compare.model.impl.SigDelta; + +public class PackageOverviewPage implements IEmitter { + + private static final String PACGE = "PackageOverviewPage"; + + private final IPackageDelta delta; + + private List<IClassDefinitionDelta> removedClasses; + private List<IClassDefinitionDelta> addedClasses; + private List<IClassDefinitionDelta> changedClasses; + private final Map<String, String> commonInfos; + + + public PackageOverviewPage(IPackageDelta delta, + Map<String, String> commonInfos) { + this.delta = delta; + this.commonInfos = commonInfos; + prepareData(); + } + + private void prepareData() { + removedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta + .getRemoved(delta.getClassDeltas())); + Collections.sort(removedClasses, new ClassByNameComparator()); + + addedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta + .getAdded(delta.getClassDeltas())); + Collections.sort(addedClasses, new ClassByNameComparator()); + + changedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta + .getChanged(delta.getClassDeltas())); + Collections.sort(changedClasses, new ClassByNameComparator()); + } + + public void writeTo(StringBuilder b) { + StringTemplate template = TemplateStore.getStringTemplate(PACGE); + template.setArgumentContext(commonInfos); + template.setAttribute("package_delta", delta); + template.setAttribute("removed_classes", removedClasses); + template.setAttribute("added_classes", addedClasses); + template.setAttribute("changed_classes", changedClasses); + b.append(template.toString()); + } + + + +} diff --git a/tools/signature-tools/src/signature/io/html/TemplateStore.java b/tools/signature-tools/src/signature/io/html/TemplateStore.java new file mode 100644 index 00000000000..a161bf79069 --- /dev/null +++ b/tools/signature-tools/src/signature/io/html/TemplateStore.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.html; + +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.antlr.stringtemplate.StringTemplate; +import org.antlr.stringtemplate.StringTemplateGroup; +import org.antlr.stringtemplate.language.DefaultTemplateLexer; + +public class TemplateStore { + + private static StringTemplateGroup group = initialize(); + + + private static StringTemplateGroup initialize() { + InputStream modelStream = TemplateStore.class.getClassLoader() + .getResourceAsStream("model/model.stg"); + InputStreamReader modelReader = new InputStreamReader(modelStream); + StringTemplateGroup modelGroup = new StringTemplateGroup(modelReader, + DefaultTemplateLexer.class); + + InputStream stream = TemplateStore.class.getClassLoader() + .getResourceAsStream("delta/deltas.stg"); + InputStreamReader reader = new InputStreamReader(stream); + StringTemplateGroup deltaGroup = new StringTemplateGroup(reader, + DefaultTemplateLexer.class); + + StringTemplateGroup group = new StringTemplateGroup("signature", null, + DefaultTemplateLexer.class); + group.setSuperGroup(deltaGroup); + + deltaGroup.setSuperGroup(modelGroup); + return group; + } + + private TemplateStore() {/* no instances allowed */ + } + + public static StringTemplate getStringTemplate(String name) { + return group.getInstanceOf(name); + } +} diff --git a/tools/signature-tools/src/signature/io/impl/BinaryApi.java b/tools/signature-tools/src/signature/io/impl/BinaryApi.java new file mode 100644 index 00000000000..f12cf6a7784 --- /dev/null +++ b/tools/signature-tools/src/signature/io/impl/BinaryApi.java @@ -0,0 +1,83 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.io.impl;
+
+import signature.converter.Visibility;
+import signature.io.IApiExternalizer;
+import signature.io.IApiLoader;
+import signature.model.IApi;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Set;
+
+public class BinaryApi implements IApiExternalizer, IApiLoader {
+
+ public void externalizeApi(String fileName, IApi api) throws IOException {
+
+ File directory = new File(fileName);
+ if (!directory.exists()) {
+ directory.mkdirs();
+ }
+
+ File file = new File(directory, getFileName(api));
+ file.createNewFile();
+
+ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
+ file));
+ oos.writeObject(api);
+
+ oos.flush();
+ oos.close();
+ }
+
+ private String getFileName(IApi api) {
+ return api.getName().replaceAll(" ", "_").concat(".sig");
+ }
+
+ public IApi loadApi(String name, Visibility visibility,
+ Set<String> fileNames, Set<String> packageNames) throws
+ IOException {
+ System.err
+ .println("Binary signature loader ignores visibility and " +
+ "package names.");
+ if (fileNames.size() != 1) {
+ throw new IllegalArgumentException(
+ "Only one file can be processed by the binary signature " +
+ "loader.");
+ }
+ String fileName = fileNames.iterator().next();
+ File file = new File(fileName);
+ ObjectInputStream ois = new ObjectInputStream(
+ new FileInputStream(file));
+ IApi sig = null;
+ try {
+ sig = (IApi) ois.readObject();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ if (name != null) {
+ sig.setName(name);
+ }
+
+ ois.close();
+ return sig;
+ }
+}
diff --git a/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java b/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java new file mode 100644 index 00000000000..62615af181d --- /dev/null +++ b/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.io.impl; + +import signature.compare.model.IApiDelta; +import signature.io.IApiDeltaExternalizer; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +public class ToStringExternalizer implements IApiDeltaExternalizer { + + public void externalize(String location, IApiDelta delta) + throws IOException { + + OutputStreamWriter outputStreamWriter = new OutputStreamWriter( + new FileOutputStream(location)); + + if (delta == null) { + outputStreamWriter.write("No delta found!"); + } else { + outputStreamWriter.write(delta.toString()); + } + outputStreamWriter.close(); + } +} diff --git a/tools/signature-tools/src/signature/model/IAnnotatableElement.java b/tools/signature-tools/src/signature/model/IAnnotatableElement.java new file mode 100644 index 00000000000..53d6c385aee --- /dev/null +++ b/tools/signature-tools/src/signature/model/IAnnotatableElement.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.Set; + +/** + * Common interface for model elements which may be annotated. Annotations can + * be attached to: + * <ul> + * <li>Classes (IClass), including annotations which are also classes + * <li>Methods and Constructors (IExecutableMember) + * <li>Fields (IField), including the annotation fields and enum constants + * <li>Parameters (IParameter) + * </ul> + */ +public interface IAnnotatableElement { + + /** + * Returns a set of annotations of a model element. + * + * @return a set of annotations of a model element + */ + Set<IAnnotation> getAnnotations(); +} diff --git a/tools/signature-tools/src/signature/model/IAnnotation.java b/tools/signature-tools/src/signature/model/IAnnotation.java new file mode 100644 index 00000000000..c31689deef0 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IAnnotation.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.Set; + +/** + * {@code IAnnotation} models an <em>instance</em> of an annotation which is + * attached to a program element. The definition of an annotation type is + * modeled as an {@link IClassDefinition} with the {@link Kind#ANNOTATION}. + */ +public interface IAnnotation { + /** + * Returns the annotation type of this annotation. + * + * @return the annotation type of this annotation + */ + IClassReference getType(); + + /** + * Returns the elements declared in this annotation. The values which are + * not declared are not contained in this list. Each element consists of its + * name and its value. + * + * @return elements declared in this annotation + */ + Set<IAnnotationElement> getElements(); +} diff --git a/tools/signature-tools/src/signature/model/IAnnotationElement.java b/tools/signature-tools/src/signature/model/IAnnotationElement.java new file mode 100644 index 00000000000..5637fd64e27 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IAnnotationElement.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IAnnotationElement} models an annotation element which consist of a + * name and a value. + */ +public interface IAnnotationElement { + /** + * Returns the value of this annotation element. The type of this value is + * restricted to the possible value types for annotation elements. + * <p> + * The following types are possible: + * <ul> + * <li>a wrapper class for a primitive type + * <li>String (for String values) + * <li>IType (representing a class literal) FIXME Reference? Def? + * <li>IEnumConstant (representing an enum constant) + * <li>IAnnotation + * </ul> + * and (one-dimensional) arrays of the above types. + * + * @return the value of this annotation element + */ + Object getValue(); + + /** + * Returns the corresponding annotation field declaration. This declaration + * contains e.g. the name of this element, its type and its modifiers. The + * declaration also contains the default value of this element which is + * overwritten by this annotation element. + * + * @return the corresponding annotation field declaration + */ + IAnnotationField getDeclaringField(); + +} diff --git a/tools/signature-tools/src/signature/model/IAnnotationField.java b/tools/signature-tools/src/signature/model/IAnnotationField.java new file mode 100644 index 00000000000..c40707f8d0f --- /dev/null +++ b/tools/signature-tools/src/signature/model/IAnnotationField.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IAnnotationField} models a field in a annotation definition. The + * following example shows an annotation field <code>androField</code> of type + * String and the default value "droid". + * + * <pre> + * + * @interface A { String androField() default "droid"; } + * + * </pre> + */ +public interface IAnnotationField extends IField { + + /** + * Returns the default value. If no default value is set then null is + * returned. + * + * The type of the returned object is one of the following: + * <ul> + * <li>a wrapper class for a primitive type + * <li>String (for String values) + * <li>IType (representing a class literal) + * <li>IEnumConstant (representing an enum constant) + * <li>IAnnotation + * </ul> + * and (one-dimensional) arrays of the above types. If an array is returned, + * then the type of the result is Object[]. The elements of this array are + * of the above listed types. + */ + Object getDefaultValue(); +} diff --git a/tools/signature-tools/src/signature/model/IApi.java b/tools/signature-tools/src/signature/model/IApi.java new file mode 100644 index 00000000000..de51938fdae --- /dev/null +++ b/tools/signature-tools/src/signature/model/IApi.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import signature.converter.Visibility; + +import java.util.Set; + +/** + * {@code IApi} models the root of an api. + */ +public interface IApi { + /** + * Returns the name of this api. + * + * @return the name of this api + */ + String getName(); + + /** + * Sets the name of this api. + * + * @param name + * the name of this api + */ + void setName(String name); + + /** + * Returns the set of packages which constitute this api. + * + * @return the set of packages which constitute this api + */ + Set<IPackage> getPackages(); + + /** + * Returns the visibility of this api. The visibility describes which + * elements are visible. Only elements with a visibility greater or equal + * this visibility are contained in this api model. + * + * @return the visibility of this api + * @see Visibility + */ + Visibility getVisibility(); +} diff --git a/tools/signature-tools/src/signature/model/IArrayType.java b/tools/signature-tools/src/signature/model/IArrayType.java new file mode 100644 index 00000000000..bb63e67c700 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IArrayType.java @@ -0,0 +1,30 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.model;
+
+/**
+ * {@code IArrayType} models an array type.
+ */
+public interface IArrayType extends ITypeReference {
+
+ /**
+ * Returns the component type of this array type.
+ *
+ * @return component type of this array type
+ */
+ ITypeReference getComponentType();
+}
diff --git a/tools/signature-tools/src/signature/model/IClassDefinition.java b/tools/signature-tools/src/signature/model/IClassDefinition.java new file mode 100644 index 00000000000..1bd5401462d --- /dev/null +++ b/tools/signature-tools/src/signature/model/IClassDefinition.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; +import java.util.Set; + +/** + * {@code IClassDefinition} models a class definition. This is the model + * equivalent to a class. + */ +public interface IClassDefinition extends ITypeDefinition, IGenericDeclaration, + IAnnotatableElement { + + /** + * Returns the kind of this class definition. + * + * @return the kind of this class definition + */ + Kind getKind(); + + /** + * Returns the name of this class definition. + * + * @return the name of this class definition + */ + String getName(); + + /** + * Returns the '.' separated package name of this class. + * + * @return the '.' separated package name of this class + */ + String getPackageName(); + + /** + * Returns a list containing each package fragment. + * <p> + * If {@link #getPackageName()} returns : "a.b.c" this method returns a list + * containing the three elements "a", "b", "c". + * <p> + * Note: this method exists only for convenience in output templating. + * + * @return a list containing each package fragment + */ + List<String> getPackageFragments(); + + /** + * Returns the qualified name of this class definition. The qualified name + * is composed of {@link #getPackageName()} '.' {@link #getName()} + * + * @return the qualified name of this class definition + */ + String getQualifiedName(); + + /** + * Returns the super class for this class definition. May return {@code + * null} if this class definition does not have any superclass. This is the + * case if the kind of this class definition is {@link Kind#INTERFACE} or + * this class definition is {@link Object}. + * + * @return the super class for this class definition or {@code null} + */ + ITypeReference getSuperClass(); + + /** + * Returns the declared interfaces this class definition implements . If no + * interfaces are declared, an empty set is returned. + * + * @return the declared interfaces for this class definition + */ + Set<ITypeReference> getInterfaces(); + + /** + * Returns the modifiers for this class definition. + * + * @return the modifiers for this class definition + */ + Set<Modifier> getModifiers(); + + /** + * Returns all declared methods of this class definition. + * + * @return all declared methods of this class definition + */ + Set<IMethod> getMethods(); + + /** + * Returns all declared constructors of this class definition. + * + * @return all declared constructors of this class definition + */ + Set<IConstructor> getConstructors(); + + /** + * Returns all declared fields of this class definition. + * + * @return all declared fields of this class definition + */ + Set<IField> getFields(); + + /** + * Returns all declared enumeration constant definitions of this class + * definition. The returned set may only contain elements if the kind of + * this class definition is {@link Kind#ENUM}. + * + * @return all declared enumeration constants of this class definition + */ + Set<IEnumConstant> getEnumConstants(); + + /** + * Returns all declared annotation field definitions of this class + * definition. The returned set may only contain elements if the kind of + * this class definition is {@link Kind#ANNOTATION}. + * + * @return all declared annotation fields of this class definition + */ + Set<IAnnotationField> getAnnotationFields(); + + /** + * Returns all classes which where defined in the lexical scope of this + * class definition. Anonymous classes are never returned. + * + * @return all classes which where defined in the lexical scope of this + * class definition + */ + Set<IClassDefinition> getInnerClasses(); +} diff --git a/tools/signature-tools/src/signature/model/IClassReference.java b/tools/signature-tools/src/signature/model/IClassReference.java new file mode 100644 index 00000000000..bcb2c555a49 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IClassReference.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IClassReference} models a reference to an {@link IClassDefinition}. If + * the referenced {@link IClassDefinition} defines + * {@link ITypeVariableDefinition}s, this reference can be seen as a raw type. + */ +public interface IClassReference extends ITypeReference { + + /** + * Returns the definition this class reference is referencing. + * + * @return the definition this class reference is referencing + */ + IClassDefinition getClassDefinition(); +} diff --git a/tools/signature-tools/src/signature/model/IConstructor.java b/tools/signature-tools/src/signature/model/IConstructor.java new file mode 100644 index 00000000000..29f52758574 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IConstructor.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IConstructor} models a constructor. + */ +public interface IConstructor extends IExecutableMember { +} diff --git a/tools/signature-tools/src/signature/model/IEnumConstant.java b/tools/signature-tools/src/signature/model/IEnumConstant.java new file mode 100644 index 00000000000..681e62b39ab --- /dev/null +++ b/tools/signature-tools/src/signature/model/IEnumConstant.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IEnumConstant} models an enumeration constant. + */ +public interface IEnumConstant extends IField { + + /** + * Returns the ordinal of this enum constant. + * + * @return the ordinal of this enum constant. + */ + int getOrdinal(); +} diff --git a/tools/signature-tools/src/signature/model/IExecutableMember.java b/tools/signature-tools/src/signature/model/IExecutableMember.java new file mode 100644 index 00000000000..ef7f7ba84bc --- /dev/null +++ b/tools/signature-tools/src/signature/model/IExecutableMember.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; +import java.util.Set; + +/** + * {@code IExecutableMember} is the common super interface for methods an + * constructors. + */ +public interface IExecutableMember extends IGenericDeclaration, + IAnnotatableElement { + + /** + * Returns the name of this executable member. + * + * @return the name of this executable member + */ + String getName(); + + /** + * Returns the parameters of this executable member. + * + * @return the parameters of this executable member + */ + List<IParameter> getParameters(); + + /** + * Returns the declared exceptions of this executable member. + * + * @return the declared exceptions of this executable member + */ + Set<ITypeReference> getExceptions(); + + /** + * Returns the modifiers of this executable member. + * + * @return the modifiers of this executable member + */ + Set<Modifier> getModifiers(); +} diff --git a/tools/signature-tools/src/signature/model/IField.java b/tools/signature-tools/src/signature/model/IField.java new file mode 100644 index 00000000000..3cf759319ce --- /dev/null +++ b/tools/signature-tools/src/signature/model/IField.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.Set; + +/** + * {@code IField} models a field. + */ +public interface IField extends IAnnotatableElement { + + /** + * Returns the name of this field. + * + * @return the name of this field + */ + String getName(); + + /** + * Returns the type of this field. + * + * @return the type of this field + */ + ITypeReference getType(); + + /** + * Returns the modifiers of this field. + * + * @return the modifiers of this field + */ + Set<Modifier> getModifiers(); +} diff --git a/tools/signature-tools/src/signature/model/IGenericDeclaration.java b/tools/signature-tools/src/signature/model/IGenericDeclaration.java new file mode 100644 index 00000000000..d7f4683e69f --- /dev/null +++ b/tools/signature-tools/src/signature/model/IGenericDeclaration.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; + +/** + * {@code IGenericDeclaration} is the common base interface for elements which + * can define type variables. + */ +public interface IGenericDeclaration { + + /** + * Returns a list of all defined type variables on this generic declaration. + * + * @return a list of all defined type variables + */ + List<ITypeVariableDefinition> getTypeParameters(); + + /** + * Returns the class definition which declares this element or {@code null} + * if this declaration is a top level class definition. + * + * @return the class definition which declares this element or {@code null} + */ + IClassDefinition getDeclaringClass(); +} diff --git a/tools/signature-tools/src/signature/model/IMethod.java b/tools/signature-tools/src/signature/model/IMethod.java new file mode 100644 index 00000000000..e205db15f9d --- /dev/null +++ b/tools/signature-tools/src/signature/model/IMethod.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import signature.model.impl.SigPrimitiveType; + +/** + * {@code IMethod} models a method. + */ +public interface IMethod extends IExecutableMember { + + /** + * Returns the return type of this method. + * <p> + * If the declared return type is {@code void} + * {@link SigPrimitiveType#VOID_TYPE} is returned. + * + * @return the return type of this method + */ + ITypeReference getReturnType(); +} diff --git a/tools/signature-tools/src/signature/model/IPackage.java b/tools/signature-tools/src/signature/model/IPackage.java new file mode 100644 index 00000000000..78b14cea876 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IPackage.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; +import java.util.Set; + +/** + * {@code IPackage} models a package. + */ +public interface IPackage extends IAnnotatableElement { + + /** + * Returns the name of this package. + * + * @return the name of this package + */ + String getName(); + + /** + * Returns a list containing each package fragment. + * <p> + * If {@link #getName()} returns : "a.b.c" this method returns a list + * containing the three elements "a", "b", "c". + * <p> + * Note: this method exists only for convenience in output templating. + * + * @return a list containing each package fragment + */ + List<String> getPackageFragments(); + + /** + * Returns all classes declared in this package, including ordinary classes, + * interfaces, enum types and annotation types. Nested classes are returned + * as well. + * + * @return all classes declared in this package + */ + Set<IClassDefinition> getClasses(); +} diff --git a/tools/signature-tools/src/signature/model/IParameter.java b/tools/signature-tools/src/signature/model/IParameter.java new file mode 100644 index 00000000000..bd359d54dee --- /dev/null +++ b/tools/signature-tools/src/signature/model/IParameter.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IParameter} models a parameter of an {@link IExecutableMember}. + */ +public interface IParameter extends IAnnotatableElement { + + /** + * Returns the type of this parameter. + * + * @return the type of this parameter + */ + ITypeReference getType(); +} diff --git a/tools/signature-tools/src/signature/model/IParameterizedType.java b/tools/signature-tools/src/signature/model/IParameterizedType.java new file mode 100644 index 00000000000..59f5692b951 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IParameterizedType.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; + +/** + * {@code IParameterizedType} models a parameterized type. A parameterized type + * instantiates a generic class definition with actual type arguments. + * + * <pre> + * IClassDefinition: + * public class A<T> {} + * + * public class XXX { + * IParameterizedType (raw type: A , type arguments: Number) + * public A<Number> fields; + * } + * </pre> + */ +public interface IParameterizedType extends ITypeReference { + + /** + * Returns the actual type arguments of this parameterized type. + * + * @return the actual type arguments of this parameterized type + */ + List<ITypeReference> getTypeArguments(); + + /** + * Returns the raw type of this parameterized type. + * + * @return the raw type of this parameterized type + */ + IClassReference getRawType(); + + /** + * Returns the owner type of this parameterized type or {@code null}. + * + * <pre> + * class Y<T> { + * class Z<S> { + * } + * + * Y<Integer>.Z<String> a; + * } + * </pre> + */ + ITypeReference getOwnerType(); // A.B<String> -> A +} diff --git a/tools/signature-tools/src/signature/model/IPrimitiveType.java b/tools/signature-tools/src/signature/model/IPrimitiveType.java new file mode 100644 index 00000000000..917b96b7262 --- /dev/null +++ b/tools/signature-tools/src/signature/model/IPrimitiveType.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code IPrimitiveType} models a primitive type. + */ +public interface IPrimitiveType extends ITypeReference { + + /** + * Returns the name of this primitive type, i.e. one of the following + * strings: + * <ul> + * <li><code>boolean</code> + * <li><code>byte</code> + * <li><code>char</code> + * <li><code>short</code> + * <li><code>int</code> + * <li><code>float</code> + * <li><code>double</code> + * <li><code>void</code> + * </ul> + * + * @return the name of this primitive type + */ + public String getName(); +} diff --git a/tools/signature-tools/src/signature/model/ITypeDefinition.java b/tools/signature-tools/src/signature/model/ITypeDefinition.java new file mode 100644 index 00000000000..b182f217527 --- /dev/null +++ b/tools/signature-tools/src/signature/model/ITypeDefinition.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code ITypeDefinition} is the common interface for type definitions. A type + * definition is either an {@link ITypeVariableDefinition} or an + * {@link IClassDefinition}. + */ +public interface ITypeDefinition { +} diff --git a/tools/signature-tools/src/signature/model/ITypeReference.java b/tools/signature-tools/src/signature/model/ITypeReference.java new file mode 100644 index 00000000000..f17f1725093 --- /dev/null +++ b/tools/signature-tools/src/signature/model/ITypeReference.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code ITypeReference} is the common interface for type references. + */ +public interface ITypeReference { +} diff --git a/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java b/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java new file mode 100644 index 00000000000..df0ead05b43 --- /dev/null +++ b/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; + +/** + * {@code ITypeVariableDefinition} models a type variable definition. + */ +public interface ITypeVariableDefinition extends ITypeDefinition { + + /** + * Returns the upper bounds for this type variable as specified by the + * extends clause. If no upper bounds are explicitly specified then + * java.lang.Object is returned as upper bound. + * + * @return the upper bounds for this type variable + */ + List<ITypeReference> getUpperBounds(); + + /** + * Returns the name of this type variable. + * + * @return the name of this type variable + */ + String getName(); + + /** + * Returns the element on which this type variable is declared. + * + * @return the element on which this type variable is declared + */ + IGenericDeclaration getGenericDeclaration(); +} diff --git a/tools/signature-tools/src/signature/model/ITypeVariableReference.java b/tools/signature-tools/src/signature/model/ITypeVariableReference.java new file mode 100644 index 00000000000..64e0657b400 --- /dev/null +++ b/tools/signature-tools/src/signature/model/ITypeVariableReference.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * {@code ITypeVariableReference} models a reference to an + * {@link ITypeVariableDefinition}. + */ +public interface ITypeVariableReference extends ITypeReference { + + /** + * Returns the definition this type variable reference is referencing. + * + * @return the definition this type variable reference is referencing + */ + ITypeVariableDefinition getTypeVariableDefinition(); +} diff --git a/tools/signature-tools/src/signature/model/IWildcardType.java b/tools/signature-tools/src/signature/model/IWildcardType.java new file mode 100644 index 00000000000..02a0d2def2a --- /dev/null +++ b/tools/signature-tools/src/signature/model/IWildcardType.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.List; + +/** + * {@code IWildcardType} models a wildcard type. + */ +public interface IWildcardType extends ITypeReference { + + /** + * Returns the upper bounds for this type variable as specified by the + * extends clause. If no upper bounds are explicitly specified then + * java.lang.Object is returned as upper bound. + * + * @return the upper bounds for this type variable + */ + List<ITypeReference> getUpperBounds(); + + /** + * Returns the lower bounds for this type variable as specified by the super + * clause. If no lower bounds are explicitly specified then null is returned + * as lower bound. + * + * @return the lower bounds for this type variable + */ + ITypeReference getLowerBound(); + +} diff --git a/tools/signature-tools/src/signature/model/Kind.java b/tools/signature-tools/src/signature/model/Kind.java new file mode 100644 index 00000000000..219e039e486 --- /dev/null +++ b/tools/signature-tools/src/signature/model/Kind.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +/** + * Type of the modeled class. + */ +public enum Kind { + CLASS("class"), INTERFACE("interface"), ANNOTATION("@interface"), ENUM( + "enum"), UNINITIALIZED("UNINITIALIZED"); + + private final String name; + + Kind(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/tools/signature-tools/src/signature/model/Modifier.java b/tools/signature-tools/src/signature/model/Modifier.java new file mode 100644 index 00000000000..223e88f7db2 --- /dev/null +++ b/tools/signature-tools/src/signature/model/Modifier.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model; + +import java.util.Set; + +/** + * {@class Modifier} models a modifer. + */ +public enum Modifier { + PUBLIC("public"), PRIVATE("private"), PROTECTED("protected"), STATIC( + "static"), FINAL("final"), SYNCHRONIZED("synchronized"), VOLATILE( + "volatile"), TRANSIENT("transient"), NATIVE("native"), ABSTRACT( + "abstract"), STRICT("strict"); + + private final String printableName; + + private Modifier(String printableName) { + this.printableName = printableName; + } + + @Override + public String toString() { + return printableName; + } + + public static String toString(Set<Modifier> modifiers) { + StringBuilder s = new StringBuilder(); + + for (Modifier modifier : values()) { + if (modifiers.contains(modifier)) { + s.append(modifier.printableName); + s.append(" "); + } + } + + return s.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java b/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java new file mode 100644 index 00000000000..53f021ea282 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Set; + +import signature.model.IAnnotatableElement; +import signature.model.IAnnotation; + +@SuppressWarnings("serial") +public abstract class SigAnnotatableElement implements IAnnotatableElement, + Serializable { + private Set<IAnnotation> annotations; + + public SigAnnotatableElement() { + annotations = Collections.emptySet(); + } + + public Set<IAnnotation> getAnnotations() { + return annotations; + } + + public void setAnnotations(Set<IAnnotation> annotations) { + this.annotations = annotations; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + for (IAnnotation annotation : getAnnotations()) { + builder.append(annotation); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotation.java b/tools/signature-tools/src/signature/model/impl/SigAnnotation.java new file mode 100644 index 00000000000..b7d0354c371 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigAnnotation.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IAnnotation; +import signature.model.IAnnotationElement; +import signature.model.IClassReference; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Set; + +@SuppressWarnings("serial") +public class SigAnnotation implements IAnnotation, Serializable { + + private Set<IAnnotationElement> elements; + private IClassReference type; + + public SigAnnotation() { + elements = Collections.emptySet(); + } + + public IClassReference getType() { + return type; + } + + public void setType(IClassReference type) { + this.type = type; + } + + public Set<IAnnotationElement> getElements() { + return elements; + } + + public void setElements(Set<IAnnotationElement> elements) { + this.elements = elements; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("@"); + builder.append(getType()); + if (!getElements().isEmpty()) { + builder.append("{"); + for (IAnnotationElement element : getElements()) { + builder.append("\n"); + builder.append(element.toString()); + } + builder.append("}"); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java b/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java new file mode 100644 index 00000000000..3d676a77ccb --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; + +import signature.model.IAnnotationElement; +import signature.model.IAnnotationField; + +@SuppressWarnings("serial") +public class SigAnnotationElement implements IAnnotationElement, Serializable { + + private IAnnotationField declaringField; + private Object value; + + public IAnnotationField getDeclaringField() { + return declaringField; + } + + public void setDeclaringField(IAnnotationField declaringField) { + this.declaringField = declaringField; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getDeclaringField().getName()); + builder.append(" = "); + builder.append(getValue()); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java b/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java new file mode 100644 index 00000000000..5dd6faf0c47 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; + +import signature.model.IAnnotationField; + +@SuppressWarnings("serial") +public class SigAnnotationField extends SigField implements IAnnotationField, + Serializable { + + private Object defaultValue = Uninitialized.unset(); + + public SigAnnotationField(String name) { + super(name); + } + + public Object getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigApi.java b/tools/signature-tools/src/signature/model/impl/SigApi.java new file mode 100644 index 00000000000..b573f8fa52a --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigApi.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IApi; +import signature.model.IPackage; + +@SuppressWarnings("serial") +public class SigApi implements IApi, Serializable { + + private Set<IPackage> packages = Uninitialized.unset(); + private String description; + private Visibility visibility; + + public SigApi(String description, Visibility visibility) { + this.description = description; + this.visibility = visibility; + } + + public String getName() { + return description; + } + + public void setName(String description) { + this.description = description; + } + + public Set<IPackage> getPackages() { + return packages; + } + + public void setPackages(Set<IPackage> packages) { + this.packages = packages; + } + + public Visibility getVisibility() { + return visibility; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getName()); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigArrayType.java b/tools/signature-tools/src/signature/model/impl/SigArrayType.java new file mode 100644 index 00000000000..3d20824e312 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigArrayType.java @@ -0,0 +1,69 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.IArrayType;
+import signature.model.ITypeReference;
+
+@SuppressWarnings("serial")
+public class SigArrayType implements IArrayType, Serializable {
+ private ITypeReference componentType;
+
+ public SigArrayType(ITypeReference componentType) {
+ this.componentType = componentType;
+ }
+
+ public ITypeReference getComponentType() {
+ return componentType;
+ }
+
+ @Override
+ public int hashCode() {
+ return SigArrayType.hashCode(this);
+ }
+
+ public static int hashCode(IArrayType type) {
+ return type.getComponentType().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return SigArrayType.equals(this, obj);
+ }
+
+ public static boolean equals(IArrayType thiz, Object that) {
+ if (!(that instanceof IArrayType)) {
+ return false;
+ }
+ IArrayType other = (IArrayType) that;
+ return thiz.getComponentType().equals(other.getComponentType());
+ }
+
+ @Override
+ public String toString() {
+ return SigArrayType.toString(this);
+ }
+
+ public static String toString(IArrayType type) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(type.getComponentType().toString());
+ builder.append("[]");
+ return builder.toString();
+ }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java b/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java new file mode 100644 index 00000000000..fe7c7ab5593 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import signature.model.IAnnotationField; +import signature.model.IClassDefinition; +import signature.model.IConstructor; +import signature.model.IEnumConstant; +import signature.model.IField; +import signature.model.IMethod; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.util.ModelUtil; + +@SuppressWarnings("serial") +public class SigClassDefinition extends SigAnnotatableElement implements + IClassDefinition, Serializable { + + private String name; + private Kind kind = Kind.UNINITIALIZED; + private ITypeReference superClass = Uninitialized.unset(); + private Set<ITypeReference> interfaces = Uninitialized.unset(); + private Set<Modifier> modifiers = Uninitialized.unset(); + private Set<IMethod> methods = Uninitialized.unset(); + private Set<IConstructor> constructors = Uninitialized.unset(); + private Set<IClassDefinition> innerClasses = Uninitialized.unset(); + private Set<IAnnotationField> annotationFields = Uninitialized.unset(); + private Set<IField> fields = Uninitialized.unset(); + private Set<IEnumConstant> enumConstants = Uninitialized.unset(); + private IClassDefinition declaringClass = Uninitialized.unset(); + private List<ITypeVariableDefinition> typeParameters = Uninitialized + .unset(); + private String packageName; + + public SigClassDefinition(String packageName, String name) { + this.packageName = packageName; + this.name = name; + } + + public Kind getKind() { + return kind; + } + + public void setKind(Kind kind) { + this.kind = kind; + } + + public String getName() { + return name; + } + + public String getPackageName() { + return packageName; + } + + public List<String> getPackageFragments() { + return Arrays.asList(packageName.split("\\.")); + } + + public String getQualifiedName() { + return packageName + "." + name; + } + + public Set<Modifier> getModifiers() { + return modifiers; + } + + public void setModifiers(Set<Modifier> modifiers) { + this.modifiers = modifiers; + } + + public Set<IClassDefinition> getInnerClasses() { + return innerClasses; + } + + public void setInnerClasses(Set<IClassDefinition> innerClasses) { + this.innerClasses = innerClasses; + } + + public Set<ITypeReference> getInterfaces() { + return interfaces; + } + + public void setInterfaces(Set<ITypeReference> interfaces) { + this.interfaces = interfaces; + } + + public Set<IMethod> getMethods() { + return methods; + } + + public void setMethods(Set<IMethod> methods) { + this.methods = methods; + } + + public Set<IConstructor> getConstructors() { + return constructors; + } + + public void setConstructors(Set<IConstructor> constructors) { + this.constructors = constructors; + } + + public ITypeReference getSuperClass() { + return superClass; + } + + public void setSuperClass(ITypeReference superClass) { + this.superClass = superClass; + } + + public IClassDefinition getDeclaringClass() { + return declaringClass; + } + + public void setDeclaringClass(IClassDefinition declaringClass) { + this.declaringClass = declaringClass; + } + + public Set<IAnnotationField> getAnnotationFields() { + return annotationFields; + } + + public void setAnnotationFields(Set<IAnnotationField> annotationFields) { + this.annotationFields = annotationFields; + } + + public Set<IField> getFields() { + return fields; + } + + public void setFields(Set<IField> fields) { + this.fields = fields; + } + + public Set<IEnumConstant> getEnumConstants() { + return enumConstants; + } + + public void setEnumConstants(Set<IEnumConstant> enumConstants) { + this.enumConstants = enumConstants; + } + + public List<ITypeVariableDefinition> getTypeParameters() { + return typeParameters; + } + + public void setTypeParameters( + List<ITypeVariableDefinition> typeParameters) { + this.typeParameters = typeParameters; + } + + @Override + public int hashCode() { + return SigClassDefinition.hashCode(this); + } + + public static int hashCode(IClassDefinition definition) { + // FIXME find out why name and packageName are null during + // de-serialization some cases + // replace the following lines with: + // return definition.getQualifiedName().hashCode(); + final int prime = 31; + int result = 1; + result = prime + + ((definition.getName() == null) ? 0 : definition.getName() + .hashCode()); + result = prime + * result + + ((definition.getPackageName() == null) ? 0 : definition + .getPackageName().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + return SigClassDefinition.equals(this, obj); + } + + public static boolean equals(IClassDefinition thiz, Object obj) { + if (thiz == obj) return true; + if (obj instanceof IClassDefinition) { + IClassDefinition that = (IClassDefinition) obj; + return thiz.getName().equals(that.getName()) + && thiz.getPackageName().equals(that.getPackageName()); + } + return false; + } + + @Override + public String toString() { + return SigClassDefinition.toString(this); + } + + public static String toString(IClassDefinition type) { + StringBuilder builder = new StringBuilder(); + if (type.getAnnotations() != null && !type.getAnnotations().isEmpty()) { + // FIXME print annotations builder.append(super.toString()); + builder.append("\n"); + } + builder.append(type.getQualifiedName()); + if (type.getTypeParameters() != null + && (!type.getTypeParameters().isEmpty())) { + builder.append("<"); + ModelUtil.separate(type.getTypeParameters(), ", "); + builder.append(">"); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigClassReference.java b/tools/signature-tools/src/signature/model/impl/SigClassReference.java new file mode 100644 index 00000000000..d4336dec7c4 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigClassReference.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IClassDefinition; +import signature.model.IClassReference; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class SigClassReference implements IClassReference, Serializable { + + private final IClassDefinition definition; + + public SigClassReference(IClassDefinition definition) { + this.definition = definition; + } + + public IClassDefinition getClassDefinition() { + return definition; + } + + @Override + public boolean equals(Object obj) { + return SigClassReference.equals(this, obj); + } + + public static boolean equals(IClassReference thiz, Object that) { + if (that instanceof IClassReference) { + return thiz.getClassDefinition().equals( + ((IClassReference) that).getClassDefinition()); + } + return false; + } + + @Override + public int hashCode() { + return SigClassReference.hashCode(this); + } + + public static int hashCode(IClassReference thiz) { + return thiz.getClassDefinition().hashCode(); + } + + @Override + public String toString() { + return SigClassReference.toString(this); + } + + public static String toString(IClassReference thiz) { + return "-> " + thiz.getClassDefinition().getQualifiedName(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigConstructor.java b/tools/signature-tools/src/signature/model/impl/SigConstructor.java new file mode 100644 index 00000000000..1da30260946 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigConstructor.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; + +import signature.model.IConstructor; +import signature.model.Modifier; +import signature.model.util.ModelUtil; + +@SuppressWarnings("serial") +public class SigConstructor extends SigExecutableMember implements + IConstructor, Serializable { + + public SigConstructor(String name) { + super(name); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(super.toString()); + builder.append(" "); + builder.append(Modifier.toString(getModifiers())); + if (getTypeParameters() != null && !getTypeParameters().isEmpty()) { + builder.append("<"); + builder.append(ModelUtil.separate(getTypeParameters(), ", ")); + builder.append("> "); + } + builder.append(getName()); + builder.append("("); + builder.append(getParameters().isEmpty() ? "" : ModelUtil.separate( + getParameters(), ", ")); + builder.append(")"); + if (getExceptions() != null && !getExceptions().isEmpty()) { + builder.append(" throws "); + builder.append(ModelUtil.separate(getExceptions(), " ")); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java b/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java new file mode 100644 index 00000000000..2878988a6e0 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IEnumConstant; + +@SuppressWarnings("serial") +public class SigEnumConstant extends SigField implements IEnumConstant { + + private static final int UNKNOWN = -1; + + private int ordinal = UNKNOWN; + + public SigEnumConstant(String name) { + super(name); + } + + public int getOrdinal() { + if (ordinal == UNKNOWN) { + throw new UnsupportedOperationException(); + } + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java b/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java new file mode 100644 index 00000000000..3203d5957e7 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IClassDefinition; +import signature.model.IExecutableMember; +import signature.model.IParameter; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.Modifier; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +@SuppressWarnings("serial") +public abstract class SigExecutableMember extends SigAnnotatableElement + implements IExecutableMember, Serializable { + + private String name; + private List<IParameter> parameters = Uninitialized.unset(); + private Set<ITypeReference> exceptions = Uninitialized.unset(); + private Set<Modifier> modifiers = Uninitialized.unset(); + private List<ITypeVariableDefinition> typeParameters = Uninitialized + .unset(); + private IClassDefinition declaringClass = Uninitialized.unset(); + + public SigExecutableMember(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List<IParameter> getParameters() { + return parameters; + } + + public void setParameters(List<IParameter> parameters) { + this.parameters = parameters; + } + + public Set<ITypeReference> getExceptions() { + return exceptions; + } + + public void setExceptions(Set<ITypeReference> exceptions) { + this.exceptions = exceptions; + } + + public Set<Modifier> getModifiers() { + return modifiers; + } + + public void setModifiers(Set<Modifier> modifiers) { + this.modifiers = modifiers; + } + + public List<ITypeVariableDefinition> getTypeParameters() { + return typeParameters; + } + + public void setTypeParameters( + List<ITypeVariableDefinition> typeParameters) { + this.typeParameters = typeParameters; + } + + public IClassDefinition getDeclaringClass() { + return declaringClass; + } + + public void setDeclaringClass(IClassDefinition declaringClass) { + this.declaringClass = declaringClass; + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigField.java b/tools/signature-tools/src/signature/model/impl/SigField.java new file mode 100644 index 00000000000..e3055667019 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigField.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IField; +import signature.model.ITypeReference; +import signature.model.Modifier; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Set; + +@SuppressWarnings("serial") +public class SigField extends SigAnnotatableElement implements IField, + Serializable { + + private String name; + private ITypeReference type = Uninitialized.unset(); + private Set<Modifier> modifiers = Uninitialized.unset(); + + public SigField(String name) { + this.name = name; + modifiers = Collections.emptySet(); + } + + public String getName() { + return name; + } + + public Set<Modifier> getModifiers() { + return modifiers; + } + + public void setModifiers(Set<Modifier> modifiers) { + this.modifiers = modifiers; + } + + public ITypeReference getType() { + return type; + } + + public void setType(ITypeReference type) { + this.type = type; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + if (getAnnotations() != null && !getAnnotations().isEmpty()) { + builder.append(super.toString()); + builder.append("\n"); + } + builder.append(Modifier.toString(getModifiers())); + builder.append(getType().toString()); + builder.append(" "); + builder.append(getName()); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigMethod.java b/tools/signature-tools/src/signature/model/impl/SigMethod.java new file mode 100644 index 00000000000..489397f3411 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigMethod.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; + +import signature.model.IMethod; +import signature.model.ITypeReference; +import signature.model.Modifier; +import signature.model.util.ModelUtil; + +@SuppressWarnings("serial") +public class SigMethod extends SigExecutableMember implements IMethod, + Serializable { + + private ITypeReference returnType = Uninitialized.unset(); + + public SigMethod(String name) { + super(name); + } + + + public ITypeReference getReturnType() { + return returnType; + } + + public void setReturnType(ITypeReference returnType) { + this.returnType = returnType; + } + + @Override + public String toString() { + return SigMethod.toString(this); + } + + public static String toString(IMethod method) { + StringBuilder builder = new StringBuilder(); + builder.append(Modifier.toString(method.getModifiers())); + builder.append(method.getReturnType()); + builder.append(" "); + if (method.getTypeParameters() != null + && !method.getTypeParameters().isEmpty()) { + builder.append("<"); + builder + .append(ModelUtil + .separate(method.getTypeParameters(), ", ")); + builder.append("> "); + } + builder.append(method.getName()); + builder.append("("); + builder.append(method.getParameters().isEmpty() ? "" : ModelUtil + .separate(method.getParameters(), ", ")); + builder.append(")"); + if (method.getExceptions() != null + && !method.getExceptions().isEmpty()) { + builder.append(" throws "); + builder.append(ModelUtil.separate(method.getExceptions(), " ")); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigPackage.java b/tools/signature-tools/src/signature/model/impl/SigPackage.java new file mode 100644 index 00000000000..686917ca275 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigPackage.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IClassDefinition; +import signature.model.IPackage; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +@SuppressWarnings("serial") +public class SigPackage extends SigAnnotatableElement implements IPackage, + Serializable { + + private String name; + private Set<IClassDefinition> classes = Uninitialized.unset(); + + public SigPackage(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List<String> getPackageFragments() { + return Arrays.asList(name.split("\\.")); + } + + public Set<IClassDefinition> getClasses() { + return classes; + } + + public void setClasses(Set<IClassDefinition> classes) { + this.classes = classes; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("package: "); + builder.append(getName()); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigParameter.java b/tools/signature-tools/src/signature/model/impl/SigParameter.java new file mode 100644 index 00000000000..d9d33698185 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigParameter.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IParameter; +import signature.model.ITypeReference; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class SigParameter extends SigAnnotatableElement implements IParameter, + Serializable { + + private ITypeReference type; + + public SigParameter(ITypeReference type) { + this.type = type; + } + + public ITypeReference getType() { + return type; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(super.toString()); + builder.append(" "); + builder.append(getType().toString()); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java b/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java new file mode 100644 index 00000000000..d72613548fd --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IClassReference; +import signature.model.IParameterizedType; +import signature.model.ITypeReference; +import signature.model.util.ModelUtil; + +import java.io.Serializable; +import java.util.List; + +@SuppressWarnings("serial") +public class SigParameterizedType implements IParameterizedType, Serializable { + + private ITypeReference ownerType; + private IClassReference rawType; + private List<ITypeReference> typeArguments; + + public SigParameterizedType(ITypeReference ownerType, + IClassReference rawType, List<ITypeReference> typeArguments) { + this.ownerType = ownerType; + this.rawType = rawType; + this.typeArguments = typeArguments; + } + + public ITypeReference getOwnerType() { + ITypeReference returnValue = ownerType; + if (returnValue == null) { + if (rawType.getClassDefinition().getDeclaringClass() != null) { + returnValue = new SigClassReference(rawType + .getClassDefinition().getDeclaringClass()); + } + } + return returnValue; + } + + public IClassReference getRawType() { + return rawType; + } + + public List<ITypeReference> getTypeArguments() { + return typeArguments; + } + + @Override + public int hashCode() { + return hashCode(this); + } + + public static int hashCode(IParameterizedType type) { + final int prime = 31; + int result = 1; + result = prime * type.getRawType().hashCode(); + result = prime * result + type.getTypeArguments().hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + return equals(this, obj); + } + + public static boolean equals(IParameterizedType thiz, Object that) { + if (!(that instanceof IParameterizedType)) { + return false; + } + IParameterizedType other = (IParameterizedType) that; + if (thiz.getOwnerType() == null) { + if (other.getOwnerType() != null) { + return false; + } + } else if (Uninitialized.isInitialized(thiz.getOwnerType())) { + if (!Uninitialized.isInitialized(other.getOwnerType())) { + return false; + } + } else if (!thiz.getOwnerType().equals(other.getOwnerType())) { + return false; + } + if (!thiz.getRawType().equals(other.getRawType())) { + return false; + } + if (!thiz.getTypeArguments().equals(other.getTypeArguments())) { + return false; + } + return true; + } + + + @Override + public String toString() { + return SigParameterizedType.toString(this); + } + + public static String toString(IParameterizedType type) { + StringBuilder builder = new StringBuilder(); + if (type.getOwnerType() != null) { + builder.append(type.getOwnerType().toString()); + builder.append("::"); + } + builder.append(type.getRawType()); + builder.append("<"); + builder.append(ModelUtil.separate(type.getTypeArguments(), ", ")); + builder.append(">"); + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java b/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java new file mode 100644 index 00000000000..27861694a93 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java @@ -0,0 +1,49 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.model.impl;
+
+import signature.model.IPrimitiveType;
+
+public enum SigPrimitiveType implements IPrimitiveType {
+ VOID_TYPE("void"), BOOLEAN_TYPE("boolean"), BYTE_TYPE("byte"), CHAR_TYPE(
+ "char"), SHORT_TYPE("short"), INT_TYPE("int"), LONG_TYPE("long"),
+ FLOAT_TYPE("float"), DOUBLE_TYPE("double");
+
+ private String name;
+
+ private SigPrimitiveType(String name) {
+ this.name = name;
+ }
+
+ public static SigPrimitiveType valueOfTypeName(String name) {
+ for (SigPrimitiveType primitive : values()) {
+ if (primitive.name.equals(name)) {
+ return primitive;
+ }
+ }
+ throw new IllegalArgumentException(name + " is not a primitive type");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java b/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java new file mode 100644 index 00000000000..e0f918e425b --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.IGenericDeclaration; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.util.ModelUtil; + +import java.io.Serializable; +import java.util.List; + +@SuppressWarnings("serial") +public class SigTypeVariableDefinition implements ITypeVariableDefinition, + Serializable { + + private String name; + private IGenericDeclaration genericDeclaration; + private List<ITypeReference> upperBounds = Uninitialized.unset(); + + public SigTypeVariableDefinition(String name, + IGenericDeclaration genericDeclaration) { + this.name = name; + this.genericDeclaration = genericDeclaration; + } + + public String getName() { + return name; + } + + public IGenericDeclaration getGenericDeclaration() { + return genericDeclaration; + } + + public List<ITypeReference> getUpperBounds() { + return upperBounds; + } + + public void setUpperBounds(List<ITypeReference> upperBounds) { + this.upperBounds = upperBounds; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(name); + if (getUpperBounds().size() != 1) { + builder.append(ModelUtil.separate(getUpperBounds(), ", ")); + } else { + if (!ModelUtil.isJavaLangObject(getUpperBounds().get(0))) { + builder.append(getUpperBounds().get(0)); + } + } + return builder.toString(); + } + +} diff --git a/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java b/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java new file mode 100644 index 00000000000..6bd25936448 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.io.Serializable; + +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; + +@SuppressWarnings("serial") +public class SigTypeVariableReference implements ITypeVariableReference, + Serializable { + + private ITypeVariableDefinition definition; + + public SigTypeVariableReference(ITypeVariableDefinition definition) { + this.definition = definition; + } + + public ITypeVariableDefinition getTypeVariableDefinition() { + return definition; + } + + @Override + public boolean equals(Object obj) { + if (getClass() == obj.getClass()) { + return getTypeVariableDefinition().equals( + ((ITypeVariableReference) obj).getTypeVariableDefinition()); + } + return false; + } + + @Override + public int hashCode() { + return getTypeVariableDefinition().hashCode(); + } + + @Override + public String toString() { + return getTypeVariableDefinition().getName(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/SigWildcardType.java b/tools/signature-tools/src/signature/model/impl/SigWildcardType.java new file mode 100644 index 00000000000..c24ac238863 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/SigWildcardType.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import signature.model.ITypeReference; +import signature.model.IWildcardType; + +import java.io.Serializable; +import java.util.List; + +@SuppressWarnings("serial") +public class SigWildcardType implements IWildcardType, Serializable { + + private ITypeReference lowerBound; + private List<ITypeReference> upperBounds; + + public SigWildcardType(ITypeReference lowerBound, + List<ITypeReference> upperBounds) { + this.lowerBound = lowerBound; + this.upperBounds = upperBounds; + } + + public ITypeReference getLowerBound() { + return lowerBound; + } + + public List<ITypeReference> getUpperBounds() { + return upperBounds; + } + + @Override + public int hashCode() { + return SigWildcardType.hashCode(this); + } + + public static int hashCode(IWildcardType type) { + final int prime = 31; + int result = 1; + result = prime + + ((type.getLowerBound() == null) ? 0 : type.getLowerBound() + .hashCode()); + result = prime * result + type.getUpperBounds().hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + return SigWildcardType.equals(this, obj); + } + + public static boolean equals(IWildcardType thiz, Object obj) { + if (thiz == obj) return true; + if (obj == null) return false; + if (!(obj instanceof IWildcardType)) return false; + IWildcardType that = (IWildcardType) obj; + if (thiz.getLowerBound() == null) { + if (that.getLowerBound() != null) return false; + } else if (!thiz.getLowerBound().equals(that.getLowerBound())) + return false; + if (!thiz.getUpperBounds().equals(that.getUpperBounds())) return false; + return true; + } + + + @Override + public String toString() { + return SigWildcardType.toString(this); + } + + public static String toString(IWildcardType thiz) { + StringBuilder builder = new StringBuilder(); + builder.append("?"); + if (thiz.getLowerBound() != null) { + builder.append(" "); + builder.append(" super "); + builder.append(thiz.getLowerBound()); + } + if (!thiz.getUpperBounds().isEmpty()) { + builder.append(" extends "); + builder.append(thiz.getUpperBounds()); + } + return builder.toString(); + } +} diff --git a/tools/signature-tools/src/signature/model/impl/Uninitialized.java b/tools/signature-tools/src/signature/model/impl/Uninitialized.java new file mode 100644 index 00000000000..cc88479a178 --- /dev/null +++ b/tools/signature-tools/src/signature/model/impl/Uninitialized.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.impl; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.List; +import java.util.Set; + +import signature.model.IAnnotationField; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IPackage; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; +import signature.model.Kind; + +/** + * + */ +public class Uninitialized { + + private static final Object UNINITIALIZED; + + static { + UNINITIALIZED = Proxy.newProxyInstance(Uninitialized.class + .getClassLoader(), new Class[] { + ITypeReference.class, IPackage.class, IClassDefinition.class, + IClassReference.class, ITypeVariableReference.class, + ITypeVariableDefinition.class, IAnnotationField.class, + Set.class, List.class}, new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + if (method.getName().equals("toString")) { + return "Uninitialized"; + } + + throw new UnsupportedOperationException(); + } + }); + } + + @SuppressWarnings("unchecked") + public static <T> T unset() { + return (T) UNINITIALIZED; + } + + public static boolean isInitialized(Object o) { + return o != UNINITIALIZED && o != Kind.UNINITIALIZED; + } +} diff --git a/tools/signature-tools/src/signature/model/util/ITypeFactory.java b/tools/signature-tools/src/signature/model/util/ITypeFactory.java new file mode 100644 index 00000000000..af3e3a9413a --- /dev/null +++ b/tools/signature-tools/src/signature/model/util/ITypeFactory.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.util; + +import signature.model.IClassReference; +import signature.model.IGenericDeclaration; +import signature.model.ITypeReference; +import signature.model.ITypeVariableReference; +import signature.model.impl.SigArrayType; +import signature.model.impl.SigClassDefinition; +import signature.model.impl.SigParameterizedType; +import signature.model.impl.SigTypeVariableDefinition; +import signature.model.impl.SigWildcardType; + +import java.util.List; + +public interface ITypeFactory { + + public static final String JAVA_LANG_OBJECT = "java.lang.Object"; + + /** + * Returns the existing type or creates a new one.<br> + * Format: java.lang.Object + */ + public SigClassDefinition getClass(String packageName, String className); + + public IClassReference getClassReference(String packageName, + String className); + + /** + * Returns the existing array type or creates a new one. + * + * @param componentType + * the component type of the array + * @return the array type + */ + public SigArrayType getArrayType(ITypeReference componentType); + + /** + * Returns the existing parameterized type or creates a new one. + * + * @param ownerType + * the owner of the parameterized type + * @param rawType + * the type which is parameterized + * @param typeArguments + * the type arguments + * @return the parameterized type + */ + public SigParameterizedType getParameterizedType(ITypeReference ownerType, + IClassReference rawType, List<ITypeReference> typeArguments); + + + public boolean containsTypeVariableDefinition(String name, + IGenericDeclaration genericDeclaration); + + /** + * Returns the existing type variable or creates a new one. + * + * @param genericDeclaration + * the declaration site of the variable + * @param name + * the name of the type variable + * @return the type variable + */ + public SigTypeVariableDefinition getTypeVariable(String name, + IGenericDeclaration genericDeclaration); + + public ITypeVariableReference getTypeVariableReference(String name, + IGenericDeclaration genericDeclaration); + + /** + * Returns the existing wildcard type or creates a new one. Wildcard types + * are equal if they have the same lower bound and have the same upper + * bounds. The order of the upper bounds is irrelevant except for the first + * element. <br> + * Note: This does not mean that two values with equal wildcard type can be + * assigned to each other! + * + * @param lowerBound + * the lower bound + * @param upperBounds + * the upper bounds + * @return the wildcard type + */ + public SigWildcardType getWildcardType(ITypeReference lowerBound, + List<ITypeReference> upperBounds); + +} diff --git a/tools/signature-tools/src/signature/model/util/ModelUtil.java b/tools/signature-tools/src/signature/model/util/ModelUtil.java new file mode 100644 index 00000000000..f66fd2c0f5e --- /dev/null +++ b/tools/signature-tools/src/signature/model/util/ModelUtil.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.util; + +import signature.model.IAnnotatableElement; +import signature.model.IAnnotation; +import signature.model.IAnnotationElement; +import signature.model.IAnnotationField; +import signature.model.IApi; +import signature.model.IClassDefinition; +import signature.model.IField; +import signature.model.IPackage; +import signature.model.ITypeReference; + +import java.util.Collection; + +public class ModelUtil { + private ModelUtil() { + } + + /** + * Returns the IClass for the given className.<br> + * Format: a.b.C + * + * @param qualifiedClassName + * the fully qualified class name + * @return the IClass instance or null; + */ + public static IClassDefinition getClass(IPackage aPackage, + String qualifiedClassName) { + for (IClassDefinition clazz : aPackage.getClasses()) { + if (qualifiedClassName.equals(clazz.getName())) { + return clazz; + } + } + return null; + } + + public static IAnnotation getAnnotation(IAnnotatableElement element, + String qualifiedTypeName) { + for (IAnnotation annotation : element.getAnnotations()) { + if (qualifiedTypeName.equals(annotation.getType() + .getClassDefinition().getQualifiedName())) { + return annotation; + } + } + return null; + } + + public static IAnnotationElement getAnnotationElement( + IAnnotation annotation, String elementName) { + for (IAnnotationElement element : annotation.getElements()) { + if (elementName.equals(element.getDeclaringField().getName())) { + return element; + } + } + return null; + } + + public static IField getField(IClassDefinition clazz, String fieldName) { + for (IField field : clazz.getFields()) { + if (fieldName.equals(field.getName())) { + return field; + } + } + return null; + } + + public static IAnnotationField getAnnotationField( + IClassDefinition annotation, String fieldName) { + for (IAnnotationField field : annotation.getAnnotationFields()) { + if (fieldName.equals(field.getName())) { + return field; + } + } + return null; + } + + /** + * Returns the IPackage for the given className.<br> + * Format: a.b + * + * @param api + * the api + * @param packageName + * the name of the package + * @return the IClass instance or null; + */ + public static IPackage getPackage(IApi api, String packageName) { + for (IPackage aPackage : api.getPackages()) { + if (packageName.equals(aPackage.getName())) { + return aPackage; + } + } + return null; + } + + /** + * "a.b.c.A;" -> "a.b.c" "A" -> "" empty string + * + * @param classIdentifier + * @return the package name + */ + public static String getPackageName(String classIdentifier) { + int lastIndexOfSlash = classIdentifier.lastIndexOf('.'); + String packageName = null; + if (lastIndexOfSlash == -1) { + packageName = ""; + } else { + packageName = classIdentifier.substring(0, lastIndexOfSlash); + } + return packageName; + } + + /** + * "a.b.c.A;" -> "A" "A" -> "A" + * + * @param classIdentifier + * fully qualified class name + * @return the class name + */ + public static String getClassName(String classIdentifier) { + int lastIndexOfDot = classIdentifier.lastIndexOf('.'); + String className = null; + if (lastIndexOfDot == -1) { + className = classIdentifier; + } else { + className = classIdentifier.substring(lastIndexOfDot + 1); + } + return className; + } + + + public static String separate(Collection<? extends Object> elements, + String separator) { + StringBuilder s = new StringBuilder(); + boolean first = true; + for (Object object : elements) { + if (!first) { + s.append(separator); + } + s.append(object.toString()); + first = false; + } + return s.toString(); + } + + public static boolean isJavaLangObject(ITypeReference type) { + if (type instanceof IClassDefinition) { + IClassDefinition clazz = (IClassDefinition) type; + if ("java.lang".equals(clazz.getPackageName())) { + return "Object".equals(clazz.getName()); + } + } + return false; + } + +} diff --git a/tools/signature-tools/src/signature/model/util/TypePool.java b/tools/signature-tools/src/signature/model/util/TypePool.java new file mode 100644 index 00000000000..dc481137f03 --- /dev/null +++ b/tools/signature-tools/src/signature/model/util/TypePool.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.model.util; + +import static signature.model.impl.Uninitialized.isInitialized; +import signature.model.IClassReference; +import signature.model.IGenericDeclaration; +import signature.model.ITypeReference; +import signature.model.ITypeVariableReference; +import signature.model.impl.SigArrayType; +import signature.model.impl.SigClassDefinition; +import signature.model.impl.SigClassReference; +import signature.model.impl.SigParameterizedType; +import signature.model.impl.SigTypeVariableDefinition; +import signature.model.impl.SigTypeVariableReference; +import signature.model.impl.SigWildcardType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Pool and factory for all {@link ITypeReference} instances.<br> + * Note: This class is not thread save + */ +public class TypePool implements ITypeFactory { + + /** + * Pool for all SigClass objects. Key format: "java.lang.Object", "a.b.C$D + */ + private Map<String, SigClassDefinition> classPool; + /** Pool for all SigTypeVariable objects */ + private Map<TypeVariableKey, SigTypeVariableDefinition> typeVariablePool; + + public TypePool() { + classPool = new HashMap<String, SigClassDefinition>(); + typeVariablePool = + new HashMap<TypeVariableKey, SigTypeVariableDefinition>(); + } + + public SigClassDefinition getClass(String packageName, String className) { + String key = packageName + "<>" + className; + SigClassDefinition clazz = classPool.get(key); + if (clazz == null) { + clazz = new SigClassDefinition(packageName, className); + classPool.put(key, clazz); + } + return clazz; + } + + public IClassReference getClassReference(String packageName, + String className) { + return new SigClassReference(getClass(packageName, className)); + } + + public SigArrayType getArrayType(ITypeReference componentType) { + assert componentType != null; + return new SigArrayType(componentType); + } + + public SigParameterizedType getParameterizedType(ITypeReference ownerType, + IClassReference rawType, List<ITypeReference> typeArguments) { + assert rawType != null; + assert typeArguments != null; + return new SigParameterizedType(ownerType, rawType, typeArguments); + } + + private static class TypeVariableKey { + private String name; + private IGenericDeclaration genericDeclaration; + + public TypeVariableKey(String name, + IGenericDeclaration genericDeclaration) { + this.genericDeclaration = genericDeclaration; + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + genericDeclaration.hashCode(); + result = prime * result + name.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + TypeVariableKey other = (TypeVariableKey) obj; + if (genericDeclaration != other.genericDeclaration) { + return false; + } + if (!name.equals(other.name)) { + return false; + } + return true; + } + } + + public boolean containsTypeVariableDefinition(String name, + IGenericDeclaration genericDeclaration) { + TypeVariableKey key = new TypeVariableKey(name, genericDeclaration); + return typeVariablePool.get(key) != null; + } + + public SigTypeVariableDefinition getTypeVariable(String name, + IGenericDeclaration genericDeclaration) { + assert name != null; + assert genericDeclaration != null; + + TypeVariableKey key = new TypeVariableKey(name, genericDeclaration); + SigTypeVariableDefinition sigTypeVariable = typeVariablePool.get(key); + if (sigTypeVariable == null) { + sigTypeVariable = new SigTypeVariableDefinition(name, + genericDeclaration); + typeVariablePool.put(key, sigTypeVariable); + } + return sigTypeVariable; + } + + public ITypeVariableReference getTypeVariableReference(String name, + IGenericDeclaration genericDeclaration) { + return new SigTypeVariableReference(getTypeVariable(name, + genericDeclaration)); + } + + public SigWildcardType getWildcardType(ITypeReference lowerBound, + List<ITypeReference> upperBounds) { + assert upperBounds != null; + + SigWildcardType sigWildcardType = new SigWildcardType(lowerBound, + upperBounds); + return sigWildcardType; + } + + public void replaceAllUninitialiezWithNull() { + for (SigClassDefinition clazz : classPool.values()) { + replaceUninitializedWithNull(clazz); + } + } + + private static void replaceUninitializedWithNull( + SigClassDefinition clazz) { + if (clazz == null) { + return; + } + if (!isInitialized(clazz.getAnnotationFields())) { + clazz.setAnnotationFields(null); + } + if (!isInitialized(clazz.getAnnotations())) { + clazz.setAnnotations(null); + } + if (!isInitialized(clazz.getAnnotations())) { + clazz.setAnnotations(null); + } + if (!isInitialized(clazz.getConstructors())) { + clazz.setConstructors(null); + } + if (!isInitialized(clazz.getDeclaringClass())) { + clazz.setDeclaringClass(null); + } + + if (!isInitialized(clazz.getEnumConstants())) { + clazz.setEnumConstants(null); + } + if (!isInitialized(clazz.getFields())) { + clazz.setFields(null); + } + if (!isInitialized(clazz.getInnerClasses())) { + clazz.setInnerClasses(null); + } + if (!isInitialized(clazz.getInterfaces())) { + clazz.setInterfaces(null); + } + if (!isInitialized(clazz.getKind())) { + clazz.setKind(null); + } + if (!isInitialized(clazz.getMethods())) { + clazz.setMethods(null); + } + if (!isInitialized(clazz.getModifiers())) { + clazz.setModifiers(null); + } + if (!isInitialized(clazz.getSuperClass())) { + clazz.setSuperClass(null); + } + if (!isInitialized(clazz.getTypeParameters())) { + clazz.setTypeParameters(null); + } + } +} diff --git a/tools/signature-tools/templates/ApiOverviewPage.st b/tools/signature-tools/templates/ApiOverviewPage.st new file mode 100644 index 00000000000..4faa1935aa9 --- /dev/null +++ b/tools/signature-tools/templates/ApiOverviewPage.st @@ -0,0 +1,60 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd"> +<html> +<head> +$Common_meta()$ +<title> +Android API Differences Report +</title> +<body> +<div class="body"> + +$Header()$ + + +<div class="content"> +<h2>Android API Differences Report</h2> +<p>This document details the changes in the Android framework API. It shows +additions, modifications, and removals for packages, classes, methods, and +fields. Each reference to an API change includes a brief description of the +API and an explanation of the change and suggested workaround, where available.</p> + +<p>The differences described in this report are based a comparison of the APIs +whose versions are specified in the upper-right corner of this page. It compares a +newer "to" API to an older "from" version, noting any changes relative to the +older API. So, for example, indicated API removals are no longer present in the "to" +API.</p> +<p>For more information about the Android framework API and SDK, +see the <a href="http://code.google.com/android/index.html" target="_top">Android product site</a>.</p> + +$if(no_delta)$ +<h3>Congratulation!</h3> +No differences were detected between the two provided APIs. +$endif$ + + +$if(removed_packages)$ +$Table(name="Removed Packages", rows=removed_packages:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + + +$if(added_packages)$ +$Table(name="Added Packages", rows=added_packages:{$it.to:PackageAddedLink()$}:SimpleTableRow())$ +<br/> +$endif$ + +$if(changed_packages)$ +$Table(name="Changed Packages", rows=changed_packages:{$it.to:PackageChangedLink()$}:SimpleTableRow())$ +<br/> +$endif$ +</div> + + +</div> +</body> +</html> + + + + + diff --git a/tools/signature-tools/templates/ClassChangedLink.st b/tools/signature-tools/templates/ClassChangedLink.st new file mode 100644 index 00000000000..20e0ed98e9e --- /dev/null +++ b/tools/signature-tools/templates/ClassChangedLink.st @@ -0,0 +1 @@ +$Link(url={$it.packageName$.$it.name$.html}, name={<tt>$it.name$</tt>})$ diff --git a/tools/signature-tools/templates/ClassOverviewPage.st b/tools/signature-tools/templates/ClassOverviewPage.st new file mode 100644 index 00000000000..45b4c1c67fe --- /dev/null +++ b/tools/signature-tools/templates/ClassOverviewPage.st @@ -0,0 +1,131 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd"> +<html> +<head> +$Common_meta()$ +<title> +$class_delta.to.packageName$.$class_delta.to.name$ +</title> +</head> +<body> + +<div class="body"> + +$Header()$ + +<div class="content"> +<h2>Class $class_delta.to.packageName$.$class_delta.to:ClassReferenceLink()$</h2> +<br/> + +$if(has_class_signature_delta)$ +<table summary="Signature Difference" border="1" width="100%"> + <tr> + <th colspan=3>Signature Difference</th> + </tr> + <tbody> + <tr class="default"> + <td>$SigClassDefinition(element=class_delta.to)$</td> + <td> + $if(class_delta.annotationDeltas)$ $MultiSubDelta(desc="Annotations Changed:", deltas=class_delta.annotationDeltas)$ $endif$ + $if(class_delta.modifierDeltas)$ $MultiSubDelta(desc="Modifiers Changed:", deltas=class_delta.modifierDeltas)$ $endif$ + $if(class_delta.typeVariableDeltas)$ $MultiSubDelta(desc="Type Variables Changed:", deltas=class_delta.typeVariableDeltas)$ $endif$ + $if(class_delta.superClassDelta)$ $SingleSubDelta(desc="Superclass Changed", delta=class_delta.superClassDelta)$ $endif$ + $if(class_delta.interfaceDeltas)$ $MultiSubDelta(desc="Interfaces Changed:", deltas=class_delta.interfaceDeltas)$ $endif$ + </td> + </tr> + </tbody> +</table> +<br/> +$endif$ + +$! Annotation Fields !$ + +$if(removed_annotation_fields)$ +$Table(name="Removed Annotation Fields", rows=removed_annotation_fields:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + +$if(added_annotation_fields)$ +$Table(name="Added Annotation Fields", rows=added_annotation_fields:{$it.to:ModelElementRow()$})$ +<br/> +$endif$ + +$if(changed_annotation_fields)$ +$Table(name="Changed Annotation Fields", rows=changed_annotation_fields:DeltaTableRow())$ +<br/> +$endif$ + + +$! --------Enum Constants-------- !$ + +$if(removed_enum_constants)$ +$Table(name="Removed Enum Constants", rows=removed_enum_constants:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + +$if(added_enum_constants)$ +$Table(name="Added Enum Constants", rows=added_enum_constants:{$it.to:ModelElementRow()$})$ +<br/> +$endif$ + +$if(changed_enum_constants)$ +$Table(name="Changed Enum Constants", rows=changed_enum_constants:DeltaTableRow())$ +<br/> +$endif$ + + +$! Fields !$ + +$if(removed_fields)$ +$Table(name="Removed Fields", rows=removed_fields:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + +$if(added_fields)$ +$Table(name="Added Fields", rows=added_fields:{$it.to:ModelElementRow()$})$ +<br/> +$endif$ + +$if(changed_fields)$ +$Table(name="Changed Fields", rows=changed_fields:DeltaTableRow())$ +<br/> +$endif$ + + +$! Constructors !$ + +$if(removed_constructors)$ +$Table(name="Removed Constructors", rows=removed_constructors:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + +$if(added_constructors)$ +$Table(name="Added Constructors", rows=added_constructors:{$it.to:ModelElementRow()$})$ +<br/> +$endif$ + +$if(changed_constructors)$ +$Table(name="Changed Constructors", rows=changed_constructors:DeltaTableRow())$ +<br/> +$endif$ + + +$! Methods !$ + +$if(removed_methods)$ +$Table(name="Removed Methods", rows=removed_methods:{$it.from:ModelElementRow()$})$ +<br/> +$endif$ + +$if(added_methods)$ +$Table(name="Added Methods", rows=added_methods:{$it.to:ModelElementRow()$})$ +<br/> +$endif$ + +$if(changed_methods)$ +$Table(name="Changed Methods", rows=changed_methods:DeltaTableRow())$ +<br/> +$endif$ +</div> +</div> +</body> +</html>
\ No newline at end of file diff --git a/tools/signature-tools/templates/ClassReferenceLink.st b/tools/signature-tools/templates/ClassReferenceLink.st new file mode 100644 index 00000000000..c22e9b5b3dc --- /dev/null +++ b/tools/signature-tools/templates/ClassReferenceLink.st @@ -0,0 +1 @@ +$Link(url={http://code.google.com/android/reference/$it.packageFragments; separator="/"$/$it.name$.html}, name={<tt>$it.name$</tt>})$ diff --git a/tools/signature-tools/templates/Common_meta.st b/tools/signature-tools/templates/Common_meta.st new file mode 100644 index 00000000000..86637815b35 --- /dev/null +++ b/tools/signature-tools/templates/Common_meta.st @@ -0,0 +1,12 @@ +<meta name="generator" content="Android signature tools v 1.0"> +<meta name="keywords" content="API difference, difference between two APIs, API diff"> +<link type="text/css" rel="stylesheet" href="../styles.css" title="Stylesheet"/> +<link type="text/css" rel="stylesheet" href="styles.css" title="Stylesheet"/> + +<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/codesite/codesite.css"/> +<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/codesite/semantic_headers.css"/> +<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css"/> + + + + diff --git a/tools/signature-tools/templates/DeltaTableRow.st b/tools/signature-tools/templates/DeltaTableRow.st new file mode 100644 index 00000000000..4d0974ce736 --- /dev/null +++ b/tools/signature-tools/templates/DeltaTableRow.st @@ -0,0 +1,8 @@ +<tr class="deltaTableRow"> + <td class="element"> + $ElementType(element=it.to):{<tt>$it$</tt>}$ + </td> + <td class="delta"> + $DeltaTypeSwitch(delta=it)$ + </td> +</tr> diff --git a/tools/signature-tools/templates/Header.st b/tools/signature-tools/templates/Header.st new file mode 100644 index 00000000000..9aa8e2fbddd --- /dev/null +++ b/tools/signature-tools/templates/Header.st @@ -0,0 +1,21 @@ +<div class="header"> + <div class="logo"> + <a href="http://code.google.com/android/documentation.html"><img style="border: 0;" src="http://code.google.com/android/images/android_icon_125.png"/></a> + </div> + <div class="specbox"> + <table> + <tr> + <th colspan="2"> API Diff Specification </th> + </tr> + <tr> + <td>To Version:</td> <td>$to_desc$</td> + </tr> + <tr> + <td>From Version:</td> <td>$from_desc$</td> + </tr> + <tr> + <td>Generated</td> <td>$creation_time$</td> + </tr> + </table> + </div> +</div>
\ No newline at end of file diff --git a/tools/signature-tools/templates/Link.st b/tools/signature-tools/templates/Link.st new file mode 100644 index 00000000000..242109424e2 --- /dev/null +++ b/tools/signature-tools/templates/Link.st @@ -0,0 +1 @@ +<a class="$link_style; null="default"$" href="$url$">$name$</a>
\ No newline at end of file diff --git a/tools/signature-tools/templates/ModelElementRow.st b/tools/signature-tools/templates/ModelElementRow.st new file mode 100644 index 00000000000..54b20c6f511 --- /dev/null +++ b/tools/signature-tools/templates/ModelElementRow.st @@ -0,0 +1,6 @@ +<tr class="deltaTableRow"> + <td class="element"> + $ElementType(element=it):{<tt>$it$</tt>}$ + </td> +</tr> + diff --git a/tools/signature-tools/templates/PackageAddedLink.st b/tools/signature-tools/templates/PackageAddedLink.st new file mode 100644 index 00000000000..eb352da0306 --- /dev/null +++ b/tools/signature-tools/templates/PackageAddedLink.st @@ -0,0 +1 @@ +$Link(url={http://code.google.com/android/reference/$it.packageFragments; separator="/"$/package-summary.html}, name={<tt>$it.name$</tt>})$ diff --git a/tools/signature-tools/templates/PackageChangedLink.st b/tools/signature-tools/templates/PackageChangedLink.st new file mode 100644 index 00000000000..5951f2ab881 --- /dev/null +++ b/tools/signature-tools/templates/PackageChangedLink.st @@ -0,0 +1 @@ +$Link(url={changes/pkg_$it.name$.html}, name={<tt>$it.name$</tt>})$
\ No newline at end of file diff --git a/tools/signature-tools/templates/PackageOverviewPage.st b/tools/signature-tools/templates/PackageOverviewPage.st new file mode 100644 index 00000000000..ebeded0b54d --- /dev/null +++ b/tools/signature-tools/templates/PackageOverviewPage.st @@ -0,0 +1,39 @@ +<!doctype html public "-//w3c//dtd html 4.0 frameset//en""http://www.w3.org/tr/rec-html40/frameset.dtd"> +<html> +<head> +$Common_meta()$ +<title> +Android API Differences Report +</title> +<body> + +<div class="body"> + +$Header()$ + +<div class="content"> + +<h2> +Package $Link(url={http://code.google.com/android/reference/$package_delta.to.packageFragments; separator="/"$/package-summary.html}, name=package_delta.to.name)$ +</h2> + + +$if(removed_classes)$ +$Table(name="Removed Classes and Interfaces", rows=removed_classes:{$it.from:{<tt>$it.name$</tt>}$}:SimpleTableRow())$ +<br/> +$endif$ + + +$if(added_classes)$ +$Table(name="Added Classes and Interfaces", rows=added_classes:{$it.to:ClassReferenceLink()$}:SimpleTableRow())$ +<br/> +$endif$ + +$if(changed_classes)$ +$Table(name="Changed Classes and Interfaces", rows=changed_classes:{$it.to:ClassChangedLink()$}:SimpleTableRow())$ +<br/> +$endif$ +</div> +</div> +</body> +</html>
\ No newline at end of file diff --git a/tools/signature-tools/templates/SimpleTableRow.st b/tools/signature-tools/templates/SimpleTableRow.st new file mode 100644 index 00000000000..3e7e7c2e215 --- /dev/null +++ b/tools/signature-tools/templates/SimpleTableRow.st @@ -0,0 +1,5 @@ +<tr class="default"> + <td> + $it$ + </td> +</tr> diff --git a/tools/signature-tools/templates/Styles.st b/tools/signature-tools/templates/Styles.st new file mode 100644 index 00000000000..4294eb31dd4 --- /dev/null +++ b/tools/signature-tools/templates/Styles.st @@ -0,0 +1,44 @@ +/* + * Noser signature html output v$version$ + */ + +/* default link style*/ +a.default:link {color: blue; text-decoration: none} +a.default:hover {color: blue; text-decoration: underline;} +a.default:visited {color: blue; text-decoration: none} + +/* discreet link style */ +a.discreet:link {color: black; text-decoration: none} +a.discreet:visited {color: black; text-decoration: none} +a.discreet:hover {color: black; text-decoration: underline;} + +ul { + list-style-type: none +} + +.body { + margin: 10px; +} + +.header { + position:relative; + width: 100%; + +} + +.logo { + left:0px; +} +.specbox { + position:absolute; + right:0px; + top:0px; +} + +.content { + width: 100%; + position: relative; + top:75px; +} + + diff --git a/tools/signature-tools/templates/Table.st b/tools/signature-tools/templates/Table.st new file mode 100644 index 00000000000..2eecb8eaf7a --- /dev/null +++ b/tools/signature-tools/templates/Table.st @@ -0,0 +1,9 @@ +<table summary="$name$" border="1" width="100%"> +<tr> + <th COLSPAN=2>$name$</th> +</tr> +<tbody> +$rows$ +</tbody> +</table> + diff --git a/tools/signature-tools/templates/delta/deltas.stg b/tools/signature-tools/templates/delta/deltas.stg new file mode 100644 index 00000000000..a27d64129a4 --- /dev/null +++ b/tools/signature-tools/templates/delta/deltas.stg @@ -0,0 +1,149 @@ +group deltas; + + +ADDED(delta) ::= "Added $ElementType(element=delta.to)$" + + +REMOVED(delta) ::= "Removed $ElementType(element=delta.from)$" + + +CHANGED(delta) ::= "$DeltaType(delta)$" + + +DeltaType(delta) ::= "$({$delta.class.simpleName$})(delta)$" + + +DeltaTypeSwitch(delta) ::= "$delta:({$delta.type$})(delta)$" + + +MultiSubDelta(desc, deltas) ::= << +$if(deltas)$ +$if(!deltas.empty)$ +$desc$ +<ul> +$deltas:{<li>$DeltaTypeSwitch(delta=it)$</li>}$ +</ul> +$endif$ +$endif$ +>> + + +SigAnnotationDelta(delta) ::= << +$MultiSubDelta(desc="Annotation Elements changed:", deltas=delta.annotationElementDeltas)$ +>> + + + +SigAnnotationElementDelta(delta) ::= << +$SingleSubDelta(desc="Value changed:", delta=delta.valueDelta)$ +>> + + +SigArrayTypeDelta(delta) ::= << +$SingleSubDelta(desc="Component Type of array changed:", delta=delta.componentTypeDelta)$ +>> + + +SigClassReferenceDelta(delta) ::= "from $SigClass(element=delta.from)$ to $SigClass(element=delta.to)$" + + +SigConstructorDelta(delta) ::= "$SigExecutableMemberDelta(delta=delta)$" + +SigMethodDelta(delta) ::= << +$SigExecutableMemberDelta(delta=delta)$ +$if(delta.returnTypeDelta)$ +$SingleSubDelta(desc="Return Type changed:", delta=delta.returnTypeDelta)$ +$endif$ +>> + + +SigExecutableMemberDelta(delta) ::= << +$if(delta.annotationDeltas)$ +$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$ +$endif$ + +$if(delta.modifierDeltas)$ +$MultiSubDelta(desc="Modifiers changed:", deltas=delta.modifierDeltas)$ +$endif$ + +$if(delta.typeVariableDeltas)$ +$MultiSubDelta(desc="Type Variables changed:", deltas=delta.typeVariableDeltas)$ +$endif$ + +$if(delta.exceptionDeltas)$ +$MultiSubDelta(desc="Exceptions changed:", deltas=delta.exceptionDeltas)$ +$endif$ + +$if(delta.parameterDeltas)$ +$MultiSubDelta(desc="Parameters changed:", deltas=delta.parameterDeltas)$ +$endif$ +>> + +SigFieldDelta(delta) ::= << +$SingleSubDelta(desc="Type changed:", delta=delta.typeDelta)$ +$MultiSubDelta(desc="Modifiers changed:", deltas=delta.modifierDeltas)$ +$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$ +>> + +SigGenericDelclarationDelta(delta) ::= "GenericDelclarationDelta $delta$" + +SigModifierDelta(delta) ::= "SigModifierDelta.st: Please file a bug if you see this message" + + +SigParameterDelta(delta) ::= << +$if(delta.annotationDeltas)$ +$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$ +$endif$ + +$if(delta.typeDelta)$ +$SingleSubDelta(desc="Type changed:", delta=delta.typeDelta)$ +$endif$ +>> + + +SigParameterizedTypeDelta(delta) ::= << +$SingleSubDelta(desc="Owner Type changed:", delta=delta.ownerTypeDelta)$ +$SingleSubDelta(desc="Raw Type changed:", delta=delta.rawTypeDelta)$ +$MultiSubDelta(desc="Type Arguments changed:", deltas=delta.argumentTypeDeltas)$ +>> + + +SigPrimitiveTypeDelta(delta) ::= "from $delta.from$ to $delta.to$" + +SigTypeDelta(delta) ::= "from $ElementType(element=delta.from)$ to $ElementType(element=delta.to)$" + +SigTypeVariableReferenceDelta(delta) ::= << +SigTypeVariableReferenceDelta: +$delta$ +>> + +SigTypeVariableDefinitionDelta(delta) ::= << +$SingleSubDelta(desc="Upper Bound changed:", delta=delta.upperBoundsDelta)$ +$SingleSubDelta(desc="Declaration changed:", delta=delta.genericDeclarationDelta)$ +>> + +SigUpperBoundsDelta(delta) ::= << +$SingleSubDelta(desc="First Upper Bound changed:", delta=delta.firstUpperBoundDelta)$ +$MultiSubDelta(desc="Upper Bounds changed:", deltas=delta.remainingUpperBoundDeltas)$ +>> + +SigWildcardTypeDelta(delta) ::= << +$SingleSubDelta(desc="Lower Bound changed:", delta=delta.lowerBoundDelta)$ +$SingleSubDelta(desc="Upper Bounds changed:", delta=delta.upperBoundDelta)$ +>> + +SigAnnotationFieldDelta(delta) ::= << +$SigFieldDelta(delta = delta)$ +$SingleSubDelta(desc="Default value changed:", delta=delta.defaultValueDelta)$ +>> + +SingleSubDelta(desc, delta) ::= << +$if(delta)$ +$desc$ +<ul> + <li>$DeltaTypeSwitch(delta=delta)$</li> +</ul> +$endif$ +>> + + diff --git a/tools/signature-tools/templates/model/model.stg b/tools/signature-tools/templates/model/model.stg new file mode 100644 index 00000000000..425ad36bf3d --- /dev/null +++ b/tools/signature-tools/templates/model/model.stg @@ -0,0 +1,135 @@ +group model; + +ElementType(element) ::= << +$({$element.class.simpleName$})(element = element)$ +>> + +Modifier(element) ::= << +$element$ +>> + +SigAnnotation(element) ::= << +@$ElementType(element = element.type)$ +$if(element.elements)$ +{$element.elements:{$SigAnnotationElement(element=it)$}$} +$endif$ +>> + +SigAnnotationElement(element) ::= << +$element.declaringField.name$=$element.value$ +>> + +SigAnnotationField(element) ::= << +$SigField(element = element)$ $if(element.defaultValue)$ default=$element.defaultValue$$endif$ +>> + +SigArrayType(element) ::= << +$ElementType(element = element.componentType)$[] +>> + + +SigClassDefinition(element) ::= << +$Annotations(element = element)$ +$Modifiers(element = element)$$element.kind$ $element:ClassReferenceLink(link_style="discreet")$ +$TypeParameters(element = element)$ +$if(element.superClass)$ extends $ElementType(element=element.superClass)$$endif$ +$if(element.interfaces)$ implements $element.interfaces:{$ElementType(element=it)$}; separator=", "$$endif$ +>> + +ClassReferenceProjection(element) ::= << +$SigClassReference(element= element)$ +>> + +SigClassReference(element) ::= << +$ClassReferenceLink(it = element.classDefinition, link_style="discreet")$ +>> + +SigConstructor(element) ::= << +$Annotations(element= element, separator=" ")$ +$Modifiers(element= element)$ +$TypeParameters(element= element)$ +$SigExecutableMember(element= element)$ +>> + +//FIXME add SigEnumConstantReference to format correct in either case +SigEnumConstant(element) ::= << +enum constant $ElementType(element=element.type)$.$element.name$ +>> + +SigExecutableMember(element) ::= << +$element.name$($element.parameters:{$SigParameter(element=it)$}; separator=", "$) +$if(element.exceptions)$ throws $element.exceptions:{$ElementType(element=it)$}; separator=", "$$endif$ +>> + +SigField(element) ::= << +$Annotations(element = element, separator="<br/>")$ +$Modifiers(element = element)$$ElementType(element=element.type)$ $element.name$ +>> + +MethodProjection(element) ::= << +$SigMethod(element=element)$ +>> + +SigMethod(element) ::= << +$Annotations(element=element)$ +$Modifiers(element=element)$ +$TypeParameters(element=element)$ +$ElementType(element=element.returnType)$ $SigExecutableMember(element = element)$ +>> + +SigPackage(element) ::= << +$element.name$ +>> + +SigParameter(element) ::= << +$Annotations(element = element, separator=" ")$ +$ElementType(element=element.type)$ +>> + +ParameterizedTypeProjection(element) ::= << +$SigParameterizedType(element = element)$ +>> + +SigParameterizedType(element) ::= << +$if(element.ownerType)$$ElementType(element=element.ownerType)$$endif$ +$SigClassReference(element=element.rawType)$ +$if(element.typeArguments)$<$element.typeArguments:{$ElementType(element=it)$}$>$endif$ +>> + +SigPrimitiveType(element) ::= << +$element.name$ +>> + +SigTypeVariableDefinition(element) ::= << +$element.name$$if(!element.upperBounds.empty)$ extends $element.upperBounds:{$ElementType(element=it)$}; separator=", "$$endif$ +>> + +SigTypeVariableReference(element) ::= << +$element.typeVariableDefinition.name$ +>> + +SigWildcardType(element) ::= << +? +$if(element.lowerBound)$ super $ElementType(element=element.lowerBound)$$endif$ +$if(!element.upperBounds.empty)$ extends $element.upperBounds:{$ElementType(element=it)$}; separator=", "$$endif$ +>> + + +/* helper templates*/ + +Modifiers(element) ::= << +$if(element.modifiers)$ +$element.modifiers; separator=" "$$\ $ +$endif$ +>> + +Annotations(element, separator) ::= << +$if(element.annotations)$ +$element.annotations:{$SigAnnotation(element=it)$}; separator=separator$ +$separator$ +$endif$ +>> + +TypeParameters(element) ::= << +$if(element.typeParameters)$ <$element.typeParameters:{$SigTypeVariableDefinition(element=it)$}; separator=", "$>$endif$ +>> diff --git a/tools/signature-tools/test/signature/comparator/AllDexTests.java b/tools/signature-tools/test/signature/comparator/AllDexTests.java new file mode 100644 index 00000000000..b44dcb6b1f2 --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/AllDexTests.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import signature.converter.dex.DexTestConverter; +import signature.converter.util.ITestSourceConverter; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AllDexTests.DexPackageCompareTest.class, + AllDexTests.DexClassCompareTest.class, + AllDexTests.DexMethodCompareTests.class, + AllDexTests.DexAnnotationCompareTest.class +}) +public class AllDexTests { + private static ITestSourceConverter newConverter(){ + return new DexTestConverter(); + } + + public static class DexPackageCompareTest extends PackageCompareTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class DexClassCompareTest extends ClassCompareTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class DexMethodCompareTests extends MethodCompareTests { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class DexAnnotationCompareTest extends AnnotationCompareTest{ + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + +}
\ No newline at end of file diff --git a/tools/signature-tools/test/signature/comparator/AllDocletTests.java b/tools/signature-tools/test/signature/comparator/AllDocletTests.java new file mode 100644 index 00000000000..327d93139e8 --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/AllDocletTests.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import signature.converter.doclet.DocletTestConverter; +import signature.converter.util.ITestSourceConverter; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AllDocletTests.DocletPackageCompareTest.class, + AllDocletTests.DocletClassCompareTest.class, + AllDocletTests.DocletMethodCompareTests.class +}) +public class AllDocletTests { + private static ITestSourceConverter newConverter(){ + return new DocletTestConverter(); + } + + public static class DocletPackageCompareTest extends PackageCompareTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class DocletClassCompareTest extends ClassCompareTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class DocletMethodCompareTests extends MethodCompareTests { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } +}
\ No newline at end of file diff --git a/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java b/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java new file mode 100644 index 00000000000..c72b6372821 --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import signature.comparator.util.AbstractComparatorTest; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; + +import java.io.IOException; + +public abstract class AnnotationCompareTest extends AbstractComparatorTest { + + @Test + public void testAnnotationValue() throws IOException{ + CompilationUnit A0 = new CompilationUnit("a.A0", + "package a; " + + "public @interface A0 {" + + " A1 value() default @A1;" + + "}"); + CompilationUnit A1 = new CompilationUnit("a.A1", + "package a; " + + "public @interface A1 {" + + "}"); + CompilationUnit AnnotBDefault = new CompilationUnit("a.B", + "package a; " + + "@A0 " + + "public class B {}"); + CompilationUnit AnnotB = new CompilationUnit("a.B", + "package a; " + + "@A0 " + + "public class B {}"); + IApi fromApi = convert(A0, A1, AnnotBDefault); + IApi toApi = convert(A0, A1, AnnotB); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void testDefaultAnnotationValue() throws IOException{ + CompilationUnit A0 = new CompilationUnit("a.A0", + "package a; " + + "public @interface A0 {" + + " String value() default \"bla\";" + + "}"); + CompilationUnit A1 = new CompilationUnit("a.A0", + "package a; " + + "public @interface A0 {" + + " String value();" + + "}"); + IApi fromApi = convert(A0); + IApi toApi = convert(A1); + assertNotNull(compare(fromApi, toApi)); + } +} diff --git a/tools/signature-tools/test/signature/comparator/ClassCompareTest.java b/tools/signature-tools/test/signature/comparator/ClassCompareTest.java new file mode 100644 index 00000000000..71719780edc --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/ClassCompareTest.java @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import org.junit.Test; + +import signature.comparator.util.AbstractComparatorTest; +import signature.compare.model.IAnnotationDelta; +import signature.compare.model.IApiDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.DeltaType; +import signature.compare.model.ITypeReferenceDelta; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Set; + +public abstract class ClassCompareTest extends AbstractComparatorTest { + + @Test + public void compareEqualClasses() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B {}"); + IApi fromApi = convert(A, B); + IApi toApi = convert(A, B); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void compareMissingClass() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B {}"); + IApi fromApi = convert(A, B); + IApi toApi = convert(A); + + IApiDelta delta = compare(fromApi, toApi); + IClassDefinitionDelta classDelta = getSingleClassDelta(delta); + assertSame(DeltaType.REMOVED, classDelta.getType()); + } + + @Test + public void compareAddedClass() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B {}"); + IApi fromApi = convert(A); + IApi toApi = convert(A, B); + + IApiDelta delta = compare(fromApi, toApi); + IClassDefinitionDelta classDelta = getSingleClassDelta(delta); + assertSame(DeltaType.ADDED, classDelta.getType()); + } + + @Test + public void compareAnnotationsOnClass() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit AnnotA = new CompilationUnit("a.A", + "package a; " + + "@Deprecated " + + "public class A {}"); + IApi fromApi = convert(A); + IApi toApi = convert(AnnotA); + + IApiDelta delta = compare(fromApi, toApi); + IClassDefinitionDelta classDelta = getSingleClassDelta(delta); + + System.out.println(classDelta); + + Set<IAnnotationDelta> annotationDeltas = classDelta.getAnnotationDeltas(); + assertEquals(1, annotationDeltas.size()); + + IAnnotationDelta annotationDelta = annotationDeltas.iterator().next(); + assertSame(DeltaType.ADDED, annotationDelta.getType()); + } + + @Test + public void compareDefaultedAnnotationElementOnClass() throws IOException{ + CompilationUnit annot = new CompilationUnit("a.A", + "package a; " + + "public @interface A {" + + " String name() default \"NAME\" ;" + + "}"); + CompilationUnit AnnotBDefault = new CompilationUnit("a.B", + "package a; " + + "@A " + + "public class B {}"); + CompilationUnit AnnotB = new CompilationUnit("a.B", + "package a; " + + "@A(name=\"NAME\") " + + "public class B {}"); + IApi fromApi = convert(annot, AnnotBDefault); + IApi toApi = convert(annot, AnnotB); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void compareSameInterfaces() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A implements Comparable<String>{ " + + " public int compareTo(String another){return 0;}" + + "}"); + IApi fromApi = convert(A); + IApi toApi = convert(A); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void compareMissingInterface() throws IOException{ + CompilationUnit A0 = new CompilationUnit("a.A", + "package a; " + + "public class A implements Cloneable{}"); + CompilationUnit A1 = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + IApi fromApi = convert(A0); + IApi toApi = convert(A1); + IApiDelta apiDelta = compare(fromApi, toApi); + IClassDefinitionDelta classDelta = getSingleClassDelta(apiDelta); + assertEquals(1, classDelta.getInterfaceDeltas().size()); + ITypeReferenceDelta<?> interfaceDelta = classDelta.getInterfaceDeltas().iterator().next(); + assertNotNull(interfaceDelta); + } + + @Test + public void compareMissingGenericInterface0() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public interface I<T>{}"); + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B implements I<String>{}"); + CompilationUnit A0 = new CompilationUnit("a.A", + "package a; " + + "public class A extends B implements I<String>{}"); + CompilationUnit A1 = new CompilationUnit("a.A", + "package a; " + + "public class A extends B {}"); + IApi fromApi = convert(I, B, A0); + IApi toApi = convert(I, B, A1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingGenericInterface1() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public interface I<T>{}"); + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B<T> implements I<T>{}"); + CompilationUnit A0 = new CompilationUnit("a.A", + "package a; " + + "public class A<T> extends B<T> implements I<T>{}"); + //generic declaration of 'T' in I<T> is A<T> + CompilationUnit A1 = new CompilationUnit("a.A", + "package a; " + + "public class A<T> extends B<T> {}"); + //generic declaration of 'T' in I<T> is B<T> + IApi fromApi = convert(I, B, A0); + IApi toApi = convert(I, B, A1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + static interface I<T>{} + static class B<T> implements I<T>{} + static class A0<E extends Number> extends B<E> implements I<E>{} + static class A1<S extends Number> extends B<S>{} + + @Test + public void compareMissingGenericInterfaceReflection() { + ParameterizedType sC = (ParameterizedType)A0.class.getGenericSuperclass(); + Type[] bounds = ((TypeVariable<?>)sC.getActualTypeArguments()[0]).getBounds(); + Type[] a1Int = A1.class.getGenericInterfaces(); + assertEquals(0,a1Int.length); + } + + @Test + public void compareInterfaceClosure() throws IOException{ + CompilationUnit I0 = new CompilationUnit("a.I0", + "package a; " + + "public interface I0{}"); + CompilationUnit I1 = new CompilationUnit("a.I1", + "package a; " + + "public interface I1 extends I0{}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 implements I1{}"); + CompilationUnit C0_I1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 implements I1, I0{}"); + IApi fromApi = convert(I0, I1, C0); + IApi toApi = convert(I0, I1, C0_I1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareUpperBounds0() throws IOException{ + CompilationUnit Number = new CompilationUnit("a.Number", + "package a; " + + "public class Number implements java.io.Serializable{}"); + CompilationUnit I0 = new CompilationUnit("a.I", + "package a; " + + "public interface I<T extends Number & java.io.Serializable>{}"); + CompilationUnit I1 = new CompilationUnit("a.I", + "package a; " + + "public interface I<T extends Number>{}"); + IApi fromApi = convert(I0,Number); + IApi toApi = convert(I1,Number); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareUpperBounds1() throws IOException{ + CompilationUnit Number = new CompilationUnit("a.Number", + "package a; " + + "public class Number {}"); + CompilationUnit I0 = new CompilationUnit("a.I", + "package a; " + + "public interface I<T extends Number & java.io.Serializable>{}"); + CompilationUnit I1 = new CompilationUnit("a.I", + "package a; " + + "public interface I<T extends Number>{}"); + IApi fromApi = convert(I0,Number); + IApi toApi = convert(I1,Number); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void compareTypeVariables0() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C", + "package a; " + + "public class C<T,S> {}"); + CompilationUnit C1 = new CompilationUnit("a.C", + "package a; " + + "public class C<S,T> {}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareTypeVariables1() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C", + "package a; " + + "public class C<T,S> {}"); + CompilationUnit C1 = new CompilationUnit("a.C", + "package a; " + + "public class C<T,S,R> {}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void compareTypeVariables2() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C", + "package a; " + + "public class C<T,S> {" + + " public void m(T t, S s){} " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C", + "package a; " + + "public class C<S,T> {" + + " public void m(S s, T t){} " + + "}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareTypeVariables3() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C", + "package a; " + + "public class C<T,S> {" + + " public void m(T t, S s){} " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C", + "package a; " + + "public class C<S,T> {" + + " public void m(T t, S s){} " + + "}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void compareTypeVariables4() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C", + "package a; " + + "public class C<T> {" + + " public class I{" + + " public void m(T t){}" + + " } " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C", + "package a; " + + "public class C {" + + " public class I<T>{" + + " public void m(T t){}" + + " } " + + "}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void interfaceClosureTest() throws IOException{ + CompilationUnit B = new CompilationUnit("a.B", + "package a; " + + "public class B<S> {}"); + CompilationUnit C = new CompilationUnit("a.C", + "package a; " + + "public class C<R> extends B<R> {}"); + CompilationUnit E = new CompilationUnit("a.E", + "package a; " + + "public class E<Q> extends C<Q> {}"); + CompilationUnit F = new CompilationUnit("a.F", + "package a; " + + "public class F<P> extends E<P> {}"); + CompilationUnit G = new CompilationUnit("a.G", + "package a; " + + "public class G<O> extends F<O> {}"); + CompilationUnit H = new CompilationUnit("a.H", + "package a; " + + "public class H<R> extends G<R> {}"); +// IApi fromApi = convert(B,C, E, F); +// IApi toApi = convert(B,C,E, F); + IApi fromApi = convert(B,C, E,F, G, H); + IApi toApi = convert(B,C,E,F, G, H); + + + long start = System.currentTimeMillis(); + IApiDelta apiDelta = compare(fromApi, toApi); + System.out.println("compare took :" + (System.currentTimeMillis() -start) + "ms"); + assertNull(apiDelta); + } + +}
\ No newline at end of file diff --git a/tools/signature-tools/test/signature/comparator/MethodCompareTests.java b/tools/signature-tools/test/signature/comparator/MethodCompareTests.java new file mode 100644 index 00000000000..3e94506d472 --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/MethodCompareTests.java @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; + +import org.junit.Test; + +import signature.comparator.util.AbstractComparatorTest; +import signature.compare.model.IApiDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.DeltaType; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; + +public abstract class MethodCompareTests extends AbstractComparatorTest { + + + @Test + public void compareEqualClasses() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(){}" + + "}"); + IApi fromApi = convert(A); + IApi toApi = convert(A); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void compareMissingMethod() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(){}" + + "}"); + CompilationUnit AMissing = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + "}"); + IApi fromApi = convert(A); + IApi toApi = convert(AMissing); + IApiDelta delta = compare(fromApi, toApi); + assertNotNull(delta); + IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next(); + assertEquals(1, classDelta.getMethodDeltas().size()); + assertEquals(DeltaType.REMOVED, classDelta.getMethodDeltas().iterator().next().getType()); + } + + @Test + public void compareAddedMethod() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(){}" + + "}"); + CompilationUnit AMissing = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + "}"); + IApi fromApi = convert(AMissing); + IApi toApi = convert(A); + IApiDelta delta = compare(fromApi, toApi); + assertNotNull(delta); + IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next(); + assertEquals(1, classDelta.getMethodDeltas().size()); + assertEquals(DeltaType.ADDED, classDelta.getMethodDeltas().iterator().next().getType()); + } + + @Test + public void compareChangedMethod() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(){}" + + "}"); + CompilationUnit AMissing = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m() throws Exception {}" + + "}"); + IApi fromApi = convert(AMissing); + IApi toApi = convert(A); + IApiDelta delta = compare(fromApi, toApi); + assertNotNull(delta); + IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next(); + assertEquals(1, classDelta.getMethodDeltas().size()); + assertEquals(DeltaType.CHANGED, classDelta.getMethodDeltas().iterator().next().getType()); + } + + @Test + public void compareAddedParameterMethod() throws IOException{ + CompilationUnit A = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(){}" + + "}"); + CompilationUnit AMissing = new CompilationUnit("a.A", + "package a; " + + "public class A {" + + " public void m(int i) {}" + + "}"); + IApi fromApi = convert(AMissing); + IApi toApi = convert(A); + IApiDelta delta = compare(fromApi, toApi); + assertNotNull(delta); + IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next(); + assertEquals(2, classDelta.getMethodDeltas().size()); //one added , one removed + } + + @Test + public void compareExceptions0() throws IOException{ + CompilationUnit E0 = new CompilationUnit("a.E0", + "package a; " + + "public class E0 extends Exception {}"); + CompilationUnit E1 = new CompilationUnit("a.E1", + "package a; " + + "public class E1 extends E0 {}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 {" + + " public void m() throws E0 {}" + + "}"); + CompilationUnit C0_E1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0{" + + " public void m() throws E0, E1 {}" + + "}"); + IApi fromApi = convert(E0, E1, C0); + IApi toApi = convert(E0, E1, C0_E1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareExceptions1() throws IOException{ + CompilationUnit E0 = new CompilationUnit("a.E0", + "package a; " + + "public class E0 extends Exception {}"); + CompilationUnit E1 = new CompilationUnit("a.E1", + "package a; " + + "public class E1 extends Exception {}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 {" + + " public void m() throws E0 {}" + + "}"); + CompilationUnit C0_E1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0{" + + " public void m() throws E0, E1 {}" + + "}"); + IApi fromApi = convert(E0, E1, C0); + IApi toApi = convert(E0, E1, C0_E1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void compareRuntimeExceptions() throws IOException{ + CompilationUnit E0 = new CompilationUnit("a.E0", + "package a; " + + "public class E0 extends RuntimeException {}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0{" + + " public void m() {}" + + "}"); + CompilationUnit C0_E0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 {" + + " public void m() throws E0 {}" + + "}"); + IApi fromApi = convert(E0, C0); + IApi toApi = convert(E0, C0_E0); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareAnnotations() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0{" + + " public void m(int i) {}" + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 {" + + " public void m(@Deprecated int i) {}" + + "}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + } + + @Test + public void compareMissingDefaultConstructor() throws IOException{ + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0{" + + " public C0() {}" + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 {}"); + IApi fromApi = convert(C0); + IApi toApi = convert(C1); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingAbstractMethod() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public interface I{" + + " void m();" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public abstract class C0 implements I{" + + " public abstract void m(); " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public abstract class C0 implements I{}"); + IApi fromApi = convert(C0, I); + IApi toApi = convert(C1, I); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethod() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public class I{" + + " public void m(){};" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 extends I{" + + " public void m(){}; " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0 extends I{}"); + IApi fromApi = convert(C0, I); + IApi toApi = convert(C1, I); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethodGeneric0() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public class I<T>{" + + " public void m(T t){};" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<T> extends I<T>{" + + " public void m(T t){}; " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<T> extends I<T>{}"); + IApi fromApi = convert(C0, I); + IApi toApi = convert(C1, I); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethodGeneric1() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public class I<T,S>{" + + " public void m(S s){};" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<Q, R> extends I<Q,R>{" + + " public void m(R t){}; " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<Y,Z> extends I<Y,Z>{}"); + IApi fromApi = convert(C0, I); + IApi toApi = convert(C1, I); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethodGeneric2() throws IOException{ + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public class I<T,S>{" + + " public void m(S s){};" + + "}"); + CompilationUnit J = new CompilationUnit("a.J", + "package a; " + + "public class J<W> extends I<Number,W>{" + + " public void m(W w){};" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<Q> extends J<Q>{" + + " public void m(Q t){}; " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<Y> extends J<Y>{}"); + IApi fromApi = convert(C0, I, J); + IApi toApi = convert(C1, I, J); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + + + @Test + public void compareMissingInheritedMethodGeneric3() throws IOException{ + CompilationUnit Q = new CompilationUnit("a.Q", + "package a; " + + "public class Q<S,T>{ " + + " public void m(T s){} " + + "}"); + + CompilationUnit W = new CompilationUnit("a.W", + "package a; " + + "public class W<A,B> extends Q<A,A>{}"); + CompilationUnit E0 = new CompilationUnit("a.E", + "package a; " + + "public class E<C,D> extends W<C,C>{" + + " public void m(C s){}" + + "}"); + CompilationUnit E1 = new CompilationUnit("a.E", + "package a; " + + "public class E<C,D> extends W<C,C>{}"); + IApi fromApi = convert(E0, Q, W); + IApi toApi = convert(E1, Q, W); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethodGeneric4() throws IOException{ + CompilationUnit Q = new CompilationUnit("a.Q", + "package a; " + + "public class Q<S,T>{ " + + " public void m(T t, S s){} " + + "}"); + + CompilationUnit W = new CompilationUnit("a.W", + "package a; " + + "public class W<A,B> extends Q<A,A>{}"); + CompilationUnit E0 = new CompilationUnit("a.E", + "package a; " + + "public class E<C,D> extends W<C,C>{" + + " public void m(C s, C c){}" + + "}"); + CompilationUnit E1 = new CompilationUnit("a.E", + "package a; " + + "public class E<C,D> extends W<C,C>{}"); + IApi fromApi = convert(E0, Q, W); + IApi toApi = convert(E1, Q, W); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void compareMissingInheritedMethodGeneric5() throws IOException{ + CompilationUnit Q = new CompilationUnit("a.Q", + "package a; " + + "public class Q{}"); + + CompilationUnit I = new CompilationUnit("a.I", + "package a; " + + "public class I<S,T>{" + + " public void m(T s){};" + + "}"); + CompilationUnit C0 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<P> extends I<P, Q>{" + + " public void m(Q t){}; " + + "}"); + CompilationUnit C1 = new CompilationUnit("a.C0", + "package a; " + + "public class C0<Y> extends I<Y, Q>{}"); + IApi fromApi = convert(C0, I, Q); + IApi toApi = convert(C1, I, Q); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + + @Test + public void substitutionTest() throws IOException{ + CompilationUnit NUMBER = new CompilationUnit("a.Number", + "package a; " + + "public class Number{}"); + CompilationUnit Q = new CompilationUnit("a.A", + "package a; " + + "public class A<T>{ " + + " public void m(T t){} " + + "}"); + CompilationUnit E0 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{" + + " public void m(Number n){}" + + "}"); + CompilationUnit E1 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{}"); + IApi fromApi = convert(E0, Q, NUMBER); + IApi toApi = convert(E1, Q, NUMBER); + + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void substitutionArrayTest() throws IOException{ + CompilationUnit NUMBER = new CompilationUnit("a.Number", + "package a; " + + "public class Number{}"); + CompilationUnit Q = new CompilationUnit("a.A", + "package a; " + + "public class A<T>{ " + + " public void m(T[] t){} " + + "}"); + CompilationUnit E0 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{" + + " public void m(Number[] n){}" + + "}"); + CompilationUnit E1 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{}"); + IApi fromApi = convert(E0, Q, NUMBER); + IApi toApi = convert(E1, Q, NUMBER); + + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } + + @Test + public void substitutionNestedTypes() throws IOException{ + CompilationUnit NUMBER = new CompilationUnit("a.Number", + "package a; " + + "public class Number{}"); + CompilationUnit Q = new CompilationUnit("a.A", + "package a; " + + "public class A<T>{ " + + " public void m(A<A<T[]>> t){} " + + "}"); + CompilationUnit E0 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{" + + " public void m(A<A<Number[]>> n){}" + + "}"); + CompilationUnit E1 = new CompilationUnit("a.E", + "package a; " + + "public class E extends A<Number>{}"); + IApi fromApi = convert(E0, Q, NUMBER); + IApi toApi = convert(E1, Q, NUMBER); + + IApiDelta apiDelta = compare(fromApi, toApi); + assertNull(apiDelta); + } +} diff --git a/tools/signature-tools/test/signature/comparator/PackageCompareTest.java b/tools/signature-tools/test/signature/comparator/PackageCompareTest.java new file mode 100644 index 00000000000..d522186226b --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/PackageCompareTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import signature.comparator.util.AbstractComparatorTest; +import signature.compare.model.IApiDelta; +import signature.compare.model.DeltaType; +import signature.compare.model.IPackageDelta; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; + +import java.io.IOException; + +public abstract class PackageCompareTest extends AbstractComparatorTest{ + + @Test + public void compareEqualPackageTest0() throws IOException{ + CompilationUnit from = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + IApi fromApi = convert(from); + IApi toApi = convert(from); + IApiDelta delta = compare(fromApi, toApi); + assertNull(delta); + } + + @Test + public void compareEqualPackageTest1() throws IOException{ + CompilationUnit from0 = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit from1 = new CompilationUnit("a.b.A", + "package a.b; " + + "public class A {}"); + IApi fromApi = convert(from0, from1); + IApi toApi = convert(from0, from1); + assertNull(compare(fromApi, toApi)); + } + + @Test + public void compareRemovedPackagePackageTest1() throws IOException{ + CompilationUnit packageA = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit packageB = new CompilationUnit("a.b.A", + "package a.b; " + + "public class A {}"); + IApi fromApi = convert(packageA, packageB); + IApi toApi = convert(packageA); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + + assertEquals(1, apiDelta.getPackageDeltas().size()); + IPackageDelta packageDelta = apiDelta.getPackageDeltas().iterator().next(); + assertEquals(DeltaType.REMOVED, packageDelta.getType()); + } + + @Test + public void compareAddedPackagePackageTest1() throws IOException{ + CompilationUnit packageA = new CompilationUnit("a.A", + "package a; " + + "public class A {}"); + CompilationUnit packageB = new CompilationUnit("a.b.A", + "package a.b; " + + "public class A {}"); + IApi fromApi = convert(packageA); + IApi toApi = convert(packageA, packageB); + IApiDelta apiDelta = compare(fromApi, toApi); + assertNotNull(apiDelta); + + assertEquals(1, apiDelta.getPackageDeltas().size()); + IPackageDelta packageDelta = apiDelta.getPackageDeltas().iterator().next(); + assertEquals(DeltaType.ADDED, packageDelta.getType()); + } +} diff --git a/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java b/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java new file mode 100644 index 00000000000..6392dc9d036 --- /dev/null +++ b/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.comparator.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; + +import signature.compare.ApiComparator; +import signature.compare.IApiComparator; +import signature.compare.model.IApiDelta; +import signature.compare.model.IClassDefinitionDelta; +import signature.compare.model.IPackageDelta; +import signature.converter.util.AbstractConvertTest; +import signature.model.IApi; +public abstract class AbstractComparatorTest extends AbstractConvertTest{ + + private IApiComparator comparator; + + @Before + public void setupComparator() { + comparator = new ApiComparator(); + } + + public IApiDelta compare(IApi from, IApi to){ + return comparator.compare(from, to); + } + + public IPackageDelta getSinglePackageDelta(IApiDelta apiDelta){ + assertNotNull(apiDelta); + assertEquals(1, apiDelta.getPackageDeltas().size()); + return apiDelta.getPackageDeltas().iterator().next(); + } + + public IClassDefinitionDelta getSingleClassDelta(IApiDelta apiDelta){ + IPackageDelta packageDelta = getSinglePackageDelta(apiDelta); + assertEquals(1, packageDelta.getClassDeltas().size()); + return packageDelta.getClassDeltas().iterator().next(); + } + +} diff --git a/tools/signature-tools/test/signature/converter/AllDexTests.java b/tools/signature-tools/test/signature/converter/AllDexTests.java new file mode 100644 index 00000000000..84d26a895bf --- /dev/null +++ b/tools/signature-tools/test/signature/converter/AllDexTests.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import signature.converter.dex.DexTestConverter; +import signature.converter.util.ITestSourceConverter; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AllDexTests.ClassTest.class, + AllDexTests.PackageTest.class, + AllDexTests.AnnotationTest.class, + AllDexTests.VisibilityTest.class, + AllDexTests.WildcardTest.class, + AllDexTests.EnumTest.class +}) +public class AllDexTests { + private static ITestSourceConverter newConverter(){ + return new DexTestConverter(); + } + + public static class ClassTest extends ConvertClassTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class AnnotationTest extends ConvertAnnotationTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class PackageTest extends ConvertPackageTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class VisibilityTest extends ConvertVisibilityTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class WildcardTest extends ConvertWildcardTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class EnumTest extends ConvertEnumTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + + public static class ParameterizedTypeTest extends ConvertParameterizedTypeTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } +} + diff --git a/tools/signature-tools/test/signature/converter/AllDocletTests.java b/tools/signature-tools/test/signature/converter/AllDocletTests.java new file mode 100644 index 00000000000..610917efd56 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/AllDocletTests.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import signature.converter.doclet.DocletTestConverter; +import signature.converter.util.ITestSourceConverter; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AllDocletTests.ClassTest.class, + AllDocletTests.PackageTest.class, + AllDocletTests.AnnotationTest.class, + AllDocletTests.VisibilityTest.class, + AllDocletTests.WildcardTest.class, + AllDocletTests.EnumTest.class +}) +public class AllDocletTests { + private static ITestSourceConverter newConverter(){ + return new DocletTestConverter(); + } + + public static class ClassTest extends ConvertClassTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class AnnotationTest extends ConvertAnnotationTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class PackageTest extends ConvertPackageTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class VisibilityTest extends ConvertVisibilityTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class WildcardTest extends ConvertWildcardTest { + @Override + public ITestSourceConverter createConverter() { + return newConverter(); + } + } + public static class EnumTest extends ConvertEnumTest { + @Override public ITestSourceConverter createConverter() { + return newConverter(); + } + } +} + diff --git a/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java b/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java new file mode 100644 index 00000000000..f53f40347cc --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java @@ -0,0 +1,761 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IAnnotation;
+import signature.model.IAnnotationField;
+import signature.model.IApi;
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IEnumConstant;
+import signature.model.IPackage;
+import signature.model.IPrimitiveType;
+import signature.model.ITypeReference;
+import signature.model.Kind;
+import signature.model.impl.SigClassReference;
+import signature.model.impl.SigPrimitiveType;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertAnnotationTest extends AbstractConvertTest {
+
+ // Tests whether an annotation declaration element may be annotated with
+ // the declared annotation.
+ @Test
+ public void convertAnnotationDefinition1() throws IOException {
+ CompilationUnit classSrc = new CompilationUnit("a.ToDo",
+ "package a; " +
+ "public @interface ToDo {" +
+ " @ToDo(name=\"ToDo\")" +
+ " String name() default \"nobody\";" +
+ "}");
+ IApi api = convert(classSrc);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ assertEquals(0, sigClass.getConstructors().size());
+ assertEquals(0, sigClass.getMethods().size());
+ assertEquals(0, sigClass.getFields().size());
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("name", field.getName());
+ assertEquals("String", ((IClassReference)field.getType()).getClassDefinition().getName());
+ assertEquals("nobody", field.getDefaultValue());
+ Set<IAnnotation> annotations = field.getAnnotations();
+ assertEquals(1, annotations.size());
+ IAnnotation annotation = annotations.iterator().next();
+ assertSame(sigClass, annotation.getType().getClassDefinition());
+ // TODO TEST add additional assert for annotation.getElements()
+ }
+
+ // Tests whether an annotation declaration may be annotated with
+ // the declared annotation.
+ @Test
+ public void convertAnnotationDefinition2() throws IOException {
+ CompilationUnit classSrc = new CompilationUnit("a.ToDo",
+ "package a; " +
+ "@ToDo\n" +
+ "public @interface ToDo {" +
+ " String name() default \"nobody\";" +
+ "}");
+ IApi api = convert(classSrc);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ assertEquals(0, sigClass.getConstructors().size());
+ assertEquals(0, sigClass.getMethods().size());
+ assertEquals(0, sigClass.getFields().size());
+ Set<IAnnotation> annotations = sigClass.getAnnotations();
+ assertEquals(1, annotations.size());
+ IAnnotation annotation = annotations.iterator().next();
+ assertSame(sigClass, ((SigClassReference)annotation.getType()).getClassDefinition());
+ assertEquals(0, annotation.getElements().size());
+ }
+
+ @Test
+ public void convertAnnotationDefinition3() throws IOException {
+ CompilationUnit classSrc = new CompilationUnit("a.ToDo",
+ "package a; " +
+ "public @interface ToDo {" +
+ " String name() default \"nobody\";" +
+ " int num() default 3;" +
+ "}");
+ IApi api = convert(classSrc);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ assertEquals(0, sigClass.getConstructors().size());
+ assertEquals(0, sigClass.getMethods().size());
+ assertEquals(0, sigClass.getFields().size());
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(2, annotationFields.size());
+ IAnnotationField name = ModelUtil.getAnnotationField(sigClass, "name");
+ IAnnotationField num = ModelUtil.getAnnotationField(sigClass, "num");
+
+ assertEquals("name", name.getName());
+ assertEquals("num", num.getName());
+
+ assertEquals("nobody", name.getDefaultValue());
+ assertEquals(3, num.getDefaultValue());
+ }
+
+
+ // tests whether default int value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsInt1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " int value() default 1;" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField annotationField = annotationFields.iterator().next();
+ assertEquals("value", annotationField.getName());
+ assertTrue(annotationField.getType() instanceof IPrimitiveType);
+ IPrimitiveType annotationFieldType = (IPrimitiveType)annotationField.getType();
+ assertSame(SigPrimitiveType.INT_TYPE, annotationFieldType);
+
+ assertTrue(annotationField.getDefaultValue() instanceof Integer);
+ Integer defaultValue = (Integer)annotationField.getDefaultValue();
+ assertEquals(1, defaultValue.intValue());
+ }
+
+ // tests whether default int[] value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsInt2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " int[] value() default {};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(0, defaultValue.length);
+ }
+
+ // tests whether default int[] value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsInt3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " int[] value() default {1,2};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof Integer);
+ Integer defaultValue0int = (Integer)defaultValue0;
+ assertEquals(1, defaultValue0int.intValue());
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof Integer);
+ Integer defaultValue1int = (Integer)defaultValue1;
+ assertEquals(2, defaultValue1int.intValue());
+ }
+
+
+ // tests whether default double value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsDouble1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " double value() default 1;" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField annotationField = annotationFields.iterator().next();
+ assertEquals("value", annotationField.getName());
+ assertTrue(annotationField.getType() instanceof IPrimitiveType);
+ IPrimitiveType annotationFieldType = (IPrimitiveType)annotationField.getType();
+ assertSame(SigPrimitiveType.DOUBLE_TYPE, annotationFieldType);
+
+
+ assertTrue(annotationField.getDefaultValue() instanceof Double);
+ Double defaultValue = (Double)annotationField.getDefaultValue();
+ assertEquals(1.0, defaultValue.doubleValue());
+ }
+
+ // tests whether default int[] value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsDouble2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " double[] value() default {};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(0, defaultValue.length);
+ }
+
+ // tests whether default int[] value has the correct type and defaultValue
+ @Test
+ public void testAnnotationDefaultsDouble3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " double[] value() default {1,2.5};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof Double);
+ Double defaultValue0int = (Double)defaultValue0;
+ assertEquals(1, defaultValue0int.doubleValue());
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof Double);
+ Double defaultValue1int = (Double)defaultValue1;
+ assertEquals(2.5, defaultValue1int.doubleValue());
+ }
+
+
+ // tests whether default enum value has the correct type
+ @Test
+ public void testAnnotationDefaultsEnum1() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " Kind value() default Kind.TWO;" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.Kind",
+ "package a; " +
+ "public enum Kind {" +
+ " ONE, TWO, THREE" +
+ "}");
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+ assertEquals("Kind", ((IClassReference)field.getType()).getClassDefinition().getName());
+ assertTrue(field.getDefaultValue() instanceof IEnumConstant);
+ IEnumConstant defaultValue = (IEnumConstant)field.getDefaultValue();
+// assertEquals(1, defaultValue.getOrdinal());
+ assertEquals("TWO", defaultValue.getName());
+
+ IClassDefinition enumClass = ModelUtil.getClass(sigPackage, "Kind");
+ assertTrue(enumClass.getKind() == Kind.ENUM);
+ IEnumConstant enumTWO = null;
+ Set<IEnumConstant> enumConstants = enumClass.getEnumConstants();
+ for(IEnumConstant c : enumConstants){
+ if("TWO".equals(c.getName())) enumTWO = c;
+ }
+ assertSame(enumTWO, defaultValue);
+ }
+
+ // tests whether default enum value has the correct type
+ @Test
+ public void testAnnotationDefaultsEnum2() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " Kind[] value() default {};" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.Kind",
+ "package a; " +
+ "public enum Kind {" +
+ " ONE, TWO, THREE" +
+ "}");
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(0, defaultValue.length);
+ }
+
+ // tests whether default enum value has the correct type
+ @Test
+ public void testAnnotationDefaultsEnum3() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " Kind[] value() default {Kind.ONE,Kind.TWO};" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.Kind",
+ "package a; " +
+ "public enum Kind {" +
+ " ONE, TWO, THREE" +
+ "}");
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("value", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ IClassDefinition enumClass = ModelUtil.getClass(sigPackage, "Kind");
+ assertTrue(enumClass.getKind() == Kind.ENUM);
+ IEnumConstant enumONE = null;
+ IEnumConstant enumTWO = null;
+ Set<IEnumConstant> enumConstants = enumClass.getEnumConstants();
+ for(IEnumConstant c : enumConstants){
+ if("ONE".equals(c.getName())) enumONE = c;
+ if("TWO".equals(c.getName())) enumTWO = c;
+ }
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof IEnumConstant);
+ IEnumConstant defaultValue0enum = (IEnumConstant)defaultValue0;
+// assertEquals(0, defaultValue0enum.getOrdinal());
+ assertEquals("ONE", defaultValue0enum.getName());
+ assertSame(enumONE, defaultValue0enum);
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof IEnumConstant);
+ IEnumConstant defaultValue1enum = (IEnumConstant)defaultValue1;
+// assertEquals(1, defaultValue1enum.getOrdinal());
+ assertEquals("TWO", defaultValue1enum.getName());
+ assertSame(enumTWO, defaultValue1enum);
+ }
+
+
+ @Test
+ public void testAnnotationDefaultsAnnotation1() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " AA aa() default @AA;" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.AA",
+ "package a; " +
+ "public @interface AA {}");
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("aa", field.getName());
+ IClassReference fieldType = (IClassReference)field.getType();
+ assertEquals("AA", fieldType.getClassDefinition().getName());
+
+ IClassDefinition aaType = ModelUtil.getClass(sigPackage, "AA");
+ assertTrue(aaType.getKind() == Kind.ANNOTATION);
+ assertSame(aaType, fieldType.getClassDefinition());
+
+ assertTrue(field.getDefaultValue() instanceof IAnnotation);
+ IAnnotation defaultValue = (IAnnotation)field.getDefaultValue();
+ assertEquals(0, defaultValue.getElements().size());
+ assertSame(aaType, defaultValue.getType().getClassDefinition());
+ }
+
+ @Test
+ public void testAnnotationDefaultsAnnotation2() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " AA[] aa() default {};" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.AA",
+ "package a; " +
+ "public @interface AA {}");
+
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("aa", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(0, defaultValue.length);
+ }
+
+ @Test
+ public void testAnnotationDefaultsAnnotation3() throws IOException {
+ CompilationUnit src1 = new CompilationUnit("a.A",
+ "package a; " +
+ "public @interface A {" +
+ " AA[] aa() default {@AA,@AA};" +
+ "}");
+ CompilationUnit src2 = new CompilationUnit("a.AA",
+ "package a; " +
+ "public @interface AA {}");
+
+ IApi api = convert(src1, src2);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("aa", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ IClassDefinition aaType = ModelUtil.getClass(sigPackage, "AA");
+ assertTrue(aaType.getKind() == Kind.ANNOTATION);
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof IAnnotation);
+ IAnnotation defaultValue0ann = (IAnnotation)defaultValue0;
+ assertSame(aaType, defaultValue0ann.getType().getClassDefinition());
+ assertEquals(0, defaultValue0ann.getElements().size());
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof IAnnotation);
+ IAnnotation defaultValue1ann = (IAnnotation)defaultValue1;
+ assertSame(aaType, defaultValue1ann.getType().getClassDefinition());
+ assertEquals(0, defaultValue1ann.getElements().size());
+ }
+
+
+
+ @Test
+ public void testAnnotationDefaultsString1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " String str() default \"xxx\";" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("str", field.getName());
+
+ assertTrue(field.getType() instanceof IClassReference);
+ assertEquals("String", ((IClassReference)field.getType()).getClassDefinition().getName());
+
+ assertTrue(field.getDefaultValue() instanceof String);
+ String defaultValue = (String)field.getDefaultValue();
+ assertEquals("xxx", defaultValue);
+ }
+
+ @Test
+ public void testAnnotationDefaultsString2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " String[] str() default {};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("str", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ Object defaultValue = field.getDefaultValue();
+ assertTrue(defaultValue instanceof Object[]);
+ assertSame(defaultValue.getClass(), Object[].class);
+ assertEquals(0, ((Object[])defaultValue).length);
+ }
+
+ @Test
+ public void testAnnotationDefaultsString3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " String[] str() default {\"ONE\", \"TWO\"};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(sigClass.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("str", field.getName());
+
+ assertTrue(field.getType() instanceof IArrayType);
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof String);
+ String defaultValue0str = (String)defaultValue0;
+ assertEquals("ONE", defaultValue0str);
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof String);
+ String defaultValue1str = (String)defaultValue1;
+ assertEquals("TWO", defaultValue1str);
+ }
+
+ @Test
+ public void testAnnotationDefaultsClass1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " Class cc() default A.class;" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(aType.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = aType.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("cc", field.getName());
+
+ assertTrue(field.getType() instanceof IClassReference);
+ assertEquals("Class", ((IClassReference)field.getType()).getClassDefinition().getName());
+ Object defaultValue = field.getDefaultValue();
+ assertSame(aType, ((IClassReference)defaultValue).getClassDefinition());
+ }
+
+ @Test
+ public void testAnnotationDefaultsClass2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " Class cc() default void.class;" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(aType.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = aType.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("cc", field.getName());
+
+ assertTrue(field.getType() instanceof IClassReference);
+ assertEquals("Class", ((IClassReference)field.getType()).getClassDefinition().getName());
+
+ Object defaultValue = field.getDefaultValue();
+ assertTrue(defaultValue instanceof IPrimitiveType);
+ assertEquals("void", ((IPrimitiveType)defaultValue).getName());
+ assertSame(SigPrimitiveType.VOID_TYPE, defaultValue);
+ }
+
+ @Test
+ public void testAnnotationDefaultsClass3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " Class[] cc() default {};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(aType.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = aType.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("cc", field.getName());
+
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(0, defaultValue.length);
+ }
+
+ @Test
+ public void testAnnotationDefaultsClass4() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public @interface A {" +
+ " Class[] cc() default {A.class, void.class};" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");
+ assertTrue(aType.getKind() == Kind.ANNOTATION);
+ Set<IAnnotationField> annotationFields = aType.getAnnotationFields();
+ assertEquals(1, annotationFields.size());
+ IAnnotationField field = annotationFields.iterator().next();
+ assertEquals("cc", field.getName());
+
+ assertTrue(field.getDefaultValue() instanceof Object[]);
+ assertSame(field.getDefaultValue().getClass(), Object[].class);
+ Object[] defaultValue = (Object[])field.getDefaultValue();
+ assertEquals(2, defaultValue.length);
+
+ Object defaultValue0 = defaultValue[0];
+ assertTrue(defaultValue0 instanceof ITypeReference);
+ ITypeReference defaultValue0type = (ITypeReference)defaultValue0;
+ assertSame(aType, ((IClassReference)defaultValue0type).getClassDefinition());
+
+ Object defaultValue1 = defaultValue[1];
+ assertTrue(defaultValue1 instanceof ITypeReference);
+ assertTrue(defaultValue1 instanceof IPrimitiveType);
+ IPrimitiveType defaultValue1type = (IPrimitiveType)defaultValue1;
+ assertEquals("void", defaultValue1type.getName());
+ assertSame(SigPrimitiveType.VOID_TYPE, defaultValue1type);
+ }
+
+ @Test
+ public void testAnnotationRetentionRuntime() throws IOException {
+ CompilationUnit retention = new CompilationUnit("java.lang.annotation.Retention",
+ "package java.lang.annotation; " +
+ "@Retention(RetentionPolicy.RUNTIME) " +
+ //"@Target(ElementType.ANNOTATION_TYPE) " +
+ "public @interface Retention { " +
+ " RetentionPolicy value() default RetentionPolicy.CLASS; " +
+ "}");
+ CompilationUnit retentionPolicy = new CompilationUnit("java.lang.annotation.RetentionPolicy",
+ "package java.lang.annotation; " +
+ "public enum RetentionPolicy { " +
+ " SOURCE," +
+ " CLASS," +
+ " RUNTIME" +
+ "}");
+ CompilationUnit anno = new CompilationUnit("a.A",
+ "package a;" +
+ "@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)" +
+ "public @interface A{}");
+ CompilationUnit cla = new CompilationUnit("a.B",
+ "package a;" +
+ "@A public class B{}");
+ IApi api = convert(anno, cla, retention, retentionPolicy);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "B");
+ assertTrue(aType.getAnnotations().isEmpty());
+ }
+
+ @Test
+ public void testAnnotationRetentionClass() throws IOException {
+ CompilationUnit retention = new CompilationUnit("java.lang.annotation.Retention",
+ "package java.lang.annotation; " +
+ "@Retention(RetentionPolicy.RUNTIME) " +
+ //"@Target(ElementType.ANNOTATION_TYPE) " +
+ "public @interface Retention { " +
+ " RetentionPolicy value() default RetentionPolicy.CLASS; " +
+ "}");
+ CompilationUnit retentionPolicy = new CompilationUnit("java.lang.annotation.RetentionPolicy",
+ "package java.lang.annotation; " +
+ "public enum RetentionPolicy { " +
+ " SOURCE," +
+ " CLASS," +
+ " RUNTIME" +
+ "}");
+ CompilationUnit anno = new CompilationUnit("a.A",
+ "package a;" +
+ "@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.CLASS)" +
+ "public @interface A{}");
+ CompilationUnit cla = new CompilationUnit("a.B",
+ "package a;" +
+ "@A public class B{}");
+ IApi api = convert(anno, cla, retention, retentionPolicy);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ IClassDefinition aType = ModelUtil.getClass(sigPackage, "B");
+ assertEquals(1, aType.getAnnotations().size());
+ }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/ConvertClassTest.java b/tools/signature-tools/test/signature/converter/ConvertClassTest.java new file mode 100644 index 00000000000..5bcdcb44f17 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertClassTest.java @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import signature.converter.util.AbstractConvertTest; +import signature.converter.util.CompilationUnit; +import signature.model.IAnnotation; +import signature.model.IApi; +import signature.model.IArrayType; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IConstructor; +import signature.model.IField; +import signature.model.IMethod; +import signature.model.IPackage; +import signature.model.IParameter; +import signature.model.IParameterizedType; +import signature.model.ITypeReference; +import signature.model.ITypeVariableDefinition; +import signature.model.ITypeVariableReference; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.impl.SigPrimitiveType; +import signature.model.util.ModelUtil; + +public abstract class ConvertClassTest extends AbstractConvertTest { + + @Test + public void convertPackageClassTest() throws IOException { + IApi api = convert(new CompilationUnit("a.b.A", "package a.b; public class A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a.b"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.b.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals("a.b", sigPackage.getName()); + assertEquals(1, sigPackage.getClasses().size()); + } + + @Test + public void convertClassClassTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertClassInterfaceTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public interface A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.INTERFACE, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertClassEnumTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public enum A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.ENUM, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertClassAnnotationTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public @interface A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.ANNOTATION, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertAnnotationTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; @Deprecated public class A{}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + assertEquals(1, sigClass.getAnnotations().size()); + IAnnotation annotation = sigClass.getAnnotations().iterator().next(); + assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName()); + } + + @Test + public void convertAnnotationOnFieldTest() throws IOException { + IApi api = convert(new CompilationUnit("a.A", + "package a; " + + "public class A{" + + " @Deprecated" + + " public int f;" + + "}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + assertEquals(1, sigClass.getFields().size()); + IField field = sigClass.getFields().iterator().next(); + assertEquals("f", field.getName()); + assertEquals(1, field.getAnnotations().size()); + IAnnotation annotation = field.getAnnotations().iterator().next(); + assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName()); + } + + @Test + public void convertGenericClass0() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A<T> {}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + //test type variable + assertEquals(1, sigClass.getTypeParameters().size()); + ITypeVariableDefinition variable = sigClass.getTypeParameters().get(0); + assertEquals("T", variable.getName()); + //test type variable bound + assertEquals(1, variable.getUpperBounds().size()); + IClassReference bound = (IClassReference) variable.getUpperBounds().get(0); + assertEquals("java.lang.Object", bound.getClassDefinition().getQualifiedName()); + } + + @Test + public void convertGenericClass00() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A<T extends Integer> {}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + //test type variable + assertEquals(1, sigClass.getTypeParameters().size()); + ITypeVariableDefinition variable = sigClass.getTypeParameters().get(0); + assertEquals("T", variable.getName()); + //test type variable bound + assertEquals(1, variable.getUpperBounds().size()); + IClassReference bound = (IClassReference) variable.getUpperBounds().get(0); + assertEquals("java.lang.Integer", bound.getClassDefinition().getQualifiedName()); + } + + @Test + public void convertGenericClass1() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A<S,T> {}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + //test type variable + assertEquals(2, sigClass.getTypeParameters().size()); + ITypeVariableDefinition variableS = sigClass.getTypeParameters().get(0); + assertEquals("S", variableS.getName()); + //test type variable bound + assertEquals(1, variableS.getUpperBounds().size()); + IClassReference boundS = (IClassReference) variableS.getUpperBounds().get(0); + assertEquals("java.lang.Object", boundS.getClassDefinition().getQualifiedName()); + + ITypeVariableDefinition variableT = sigClass.getTypeParameters().get(1); + assertEquals("T", variableT.getName()); + //test type variable bound + assertEquals(1, variableT.getUpperBounds().size()); + IClassReference boundT = (IClassReference) variableT.getUpperBounds().get(0); + assertEquals("java.lang.Object", boundT.getClassDefinition().getQualifiedName()); + } + + @Test + public void convertGenericClass2() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A<S,T extends S> {}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + //test type variable + assertEquals(2, sigClass.getTypeParameters().size()); + ITypeVariableDefinition variableS = sigClass.getTypeParameters().get(0); + assertEquals("S", variableS.getName()); + //test type variable bound + assertEquals(1, variableS.getUpperBounds().size()); + IClassReference boundS = (IClassReference) variableS.getUpperBounds().get(0); + assertEquals("java.lang.Object", boundS.getClassDefinition().getQualifiedName()); + + ITypeVariableDefinition variableT = sigClass.getTypeParameters().get(1); + assertEquals("T", variableT.getName()); + //test type variable bound + assertEquals(1, variableT.getUpperBounds().size()); + ITypeVariableReference boundT = (ITypeVariableReference) variableT.getUpperBounds().get(0); + assertSame(variableS, boundT.getTypeVariableDefinition()); + } + + @Test + public void convertClassImplementsInterface0() throws IOException { + IApi api = convert(new CompilationUnit("a.A", "package a; public class A implements Cloneable {}")); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + + assertEquals(1, sigClass.getInterfaces().size()); + IClassDefinition clonable = ((IClassReference) sigClass.getInterfaces().iterator().next()).getClassDefinition(); + assertEquals("java.lang.Cloneable", clonable.getQualifiedName()); + assertEquals(Kind.INTERFACE, clonable.getKind()); + } + + @Test + public void convertClassImplementsInterface1() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A implements I {}"); + CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I {}"); + IApi api = convert(classSrc, interfaceSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + + IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I"); + assertEquals("a.I", sigInterface.getQualifiedName()); + assertEquals("I", sigInterface.getName()); + assertEquals(Kind.INTERFACE, sigInterface.getKind()); + assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC)); + + assertEquals(1, sigClass.getInterfaces().size()); + IClassReference interfaze = (IClassReference) sigClass.getInterfaces().iterator().next(); + assertEquals(Kind.INTERFACE, interfaze.getClassDefinition().getKind()); + assertSame(sigInterface, interfaze.getClassDefinition()); + } + + @Test + public void convertClassImplementsGenericInterface0() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A implements I<String> {}"); + CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I<T> {}"); + IApi api = convert(classSrc, interfaceSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + + IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I"); + assertEquals("a.I", sigInterface.getQualifiedName()); + assertEquals("I", sigInterface.getName()); + assertEquals(Kind.INTERFACE, sigInterface.getKind()); + assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC)); + + assertEquals(1, sigClass.getInterfaces().size()); + IParameterizedType interfaze = (IParameterizedType) sigClass.getInterfaces().iterator().next(); + //compare raw type "I" + assertSame(sigInterface, interfaze.getRawType().getClassDefinition()); + //test type argument string + assertEquals(1, interfaze.getTypeArguments().size()); + IClassReference string = (IClassReference) interfaze.getTypeArguments().get(0); + assertEquals("java.lang.String", string.getClassDefinition().getQualifiedName()); + } + + @Test + public void convertGenericClassImplementsGenericInterface() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A<T> implements I<T> {}"); + CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I<T> {}"); + IApi api = convert(classSrc, interfaceSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals("a.A", sigClass.getQualifiedName()); + assertEquals("A", sigClass.getName()); + assertEquals(Kind.CLASS, sigClass.getKind()); + assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC)); + + //get type variable from class + assertEquals(1, sigClass.getTypeParameters().size()); + ITypeVariableDefinition classTypeVar = sigClass.getTypeParameters().get(0); + assertEquals("T", classTypeVar.getName()); + assertSame(sigClass, classTypeVar.getGenericDeclaration()); + + //inspect interface + IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I"); + assertEquals("a.I", sigInterface.getQualifiedName()); + assertEquals("I", sigInterface.getName()); + assertEquals(Kind.INTERFACE, sigInterface.getKind()); + assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC)); + + //get type variable from interface + assertEquals(1, sigInterface.getTypeParameters().size()); + ITypeVariableDefinition interfaceTypeVar = sigInterface.getTypeParameters().get(0); + + //get implemented interface from A + assertEquals(1, sigClass.getInterfaces().size()); + IParameterizedType interfaze = (IParameterizedType) sigClass.getInterfaces().iterator().next(); + + //compare raw type "I" + assertSame(sigInterface, interfaze.getRawType().getClassDefinition()); + + //test if type variable of A is type argument of I + assertEquals(1, interfaze.getTypeArguments().size()); + ITypeVariableReference argument = (ITypeVariableReference) interfaze.getTypeArguments().get(0); + assertSame(sigClass, argument.getTypeVariableDefinition().getGenericDeclaration()); + assertEquals(classTypeVar, argument.getTypeVariableDefinition()); + + //test that the two type parameters are not equal + assertNotSame(classTypeVar, interfaceTypeVar); + assertEquals(classTypeVar.getName(), interfaceTypeVar.getName()); + assertNotSame(classTypeVar.getGenericDeclaration(), interfaceTypeVar.getGenericDeclaration()); + } + + @Test + public void convertConstructor0() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A(){} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertConstructor1a() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public class B{ } }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC)); + } + + @Test + public void convertConstructor1b() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { protected class B{ } }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PROTECTED)); + } + + @Test + public void convertConstructor2() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A {}"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getConstructors().size()); + } + + @Test + public void convertConstructor3() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public class B { public B(){}} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B"); + assertEquals(1, sigClass.getConstructors().size()); + } + + @Test + public void convertConstructorWithException() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A() throws NullPointerException{} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC)); + assertEquals(1, constructor.getExceptions().size()); + IClassReference exception = (IClassReference) constructor.getExceptions().iterator().next(); + assertEquals("java.lang.NullPointerException", exception.getClassDefinition().getQualifiedName()); + } + + @Test + public void convertConstructorWithParameter() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A(String param){} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC)); + assertEquals(1, constructor.getParameters().size()); + IParameter param = constructor.getParameters().get(0); + assertEquals("java.lang.String", ((IClassReference)param.getType()).getClassDefinition().getQualifiedName()); + } + + @Test + public void convertConstructorWithGenericParameter() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A<T> { public A(T param){} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getConstructors().size()); + IConstructor constructor = sigClass.getConstructors().iterator().next(); + assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC)); + assertEquals(1, constructor.getParameters().size()); + IParameter param = constructor.getParameters().get(0); + ITypeVariableDefinition paramType = ((ITypeVariableReference)param.getType()).getTypeVariableDefinition(); + assertEquals("T", paramType.getName()); + assertSame(sigClass, paramType.getGenericDeclaration()); + } + + @Test + public void convertVoidMethod() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public void m(){} }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getMethods().size()); + IMethod method = sigClass.getMethods().iterator().next(); + assertTrue(method.getModifiers().contains(Modifier.PUBLIC)); + assertEquals("m", method.getName()); + assertSame(SigPrimitiveType.VOID_TYPE, method.getReturnType()); + } + + @Test + public void convertArrayMethod() throws IOException { + CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public String[] m(){ return null; } }"); + IApi api = convert(classSrc); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + assertEquals(1, sigClass.getMethods().size()); + IMethod method = sigClass.getMethods().iterator().next(); + assertTrue(method.getModifiers().contains(Modifier.PUBLIC)); + assertEquals("m", method.getName()); + IArrayType arrayType = (IArrayType) method.getReturnType(); + IClassDefinition clazz = ((IClassReference) arrayType.getComponentType()).getClassDefinition(); + assertEquals("java.lang.String", clazz.getQualifiedName()); + } + + @Test + public void testParameterConformance1() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "import java.util.List;" + + "public class A<T> {" + + " public String[] a;" + + " public String[] b;" + + " public List<String> c;" + + " public List<String> d;" + + " public List<T> e;" + + " public List<T> f;" + + "}" + )); + IPackage p = ModelUtil.getPackage(api, "test"); + assertEquals("test", p.getName()); + IClassDefinition c = ModelUtil.getClass(p, "A"); + assertEquals("A", c.getName()); + assertEquals("test.A", c.getQualifiedName()); + + Map<String, IField> fields = new HashMap<String, IField>(); + for(IField f : c.getFields()){ + fields.put(f.getName(), f); + } + assertSame(((IClassReference)((IArrayType)fields.get("a").getType()).getComponentType()).getClassDefinition(), ((IClassReference)((IArrayType)fields.get("b").getType()).getComponentType()).getClassDefinition()); + assertSame(((IParameterizedType)fields.get("c").getType()).getRawType().getClassDefinition(), ((IParameterizedType)fields.get("d").getType()).getRawType().getClassDefinition()); + assertSame(((IParameterizedType)fields.get("e").getType()).getRawType().getClassDefinition(), ((IParameterizedType)fields.get("f").getType()).getRawType().getClassDefinition()); + + ITypeReference type = fields.get("f").getType(); + assertTrue(type instanceof IParameterizedType); + ITypeReference typeArgument = ((IParameterizedType)type).getTypeArguments().get(0); + ITypeVariableDefinition typeParameter = c.getTypeParameters().get(0); + assertSame(((ITypeVariableReference)typeArgument).getTypeVariableDefinition(), typeParameter); + } + + @Test + public void testParameterConformance2() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public class A<T> {" + + " public <T> T foo(T t){return null;}" + + "}" + )); + IPackage p = ModelUtil.getPackage(api, "test"); + assertEquals("test", p.getName()); + + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + ITypeVariableDefinition t = sigClass.getTypeParameters().get(0); + + IMethod sigMethod = sigClass.getMethods().iterator().next(); + ITypeVariableDefinition t1 = sigMethod.getTypeParameters().get(0); + IParameter param = sigMethod.getParameters().get(0); + ITypeReference t2 = param.getType(); + ITypeReference t3 = sigMethod.getReturnType(); + + assertSame(t1, ((ITypeVariableReference)t2).getTypeVariableDefinition()); + assertSame(((ITypeVariableReference)t2).getTypeVariableDefinition(), ((ITypeVariableReference)t3).getTypeVariableDefinition()); + + assertNotSame(t, t1); + } + + @Test + public void testInnerReferenceToOuterTypeVariable() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public class A<T> {" + + " public class B {" + + " public T f;" + + " } " + + "}" + )); + IPackage p = ModelUtil.getPackage(api, "test"); + assertEquals("test", p.getName()); + + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + ITypeVariableDefinition t = sigClass.getTypeParameters().get(0); + + IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B"); + IField field = ModelUtil.getField(innerClass, "f"); + + assertSame(t, ((ITypeVariableReference)field.getType()).getTypeVariableDefinition()); + } + + + @Test + public void convertTypeVariableMultipleUpperBound() throws IOException { + String source = + "package a; " + + "public class A<T extends Comparable<T> & java.io.Serializable> {}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + + List<ITypeVariableDefinition> typeParameters = sigClass.getTypeParameters(); + assertEquals(1, typeParameters.size()); + + ITypeVariableDefinition typeVariable = typeParameters.get(0); + List<ITypeReference> upperBounds = typeVariable.getUpperBounds(); + assertEquals(2, upperBounds.size()); + ITypeReference firstBound = upperBounds.get(0); + ITypeReference secondBound = upperBounds.get(1); + + assertTrue(firstBound instanceof IParameterizedType); + + IParameterizedType parametrizedType = (IParameterizedType)firstBound; + + IClassReference rawType = parametrizedType.getRawType(); + assertEquals("Comparable", rawType.getClassDefinition().getName()); + assertEquals(1, parametrizedType.getTypeArguments().size()); + ITypeVariableReference variable = (ITypeVariableReference) parametrizedType.getTypeArguments().get(0); + assertSame(typeVariable, variable.getTypeVariableDefinition()); + + assertTrue(secondBound instanceof IClassReference); + IClassReference secondBoundClass = (IClassReference) secondBound; + assertEquals("Serializable", secondBoundClass.getClassDefinition().getName()); + } + + @Test + public void convertPrivateStaticInnerClass0() throws IOException { + String source = + "package a; " + + "public class A { " + + " private static class I{}" + + " private transient Object i = new I(); " + + "}"; + IApi api = convert(Visibility.PRIVATE, new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.I"); + assertEquals("A.I", innerClass.getName()); + Set<IConstructor> constructors = innerClass.getConstructors(); + assertEquals(1, constructors.size()); + } + + @Test + public void convertPrivateStaticInnerClass1() throws IOException { + String source = + "package a; " + + "public class A {" + + " private static class B {" + + " public static class C {}" + + " }" + + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + assertEquals(1, sigPackage.getClasses().size()); + } + + /** + * Tests whether the first constructor argument is removed. + */ + @Test + public void convertNonStaticInnerClassConstructor0() throws IOException { + String source = + "package a; " + + "public class A {" + + " public class B {" + + " public B(){}" + + " }" + + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B"); + assertEquals(1, innerClass.getConstructors().size()); + Set<IConstructor> constructors = innerClass.getConstructors(); + IConstructor first = constructors.iterator().next(); + //implicit A.this reference must be removed + assertEquals(0, first.getParameters().size()); + } + + /** + * Tests whether the first constructor argument is removed. + */ + @Test + public void convertNonStaticInnerClassConstructor1() throws IOException { + String source = + "package a; " + + "public class A {" + + " public class B {}" + + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B"); + assertEquals(1, innerClass.getConstructors().size()); + Set<IConstructor> constructors = innerClass.getConstructors(); + IConstructor first = constructors.iterator().next(); + //implicit A.this reference must be removed + assertEquals(0, first.getParameters().size()); + } + + + +} diff --git a/tools/signature-tools/test/signature/converter/ConvertEnumTest.java b/tools/signature-tools/test/signature/converter/ConvertEnumTest.java new file mode 100644 index 00000000000..98ebd612fec --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertEnumTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import signature.converter.util.AbstractConvertTest; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; +import signature.model.IArrayType; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IConstructor; +import signature.model.IEnumConstant; +import signature.model.IField; +import signature.model.IMethod; +import signature.model.IPackage; +import signature.model.IParameter; +import signature.model.Kind; +import signature.model.Modifier; +import signature.model.util.ModelUtil; + +public abstract class ConvertEnumTest extends AbstractConvertTest { + + @Test + public void testEnum1() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public enum A {" + + " ONE, TWO, THREE" + + "}")); + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition c = ModelUtil.getClass(sigPackage, "A"); + assertNotNull(c); + assertTrue(c.getKind() == Kind.ENUM); + + Set<IEnumConstant> constants = c.getEnumConstants(); + assertEquals(3, constants.size()); + + Set<String> constantNames = new HashSet<String>(); + for (IEnumConstant constant : constants) { + constantNames.add(constant.getName()); + } + + assertTrue(constantNames.contains("ONE")); + assertTrue(constantNames.contains("TWO")); + assertTrue(constantNames.contains("THREE")); + +// IEnumConstant[] enumConstants = new IEnumConstant[3]; +// for (IEnumConstant enumConstant : constants) { +// enumConstants[enumConstant.getOrdinal()] = enumConstant; +// assertEquals(0, enumConstant.getAnnotations().size()); +// assertSame(c, enumConstant.getType()); +// } +// +// assertEquals("ONE", enumConstants[0].getName()); +// assertEquals("TWO", enumConstants[1].getName()); +// assertEquals("THREE", enumConstants[2].getName()); + } + + @Test + public void testEnum2() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public enum A {" + + " ONE, TWO, THREE;" + + " public static A FOUR = ONE;" + + "}")); + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition c = ModelUtil.getClass(sigPackage, "A"); + assertNotNull(c); + assertTrue(c.getKind() == Kind.ENUM); + + Set<IEnumConstant> constants = c.getEnumConstants(); + assertEquals(3, constants.size()); + + Set<IField> fields = c.getFields(); + assertEquals(1, fields.size()); + IField field = c.getFields().iterator().next(); + + assertEquals("FOUR", field.getName()); + assertSame(c, ((IClassReference)field.getType()).getClassDefinition()); + } + + + @Test + public void testEnum3() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public enum A {" + + " ONE(1), TWO(2), THREE(3);" + + " A(int value){}" + + "}")); + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition c = ModelUtil.getClass(sigPackage, "A"); + assertNotNull(c); + assertTrue(c.getKind() == Kind.ENUM); + + Set<IEnumConstant> constants = c.getEnumConstants(); + assertEquals(3, constants.size()); + + Set<IConstructor> ctors = c.getConstructors(); + assertEquals(0, ctors.size()); + + Set<IMethod> methods = c.getMethods(); + assertEquals(2, methods.size()); + Map<String, IMethod> map = new HashMap<String, IMethod>(); + for(IMethod m : methods){ + map.put(m.getName(), m); + } + + IMethod values = map.get("values"); + assertNotNull(values); + assertEquals(0, values.getParameters().size()); + assertTrue(values.getReturnType() instanceof IArrayType); + assertSame(c, ((IClassReference)((IArrayType)values.getReturnType()).getComponentType()).getClassDefinition()); + assertTrue(c.getModifiers().contains(Modifier.PUBLIC)); + assertFalse(c.getModifiers().contains(Modifier.STATIC)); + assertTrue(c.getModifiers().contains(Modifier.FINAL)); + + IMethod valueOf = map.get("valueOf"); + assertNotNull(valueOf); + assertEquals(1, valueOf.getParameters().size()); + IParameter param = valueOf.getParameters().iterator().next(); + assertEquals("java.lang.String", ((IClassReference)param.getType()).getClassDefinition().getQualifiedName()); + assertSame(c, ((IClassReference)valueOf.getReturnType()).getClassDefinition()); + } + + @Test + public void testEnum4() throws IOException { + IApi api = convert(new CompilationUnit("test.A", + "package test; " + + "public enum A {" + + " ONE { void m(){} }, TWO{ void m(){} };" + + " abstract void m();" + + "}")); + IPackage sigPackage = ModelUtil.getPackage(api, "test"); + IClassDefinition c = ModelUtil.getClass(sigPackage, "A"); + assertNotNull(c); + assertTrue(c.getKind() == Kind.ENUM); + + Set<IEnumConstant> constants = c.getEnumConstants(); + assertEquals(2, constants.size()); + + Set<IConstructor> ctors = c.getConstructors(); + assertEquals(0, ctors.size()); + + Set<IMethod> methods = c.getMethods(); + assertEquals(2, methods.size()); + Map<String, IMethod> map = new HashMap<String, IMethod>(); + for(IMethod m : methods){ + map.put(m.getName(), m); + } + + IMethod values = map.get("values"); + assertNotNull(values); + assertEquals(0, values.getParameters().size()); + assertTrue(values.getReturnType() instanceof IArrayType); + assertSame(c, ((IClassReference)((IArrayType)values.getReturnType()).getComponentType()).getClassDefinition()); + assertTrue(c.getModifiers().contains(Modifier.PUBLIC)); + assertFalse(c.getModifiers().contains(Modifier.STATIC)); + assertFalse(c.getModifiers().contains(Modifier.FINAL)); + } + +} diff --git a/tools/signature-tools/test/signature/converter/ConvertPackageTest.java b/tools/signature-tools/test/signature/converter/ConvertPackageTest.java new file mode 100644 index 00000000000..edd2a41c6a0 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertPackageTest.java @@ -0,0 +1,69 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IAnnotation;
+import signature.model.IApi;
+import signature.model.IPackage;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertPackageTest extends AbstractConvertTest {
+
+ // tests whether package annotations are returned
+ @Test
+ public void testPackageAnnotation() throws IOException {
+ CompilationUnit packageSrc = new CompilationUnit("a.package-info", "@Deprecated package a;");
+ CompilationUnit classSrc = new CompilationUnit("a.X", "package a; public class X{}");
+ IApi api = convert(classSrc, packageSrc);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(1, sigPackage.getAnnotations().size());
+ IAnnotation annotation = sigPackage.getAnnotations().iterator().next();
+ assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName());
+ }
+
+ // tests that package-info is not returned as class
+ @Test
+ public void testNumberOfClasses1() throws IOException {
+ CompilationUnit packageSrc = new CompilationUnit("a.package-info", "@Deprecated package a;");
+ CompilationUnit classSrc = new CompilationUnit("a.X", "package a; public class X{}");
+ IApi api = convert(classSrc, packageSrc);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(1, sigPackage.getClasses().size());
+ }
+
+ // tests that nested classes are returned as package classes
+ @Test
+ public void testNumberOfClasses2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.X",
+ "package a;" +
+ "public class X{" +
+ " public static class Y{}" +
+ "}");
+ IApi api = convert(src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(2, sigPackage.getClasses().size());
+ }
+
+}
\ No newline at end of file diff --git a/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java b/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java new file mode 100644 index 00000000000..653d42f6313 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import org.junit.Test; + +import signature.converter.util.AbstractConvertTest; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; +import signature.model.IClassDefinition; +import signature.model.IField; +import signature.model.IPackage; +import signature.model.IParameterizedType; +import signature.model.ITypeReference; +import signature.model.util.ModelUtil; + +public abstract class ConvertParameterizedTypeTest extends AbstractConvertTest { + /** + * [L, a, /, A, $, B, <, L, j, a, v, a, /, l, a, n, g, /, I, n, t, e, g, e, r, ;, >, ;] + * '$' - separated + * @throws IOException + */ + @Test + public void convertParameterizedType() throws IOException { + String source = + "package a; " + + "public class A{" + + " public class B<T> {} " + + " public A.B<Integer> f; "+ + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + IField field = ModelUtil.getField(sigClass, "f"); + + ITypeReference type = field.getType(); + assertTrue(type instanceof IParameterizedType); + + IParameterizedType parametrizedType = (IParameterizedType)type; + ITypeReference ownerType = parametrizedType.getOwnerType(); + assertNotNull(ownerType); + } + + @Test + public void convertWildcardLowerBound() throws IOException { + String clazz = + "package a; " + + "public final class A<T> implements I<T>{ " + + " abstract class Super{} " + + " final class Sub extends Super implements I<T>{} " + + "}"; + String interfaze = + "package a; " + + "public interface I <T>{}"; + IApi api = convert(Visibility.PRIVATE, new CompilationUnit("a.A", clazz),new CompilationUnit("a.I", interfaze)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.Sub"); + System.out.println(sigClass); + } + + public class A{ + public class B<T> {} + public A.B<Integer> f; + } + + @Test + public void reflectionTest0() throws SecurityException, NoSuchFieldException{ + Field field = A.class.getDeclaredField("f"); + ParameterizedType paramType = (ParameterizedType)field.getGenericType(); + assertNotNull(paramType.getOwnerType()); + } + + public static class C<T>{} + + ConvertParameterizedTypeTest.C<String> f; + + @Test + public void reflectionTest1() throws SecurityException, NoSuchFieldException{ + Field field = ConvertParameterizedTypeTest.class.getDeclaredField("f"); + ParameterizedType paramType = (ParameterizedType)field.getGenericType(); + assertNotNull(paramType.getOwnerType()); + } + + public static class E<T>{ + static class F<Q>{} + E.F<String> f; + } + + + @Test + public void reflectionTest2() throws SecurityException, NoSuchFieldException { + Field field = E.class.getDeclaredField("f"); + ParameterizedType paramType = (ParameterizedType) field.getGenericType(); + assertNotNull(paramType.getOwnerType()); + } +} diff --git a/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java b/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java new file mode 100644 index 00000000000..09fc32f1fc9 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java @@ -0,0 +1,173 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.Test;
+
+import signature.converter.Visibility;
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+import signature.model.IClassDefinition;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertVisibilityTest extends AbstractConvertTest {
+
+ @Test
+ public void testVisibilityMethods1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public class A{" +
+ " public void foo1(){}" +
+ " protected void foo2(){}" +
+ " void foo3(){}" +
+ " private void foo4(){}" +
+ "}");
+
+ IApi api = convert(Visibility.PUBLIC, src);
+ IPackage p = ModelUtil.getPackage(api, "a");
+ IClassDefinition c = ModelUtil.getClass(p, "A");
+ Set<IMethod> methods = c.getMethods();
+ assertEquals(1, methods.size());
+ }
+
+ @Test
+ public void testVisibilityMethods2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public class A{" +
+ " public void foo1(){}" +
+ " protected void foo2(){}" +
+ " void foo3(){}" +
+ " private void foo4(){}" +
+ "}");
+
+ IApi api = convert(Visibility.PROTECTED, src);
+ IPackage p = ModelUtil.getPackage(api, "a");
+ IClassDefinition c = ModelUtil.getClass(p, "A");
+ Set<IMethod> methods = c.getMethods();
+ assertEquals(2, methods.size());
+ }
+
+ @Test
+ public void testVisibilityMethods3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public class A{" +
+ " public void foo1(){}" +
+ " protected void foo2(){}" +
+ " void foo3(){}" +
+ " private void foo4(){}" +
+ "}");
+
+ IApi api = convert(Visibility.PACKAGE, src);
+ IPackage p = ModelUtil.getPackage(api, "a");
+ IClassDefinition c = ModelUtil.getClass(p, "A");
+ Set<IMethod> methods = c.getMethods();
+ assertEquals(3, methods.size());
+ }
+
+ @Test
+ public void testVisibilityMethods4() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.A",
+ "package a;" +
+ "public class A{" +
+ " public void foo1(){}" +
+ " protected void foo2(){}" +
+ " void foo3(){}" +
+ " private void foo4(){}" +
+ "}");
+
+ IApi api = convert(Visibility.PRIVATE, src);
+ IPackage p = ModelUtil.getPackage(api, "a");
+ IClassDefinition c = ModelUtil.getClass(p, "A");
+ Set<IMethod> methods = c.getMethods();
+ assertEquals(4, methods.size());
+ }
+
+ @Test
+ public void testVisibility1() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.X1",
+ "package a;" +
+ "public class X1{" +
+ " static class X2{}" +
+ " protected static class X3{}" +
+ " private static class X4{}" +
+ "}");
+
+ IApi api = convert(Visibility.PUBLIC, src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(1, sigPackage.getClasses().size());
+ }
+
+ @Test
+ public void testVisibility2() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.X1",
+ "package a;" +
+ "public class X1{" +
+ " static class X2{}" +
+ " protected static class X3{}" +
+ " private static class X4{}" +
+ "}");
+
+ IApi api = convert(Visibility.PROTECTED, src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(2, sigPackage.getClasses().size());
+ assertNotNull(ModelUtil.getClass(sigPackage, "X1.X3"));
+ }
+
+ @Test
+ public void testVisibility3() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.X1",
+ "package a;" +
+ "public class X1{" +
+ " static class X2{}" +
+ " protected static class X3{}" +
+ " private static class X4{}" +
+ "}");
+
+ IApi api = convert(Visibility.PACKAGE, src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(3, sigPackage.getClasses().size());
+ assertNotNull(ModelUtil.getClass(sigPackage, "X1.X2"));
+ }
+
+ @Test
+ public void testVisibility4() throws IOException {
+ CompilationUnit src = new CompilationUnit("a.X1",
+ "package a;" +
+ "public class X1{" +
+ " static class X2{}" +
+ " protected static class X3{}" +
+ " private static class X4{}" +
+ "}");
+
+ IApi api = convert(Visibility.PRIVATE, src);
+ IPackage sigPackage = ModelUtil.getPackage(api, "a");
+ assertEquals(4, sigPackage.getClasses().size());
+ assertNotNull(ModelUtil.getClass(sigPackage, "X1.X4"));
+ }
+
+}
\ No newline at end of file diff --git a/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java b/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java new file mode 100644 index 00000000000..d18c568d63c --- /dev/null +++ b/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import signature.converter.util.AbstractConvertTest; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; +import signature.model.IClassDefinition; +import signature.model.IClassReference; +import signature.model.IField; +import signature.model.IPackage; +import signature.model.IParameterizedType; +import signature.model.ITypeReference; +import signature.model.IWildcardType; +import signature.model.util.ModelUtil; + +import java.io.IOException; + +public abstract class ConvertWildcardTest extends AbstractConvertTest { + + @Test + public void convertWildcardUpperBound() throws IOException { + String source = + "package a; " + + "public class A{" + + " public java.util.Set<? extends Number> f; "+ + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + IField field = ModelUtil.getField(sigClass, "f"); + + ITypeReference type = field.getType(); + assertTrue(type instanceof IParameterizedType); + + IParameterizedType parametrizedType = (IParameterizedType)type; + + IClassDefinition rawType = parametrizedType.getRawType().getClassDefinition(); + assertEquals("Set", rawType.getName()); + + assertEquals(1, parametrizedType.getTypeArguments().size()); + IWildcardType wildcardType = (IWildcardType) parametrizedType.getTypeArguments().get(0); + assertEquals(1, wildcardType.getUpperBounds().size()); + ITypeReference upperBound = wildcardType.getUpperBounds().get(0); + assertTrue(upperBound instanceof IClassReference); + + assertEquals("Number", ((IClassReference)upperBound).getClassDefinition().getName()); + } + + @Test + public void convertWildcardLowerBound() throws IOException { + String source = + "package a; " + + "public class A{" + + " public java.util.Set<? super Number> f; "+ + "}"; + IApi api = convert(new CompilationUnit("a.A", source)); + IPackage sigPackage = ModelUtil.getPackage(api, "a"); + IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A"); + IField field = ModelUtil.getField(sigClass, "f"); + + ITypeReference type = field.getType(); + assertTrue(type instanceof IParameterizedType); + + IParameterizedType parametrizedType = (IParameterizedType)type; + + IClassDefinition rawType = parametrizedType.getRawType().getClassDefinition(); + assertEquals("Set", rawType.getName()); + + assertEquals(1, parametrizedType.getTypeArguments().size()); + IWildcardType wildcardType = (IWildcardType) parametrizedType.getTypeArguments().get(0); + assertEquals(1, wildcardType.getUpperBounds().size()); + ITypeReference upperBound = wildcardType.getUpperBounds().get(0); + assertTrue(upperBound instanceof IClassReference); + assertEquals("Object", ((IClassReference)upperBound).getClassDefinition().getName()); + + ITypeReference lowerBound = wildcardType.getLowerBound(); + assertTrue(lowerBound instanceof IClassReference); + assertEquals("Number", ((IClassReference)lowerBound).getClassDefinition().getName()); + } +} diff --git a/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java b/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java new file mode 100644 index 00000000000..8e27da52704 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import org.junit.Test; + +import signature.converter.Visibility; +import signature.io.IApiExternalizer; +import signature.io.impl.BinaryApi; +import signature.model.IApi; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; + +public class DexExternalizerTest { + + @Test + public void testExternalizer() throws IOException{ + DexToSigConverter converter = new DexToSigConverter(); + IApi api = converter.convertApi("Dex Tests", DexUtil.getDexFiles(new HashSet<String>(Arrays.asList(new String[]{"resources/javaCore.dex"}))), Visibility.PRIVATE); + System.setProperty("sun.io.serialization.extendedDebugInfo", "true"); + IApiExternalizer externalizer = new BinaryApi(); + externalizer.externalizeApi("dex-spec", api); + } +} diff --git a/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java b/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java new file mode 100644 index 00000000000..b6b90fa4a04 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import dex.reader.util.JavaSource; +import dex.reader.util.JavaSourceToDexUtil; +import dex.structure.DexFile; +import signature.converter.Visibility; +import signature.converter.dex.DexToSigConverter; +import signature.converter.util.AbstractTestSourceConverter; +import signature.converter.util.CompilationUnit; +import signature.model.IApi; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class DexTestConverter extends AbstractTestSourceConverter { + + public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException { + JavaSourceToDexUtil toDexUtil = new JavaSourceToDexUtil(); + DexToSigConverter converter = new DexToSigConverter(); + Set<JavaSource> sources = new HashSet<JavaSource>(); + for (CompilationUnit unit : units) { + sources.add(new JavaSource(unit.getName(), unit.getSource())); + } + DexFile dexFile = toDexUtil.getAllFrom(sources); + return converter.convertApi("Dex Tests", Collections.singleton(dexFile), visibility); + } + +} diff --git a/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java b/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java new file mode 100644 index 00000000000..ff005fb78d1 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + + +import dex.reader.DexTestsCommon; +import dex.reader.util.JavaSource; +import dex.reader.util.JavaSourceToDexUtil; +import dex.structure.DexClass; +import dex.structure.DexFile; + +import org.junit.Before; +import org.junit.Test; + +import signature.converter.dex.DexToSigConverter; +import signature.model.impl.SigPackage; +import static signature.converter.dex.DexUtil.*; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class DexUtilTest extends DexTestsCommon { + + private JavaSourceToDexUtil dexUtil; + private DexToSigConverter converter; + + @Before + public void setupDexUtil(){ + dexUtil = new JavaSourceToDexUtil(); + converter = new DexToSigConverter(); + } + + @Test + public void convertPackageTest(){ + SigPackage aPackage = converter.convertPackage("a"); + assertEquals("a", aPackage.getName()); + + aPackage = converter.convertPackage("a.b.c"); + assertEquals("a.b.c", aPackage.getName()); + } + + @Test + public void getPackageNameTest(){ + assertEquals("",getPackageName("LA;")); + assertEquals("a",getPackageName("La/A;")); + assertEquals("a.b.c",getPackageName("La/b/c/A;")); + } + + @Test + public void getClassNameTest(){ + assertEquals("A",getClassName("LA;")); + assertEquals("A",getClassName("La/A;")); + assertEquals("A",getClassName("La/b/c/A;")); + } + + @Test + public void hasGenericSignatureTest() throws IOException { + DexFile dexFile = dexUtil.getFrom(new JavaSource("A", "public class A{}")); + DexClass dexClass = getClass(dexFile, "LA;"); + assertFalse(hasGenericSignature(dexClass)); + + dexFile = dexUtil.getFrom(new JavaSource("B", "public class B<T>{}")); + dexClass = getClass(dexFile, "LB;"); + assertTrue(hasGenericSignature(dexClass)); + } + + @Test + public void getGenericSignatureTest() throws IOException { + DexFile dexFile = dexUtil.getFrom(new JavaSource("A", "public class A{}")); + DexClass dexClass = getClass(dexFile, "LA;"); + assertNull(getGenericSignature(dexClass)); + + dexFile = dexUtil.getFrom(new JavaSource("B", "public class B<T>{}")); + dexClass = getClass(dexFile, "LB;"); + assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", getGenericSignature(dexClass)); + } + + + +} diff --git a/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java b/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java new file mode 100644 index 00000000000..52d73f8955c --- /dev/null +++ b/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.dex; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import dex.reader.DexTestsCommon; +import dex.reader.util.JavaSource; +import dex.reader.util.JavaSourceToDexUtil; +import dex.structure.DexClass; +import dex.structure.DexFile; + +import org.junit.Before; +import org.junit.Test; + +import signature.converter.dex.DexToSigConverter; +import signature.converter.dex.DexUtil; +import signature.converter.dex.GenericSignatureParser; +import signature.model.impl.SigClassDefinition; +import signature.model.util.TypePool; + +import java.io.IOException; + +public class GenericSignatureParserTest extends DexTestsCommon{ + + private DexToSigConverter converter; + private JavaSourceToDexUtil dexUtil; + private GenericSignatureParser parser; + + @Before + public void setupConverter(){ + converter = new DexToSigConverter(); + dexUtil = new JavaSourceToDexUtil(); + parser = new GenericSignatureParser(new TypePool(), converter); + } + + @Test + public void getGenericSignatureTest() throws IOException { + DexFile dexFile = dexUtil.getFrom(new JavaSource("B", "public class B<T>{}")); + DexClass dexClass = getClass(dexFile, "LB;"); + assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", DexUtil.getGenericSignature(dexClass)); + SigClassDefinition sigClass = converter.convertClass(dexClass); + + parser.parseForClass(sigClass, DexUtil.getGenericSignature(dexClass)); + //type parameter name + assertEquals(1, parser.formalTypeParameters.size()); + assertEquals("T", parser.formalTypeParameters.get(0).getName()); + //type parameter declaration + assertSame(sigClass, parser.formalTypeParameters.get(0).getGenericDeclaration()); + //type parameter upper bounds + assertEquals(1, parser.formalTypeParameters.get(0).getUpperBounds().size()); +// IType type = parser.formalTypeParameters.get(0).getUpperBounds().get(0); + + } +} diff --git a/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java b/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java new file mode 100644 index 00000000000..8e867ddb469 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java @@ -0,0 +1,182 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signature.converter.doclet;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.util.HashSet;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.converter.doclet.DocletToSigConverter;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+import signature.model.util.ModelUtil;
+
+import com.sun.javadoc.RootDoc;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Options;
+import com.sun.tools.javadoc.JavadocTool;
+import com.sun.tools.javadoc.Messager;
+import com.sun.tools.javadoc.ModifierFilter;
+import com.sun.tools.javadoc.RootDocImpl;
+
+public class DocletTestConverter extends signature.converter.util.AbstractTestSourceConverter {
+
+ static String sourcepath;
+ static String separator;
+
+ static {
+ separator = System.getProperty("file.separator");
+
+ sourcepath = System.getProperty("java.io.tmpdir");
+ sourcepath = sourcepath + separator + "cts" + separator;
+ System.out.println(">> "+sourcepath);
+ }
+
+ public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException {
+ try {
+ Set<String> packages = new HashSet<String>();
+ for(CompilationUnit u : units){
+ putSource(u);
+ String p = ModelUtil.getPackageName(u.getName());
+ assert p.length() > 0 : "default package not supported by doclets";
+ packages.add(p);
+ }
+
+ RootDoc root = getRootDoc(visibility, packages);
+
+ DocletToSigConverter converter = new DocletToSigConverter();
+
+ IApi api = converter.convertDocletRoot("Doclet Test", root, visibility, packages);
+ return api;
+ }
+ finally {
+ removeSources();
+ }
+ }
+
+ public static void putSource(CompilationUnit source) throws IOException {
+ String directory = sourcepath;
+ String filename = source.getName(); // a.b.C
+ int pos = filename.indexOf(".");
+ while(pos > 0) {
+ directory = directory + filename.substring(0, pos) + separator;
+ filename = filename.substring(pos+1);
+ pos = filename.indexOf(".");
+ }
+
+ File file = new File(directory, filename + ".java");
+ File parent = file.getParentFile();
+ parent.mkdirs();
+
+ FileWriter wr = new FileWriter(file);
+ wr.write(source.getSource());
+ wr.close();
+ }
+
+ private static void removeSources() {
+ File file = new File(sourcepath);
+ removeFile(file);
+ }
+
+ private static void removeFile(File file){
+ if(file.isDirectory()){
+ for(File f : file.listFiles()) removeFile(f);
+ }
+ file.delete();
+ }
+
+ private static RootDoc getRootDoc(Visibility visibility, java.util.Set<String> packages) throws IOException {
+ long accessModifier = 0;
+ if(visibility == Visibility.PUBLIC){
+ accessModifier =
+ com.sun.tools.javac.code.Flags.PUBLIC; // 0x1
+ }
+ if(visibility == Visibility.PROTECTED){
+ accessModifier =
+ com.sun.tools.javac.code.Flags.PUBLIC // 0x1
+ | com.sun.tools.javac.code.Flags.PROTECTED; // 0x4
+ }
+ if(visibility == Visibility.PACKAGE){
+ accessModifier =
+ com.sun.tools.javac.code.Flags.PUBLIC // 0x1
+ | com.sun.tools.javac.code.Flags.PROTECTED // 0x4
+ | com.sun.tools.javadoc.ModifierFilter.PACKAGE; // 0x80000000
+ }
+ if(visibility == Visibility.PRIVATE){
+ accessModifier =
+ com.sun.tools.javac.code.Flags.PUBLIC // 0x1
+ | com.sun.tools.javac.code.Flags.PROTECTED // 0x4
+ | com.sun.tools.javadoc.ModifierFilter.PACKAGE // 0x80000000
+ | com.sun.tools.javac.code.Flags.PRIVATE; // 0x2
+ }
+
+ ModifierFilter showAccess = new ModifierFilter(accessModifier);
+ boolean breakiterator = false;
+ boolean quiet = false;
+ boolean legacy = false;
+ boolean docClasses = false;
+
+ String docLocale = "";
+ String encoding = null;
+ ListBuffer<String> javaNames = new ListBuffer<String>();
+ for(String p : packages)
+ javaNames.append(p);
+
+ ListBuffer<String[]> options = new ListBuffer<String[]>();
+
+
+// String sourcepath = "//D:/Documents/Projects/08_CTS/signature-tools/signature-tools/test/";
+ options.append(new String[]{"-sourcepath", sourcepath});
+
+ ListBuffer<String> subPackages = new ListBuffer<String>();
+ ListBuffer<String> excludedPackages = new ListBuffer<String>();
+
+ Context context = new Context();
+ Options compOpts = Options.instance(context);
+ compOpts.put("-sourcepath", sourcepath);
+
+ Constructor<Messager> c;
+ try {
+// c = Messager.class.getDeclaredConstructor(Context.class, String.class);
+// c.setAccessible(true);
+// c.newInstance(context, "SigTest");
+ c = Messager.class.getDeclaredConstructor(Context.class, String.class, PrintWriter.class, PrintWriter.class, PrintWriter.class);
+ c.setAccessible(true);
+ PrintWriter err = new PrintWriter(new StringWriter());
+ PrintWriter warn = new PrintWriter(new StringWriter());
+ PrintWriter notice = new PrintWriter(new StringWriter());
+ c.newInstance(context, "SigTest", err, warn, notice);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ JavadocTool comp = JavadocTool.make0(context);
+ RootDocImpl root = comp.getRootDocImpl(docLocale, encoding, showAccess,
+ javaNames.toList(), options.toList(), breakiterator,
+ subPackages.toList(), excludedPackages.toList(), docClasses,
+ legacy, quiet);
+ return root;
+ }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java b/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java new file mode 100644 index 00000000000..04935d8ebb1 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.util; + +import java.io.IOException; +import java.util.Set; + +import org.junit.Before; + +import signature.converter.Visibility; +import signature.model.IApi; + +public abstract class AbstractConvertTest extends AbstractTestSourceConverter { + + private ITestSourceConverter converter; + + /** + * Creates and returns a converter instance. + * @return a converter instance + */ + public abstract ITestSourceConverter createConverter(); + + + @Before + public void setupConverter(){ + converter = createConverter(); + } + + public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException { + return converter.convert(visibility, units); + } + +} diff --git a/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java b/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java new file mode 100644 index 00000000000..5ca7422f080 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.util; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IApi; + +public abstract class AbstractTestSourceConverter implements ITestSourceConverter { + + public IApi convert(Set<CompilationUnit> units) throws IOException { + return convert(Visibility.PROTECTED, units); + } + public IApi convert(CompilationUnit... units) throws IOException { + return convert(Visibility.PROTECTED, new HashSet<CompilationUnit>(Arrays.asList(units))); + } + public IApi convert(Visibility visibility, CompilationUnit... units) throws IOException { + return convert(visibility, new HashSet<CompilationUnit>(Arrays.asList(units))); + } +} + diff --git a/tools/signature-tools/test/signature/converter/util/CompilationUnit.java b/tools/signature-tools/test/signature/converter/util/CompilationUnit.java new file mode 100644 index 00000000000..95960aef0ac --- /dev/null +++ b/tools/signature-tools/test/signature/converter/util/CompilationUnit.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.util; + +public class CompilationUnit { + + /** a.b.C */ + private String name; + private String source; + + public CompilationUnit(String name, String source) { + this.name = name; + this.source = source; + } + + public String getName() { + return name; + } + + public String getSource() { + return source; + } +} diff --git a/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java b/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java new file mode 100644 index 00000000000..568a3e9bc37 --- /dev/null +++ b/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signature.converter.util; + +import java.io.IOException; +import java.util.Set; + +import signature.converter.Visibility; +import signature.model.IApi; + +public interface ITestSourceConverter { + IApi convert(Set<CompilationUnit> units) throws IOException; + IApi convert(CompilationUnit... units) throws IOException; + IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException; + IApi convert(Visibility visibility, CompilationUnit... units) throws IOException; +} |