diff --git a/DEVELOPING_OPAL/validate/src/it/scala/org/opalj/br/InvokedynamicRewritingExecutionTest.scala b/DEVELOPING_OPAL/validate/src/it/scala/org/opalj/br/InvokedynamicRewritingExecutionTest.scala index 925352173c..90919141a3 100644 --- a/DEVELOPING_OPAL/validate/src/it/scala/org/opalj/br/InvokedynamicRewritingExecutionTest.scala +++ b/DEVELOPING_OPAL/validate/src/it/scala/org/opalj/br/InvokedynamicRewritingExecutionTest.scala @@ -379,7 +379,6 @@ class InvokedynamicRewritingExecutionTest extends AnyFunSpec with Matchers { new File("OPAL/ai/src/main/resources/").toURI.toURL, new File("OPAL/ba/src/main/resources/").toURI.toURL, new File("OPAL/bi/src/main/resources/").toURI.toURL, - new File("OPAL/bp/src/main/resources/").toURI.toURL, new File("OPAL/br/src/main/resources/").toURI.toURL, new File("OPAL/common/src/main/resources/").toURI.toURL ) ++ opalDependencies diff --git a/OPAL/ai/src/main/scala/org/opalj/ai/domain/l2/PerformInvocationsWithRecursionDetection.scala b/OPAL/ai/src/main/scala/org/opalj/ai/domain/l2/PerformInvocationsWithRecursionDetection.scala index bfd763dc23..6eed5cd1b0 100644 --- a/OPAL/ai/src/main/scala/org/opalj/ai/domain/l2/PerformInvocationsWithRecursionDetection.scala +++ b/OPAL/ai/src/main/scala/org/opalj/ai/domain/l2/PerformInvocationsWithRecursionDetection.scala @@ -9,9 +9,6 @@ import org.opalj.br.Method /** * Enables to perform invocations. * - * ==Example== - * (PerformInvocationsWithRecursionDetection is in particular used by BugPicker's domain.) - * * @author Michael Eichberg */ trait PerformInvocationsWithRecursionDetection extends PerformInvocations with TheMemoryLayout { diff --git a/TOOLS/bp/build.sbt b/TOOLS/bp/build.sbt deleted file mode 100644 index b511e98651..0000000000 --- a/TOOLS/bp/build.sbt +++ /dev/null @@ -1 +0,0 @@ -// build settings reside in the opal root build.sbt file diff --git a/TOOLS/bp/src/TODO/BoxingImmediatelyUnboxedToPerformCoercion.scala b/TOOLS/bp/src/TODO/BoxingImmediatelyUnboxedToPerformCoercion.scala deleted file mode 100644 index f8a322c7c2..0000000000 --- a/TOOLS/bp/src/TODO/BoxingImmediatelyUnboxedToPerformCoercion.scala +++ /dev/null @@ -1,122 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports code such as this: - * {{{ - * new Integer(1).doubleValue() - * }}} - * where a literal value is boxed into an object and then immediately unboxed. This means - * that the object creation was useless. - * - * IMPROVE to also detect code like this: {{{Integer.valueOf(1).doubleValue()}}} - * - * @author Ralf Mitschke - * @author Daniel Klauer - * @author Michael Eichberg - */ -object BoxingImmediatelyUnboxedToPerformCoercion { - - override def description: String = - "Reports sections of code that box a value but then immediately unbox it." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: SomeProject, - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[LineAndColumnBasedReport[Source]] = { - - // For each method doing INVOKESPECIAL followed by INVOKEVIRTUAL on the same - // java.lang class, where the called method's name ends in "Value"... - val theTypes = scala.collection.mutable.HashSet( - ClassType.Boolean, - ClassType.Byte, - ClassType.Character, - ClassType.Short, - ClassType.Integer, - ClassType.Long, - ClassType.Float, - ClassType.Double - ) - val theMethods = scala.collection.mutable.HashSet( - "booleanValue", - "byteValue", - "charValue", - "shortValue", - "intValue", - "longValue", - "floatValue", - "doubleValue" - ) - - var result: List[LineAndColumnBasedReport[Source]] = List.empty - for { - classFile <- project.allProjectClassFiles - if classFile.majorVersion >= 49 - if !project.isLibraryType(classFile) - method @ MethodWithBody(body) <- classFile.methods - } { - val instructions = body.instructions - val max_pc = body.instructions.length - - var pc = 0 - var next_pc = body.pcOfNextInstruction(pc) - - while (next_pc < max_pc) { - if (pc + 3 == next_pc) { - instructions(pc) match { - case INVOKESPECIAL(receiver1, _, TheArgument(parameterType: BaseType)) => - instructions(next_pc) match { - case INVOKEVIRTUAL( - `receiver1`, - name, - NoArgumentMethodDescriptor(returnType: BaseType) - ) - if ((returnType ne parameterType) && (theTypes.contains( - receiver1 - ) && theMethods.contains(name))) => { - result = - LineAndColumnBasedReport( - project.source(classFile.thisType), - Severity.Info, - classFile.thisType, - method.descriptor, - method.name, - body.lineNumber(pc), - None, - "Value boxed and immediately unboxed" - ) :: result - // we have matched the sequence - pc = body.pcOfNextInstruction(next_pc) - } - case _ => - pc = next_pc - next_pc = body.pcOfNextInstruction(pc) - - } - case _ => - pc = next_pc - next_pc = body.pcOfNextInstruction(pc) - } - } else { - pc = next_pc - next_pc = body.pcOfNextInstruction(pc) - } - } - } - result - } -} diff --git a/TOOLS/bp/src/TODO/CloneDoesNotCallSuperClone.scala b/TOOLS/bp/src/TODO/CloneDoesNotCallSuperClone.scala deleted file mode 100644 index 687df7ceda..0000000000 --- a/TOOLS/bp/src/TODO/CloneDoesNotCallSuperClone.scala +++ /dev/null @@ -1,91 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import org.opalj.br.MethodDescriptor.JustReturnsObject - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports `clone()` methods that do not contain a call to `super.clone`. - * Such `clone()` methods are probably (but not necessarily) implemented incorrectly. - * - * In order to satisfy the standard `clone()` contract, `clone()` must return an object of - * the same class it was called on. If every `clone()` method in an inheritance hierarchy - * calls `super.clone()`, then `Object.clone()` will eventually be called and create an - * object of the proper type. - * - * If a clone() method does not rely on `Object.clone()` to create the new object, but - * instead invokes a constructor of some class, it will always return an object of that - * class, regardless of whether it was actually called on an object of that type. - * - * This can cause problems if this `clone()` is inherited by a subclass, because then - * calling `clone()` on the subclass returns an instance of the superclass, instead of - * an instance of the subclass as it should. This violates the `clone()` contract. If the - * `clone()` method would call `super.clone()` instead of a constructor, then this issue - * would not happen, because `Object.clone()` would have created an object of the proper - * type. - * - * Of course, if the subclass implements `clone()` by creating the proper object itself, - * or the superclass with the suspicious `clone()` is `final` so that there cannot be any - * subclasses, then the mentioned problem can never occur. - * - * TODO: Ideas to improve this analysis: - * - It currently only checks whether a call to `super.clone()` exists inside `clone()`, - * but not whether it is actually reached/executed on all possible code paths. - * - It produces false-positives when super.clone() is called indirectly through a helper - * method. - * - It produces false-positives in cases where super.clone() doesn't need to be called: - * - if there are no subclasses, - * - or if the class is `final` so that there can be no subclasses, - * - or if all subclasses implement clone() themselves without calling super.clone(), - * i.e. the subclasses themselves take care of creating the proper object, so the - * superclass' clone() doesn't need to make sure to eventually call Object.clone() by - * calling super.clone(). - * - * @author Ralf Mitschke - * @author Daniel Klauer - */ -class CloneDoesNotCallSuperClone[Source] extends FindRealBugsAnalysis[Source] { - - override def description: String = - "Reports clone() methods that do not contain a call to super.clone()." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[MethodBasedReport[Source]] = { - - // For each clone() methods that doesn't contain a call to super.clone()... - for { - classFile <- project.allProjectClassFiles - if !classFile.isInterfaceDeclaration && !classFile.isAnnotationDeclaration - superClass <- classFile.superclassType.toSeq - method @ Method(_, "clone", JustReturnsObject) <- classFile.methods - if method.body.isDefined - if !method.body.get.instructions.exists { - case INVOKESPECIAL(`superClass`, "clone", JustReturnsObject) => true - case _ => false - } - } yield { - MethodBasedReport( - project.source(classFile.thisType), - Severity.Warning, - classFile.thisType, - method, - "Missing call to super.clone()" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/DoInsideDoPrivileged.scala b/TOOLS/bp/src/TODO/DoInsideDoPrivileged.scala deleted file mode 100644 index d2f27f1674..0000000000 --- a/TOOLS/bp/src/TODO/DoInsideDoPrivileged.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports invocations of `java.lang.reflect.Field|Method.setAccessible()` - * outside of doPrivileged blocks. - * - * @author Ralf Mitschke - * @author Roberts Kolosovs - */ -class DoInsideDoPrivileged[Source] extends FindRealBugsAnalysis[Source] { - - /** - * Returns a description text for this analysis. - * @return analysis description - */ - override def description: String = - "Detects calls to setAccessible() outside of doPrivileged blocks." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[MethodBasedReport[Source]] = { - - // For all classes referencing neither privilegedAction nor - // privilegedExceptionAction, look for methods that call setAccessible() on - // java/lang/reflect/{Field|Method}. - for { - classFile <- project.allProjectClassFiles - if !classFile.interfaceTypes.contains(ClassType.PrivilegedAction) && - !classFile.interfaceTypes.contains(ClassType.PrivilegedExceptionAction) - method @ MethodWithBody(body) <- classFile.methods - ( - _, - INVOKEVIRTUAL( - ClassType.Field | ClassType.Method, - "setAccessible", - _ - ) - ) <- body.associateWithIndex - } yield { - MethodBasedReport( - project.source(classFile.thisType), - Severity.Warning, - classFile.thisType, - method, - "Calls java.lang.reflect.Field|Method.setAccessible() outside of " + - "doPrivileged block" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/EqualsHashCodeContract.scala b/TOOLS/bp/src/TODO/EqualsHashCodeContract.scala deleted file mode 100644 index d7584384b2..0000000000 --- a/TOOLS/bp/src/TODO/EqualsHashCodeContract.scala +++ /dev/null @@ -1,78 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* - -/** - * This analysis reports violations of the contract defined in `java.lang.Object` w.r.t. - * the methods `equals` and `hashcode`. - * - * @author Michael Eichberg - */ -class EqualsHashCodeContract[Source] extends FindRealBugsAnalysis[Source] { - - /** - * Returns a description text for this analysis. - * @return analysis description - */ - override def description: String = "Finds violations of the equals-hashCode contract." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[ClassBasedReport[Source]] = { - - val mutex = new Object - var reports = List[ClassBasedReport[Source]]() - - for (classFile <- project.allProjectClassFiles) { - var definesEqualsMethod = false - var definesHashCodeMethod = false - for (method <- classFile.methods) method match { - case Method( - _, - "equals", - MethodDescriptor( - Seq(ClassType.Object), - BooleanType - ) - ) => - definesEqualsMethod = true - case Method( - _, - "hashCode", - MethodDescriptor( - Seq(), - IntegerType - ) - ) => - definesHashCodeMethod = true - case _ => - } - - if (definesEqualsMethod != definesHashCodeMethod) { - mutex.synchronized { - reports = ClassBasedReport( - project.source(classFile.thisType), - Severity.Error, - classFile.thisType, - "Does not satisfy java.lang.Object's equals-hashCode " + - "contract." - ) :: reports - } - } - } - reports - } -} diff --git a/TOOLS/bp/src/TODO/InefficientToArray.scala b/TOOLS/bp/src/TODO/InefficientToArray.scala deleted file mode 100644 index f395346eca..0000000000 --- a/TOOLS/bp/src/TODO/InefficientToArray.scala +++ /dev/null @@ -1,101 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports code that calls `SomeCollectionClassObject.toArray(T[])` with - * zero-length array argument, for example: - * {{{ - * myList.toArray(new T[0]) - * }}} - * This is bad because this `toArray()` call will never optimize for speed by re-using the - * array passed in as argument for returning the result. Such code should do something - * like this instead: - * {{{ - * myList.toArray(new T[myList.size()]) - * }}} - * - * @author Ralf Mitschke - * @author Daniel Klauer - */ -class InefficientToArray[Source] extends FindRealBugsAnalysis[Source] { - - /** - * Returns a description text for this analysis. - * @return analysis description - */ - override def description: String = "Reports inefficient toArray(T[]) calls" - - private val objectArrayType = ArrayType(ClassType.Object) - private val toArrayDescriptor = MethodDescriptor( - IndexedSeq(objectArrayType), - objectArrayType - ) - - /** - * Checks whether a type inherits from java/util/Collection or is java/util/List. - * @param classHierarchy class hierarchy to search in - * @param checkedType type, that is checked if it's a collection or list - * @return true, if checkedType is a collection or list, false otherwise - */ - private def isCollectionType( - classHierarchy: ClassHierarchy - )(checkedType: ReferenceType): Boolean = { - checkedType.isClassType && - (classHierarchy.isSubtypeOf( - checkedType.asClassType, - ClassType.Collection - ).isNoOrUnknown || checkedType == ClassType.List) - // TODO needs more heuristic or more analysis - } - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[LineAndColumnBasedReport[Source]] = { - - val classHierarchy: ClassHierarchy = project.classHierarchy - val isCollectionType = this.isCollectionType(classHierarchy) _ - - // In all method bodies, look for calls to "toArray()" with "new ...[0]" argument, - // on objects derived from the Collection classes. - for { - classFile <- project.allProjectClassFiles - method @ MethodWithBody(body) <- classFile.methods - pc <- body.matchTriple { - case ( - ICONST_0, - _: ANEWARRAY, - VirtualMethodInvocationInstruction(targetType, "toArray", `toArrayDescriptor`) - ) => - isCollectionType(targetType) - case _ => false - } - } yield { - LineAndColumnBasedReport( - project.source(classFile.thisType), - Severity.Info, - classFile.thisType, - method.descriptor, - method.name, - body.lineNumber(pc), - None, - "Calling x.toArray(new T[0]) is inefficient, should be " + - "x.toArray(new T[x.size()])" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/LongBitsToDoubleInvokedOnInt.scala b/TOOLS/bp/src/TODO/LongBitsToDoubleInvokedOnInt.scala deleted file mode 100644 index 52cdb142af..0000000000 --- a/TOOLS/bp/src/TODO/LongBitsToDoubleInvokedOnInt.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports code that passes a 32bit `int` to `Double.longBitsToDouble()`, - * which takes a 64bit `long`. Such code is broken, because an `int` is too small to hold - * a `double`'s bit pattern. - * - * The conversion from `int` to `long` may change the bit pattern (sign extension), and - * even if that doesn't happen the outcome won't necessarily be intended/expected. Perhaps - * `float` should have been used, instead of `double` - or `long` instead of `int`. - * - * @author Ralf Mitschke - * @author Daniel Klauer - */ -class LongBitsToDoubleInvokedOnInt[Source] extends FindRealBugsAnalysis[Source] { - - /** - * Returns a description text for this analysis. - * @return analysis description - */ - override def description: String = - "Reports code passing ints to Double.longBitsToDouble(long)" - - private val longBitsToDoubleDescriptor = - MethodDescriptor(IndexedSeq(LongType), ClassType.Double) - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[LineAndColumnBasedReport[Source]] = { - - // In all method bodies, look for occurrences of (I2L, INVOKESTATIC) instruction - // sequences, where the INVOKESTATIC is a call to - // java.lang.Double.longBitsToDouble(). - for { - classFile <- project.allProjectClassFiles - method @ MethodWithBody(body) <- classFile.methods - pc <- body.matchPair { - case ( - I2L, - INVOKESTATIC(`ClassType.Double`, "longBitsToDouble", `longBitsToDoubleDescriptor`) - ) => true - case _ => false - } - } yield { - LineAndColumnBasedReport( - project.source(classFile.thisType), - Severity.Error, - classFile.thisType, - method.descriptor, - method.name, - body.lineNumber(pc), - None, - "Passing int to Double.longBitsToDouble(long)" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/NonSerializableClassHasASerializableInnerClass.scala b/TOOLS/bp/src/TODO/NonSerializableClassHasASerializableInnerClass.scala deleted file mode 100644 index caef1c444a..0000000000 --- a/TOOLS/bp/src/TODO/NonSerializableClassHasASerializableInnerClass.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import bi.AccessFlagsMatcher -import br.* -import br.analyses.* - -/** - * This analysis reports outer classes that have (non-`static`) inner `Serializable` - * classes without themselves being `Serializable`. - * - * This situation is problematic, because the serialization of the inner class would - * require – due to the link to its outer class – always the serialization of the outer - * class which will, however, fail. - * - * ==Implementation Note== - * This analysis is implemented using the traditional approach where each analysis - * analyzes the project's resources on its own and fully controls the process. - * - * @author Michael Eichberg - */ -class NonSerializableClassHasASerializableInnerClass[Source] - extends FindRealBugsAnalysis[Source] { - - override def description: String = - "Identifies (non-static) inner classes that are serializable, " + - "but where the outer class is not." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[ClassBasedReport[Source]] = { - - import project.classHierarchy.isSubtypeOf - - val Serializable = ClassType.Serializable - - // If it's unknown, it's neither possible nor necessary to collect subtypes - if (project.classHierarchy.isUnknown(Serializable)) { - return Iterable.empty - } - - for { - serializableType <- project.classHierarchy.allSubtypes(Serializable, false) - classFile <- project.classFile(serializableType) - if !project.isLibraryType(classFile) - (outerType, AccessFlagsMatcher.NOT_STATIC()) <- classFile.outerType - /* if we know nothing about the class, then we never generate a warning */ - if isSubtypeOf(outerType, Serializable).isNo - } yield { - ClassBasedReport( - project.source(outerType), - Severity.Error, - outerType, - "Has a serializable non-static inner class (" + serializableType.toJava + - "), but is not serializable itself" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/SwingMethodInvokedInSwingThread.scala b/TOOLS/bp/src/TODO/SwingMethodInvokedInSwingThread.scala deleted file mode 100644 index 9f8339c1e8..0000000000 --- a/TOOLS/bp/src/TODO/SwingMethodInvokedInSwingThread.scala +++ /dev/null @@ -1,80 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports calls to `show()`, `pack()` or `setVisible()` methods on - * `javax/swing/` objects. - * - * These methods should only be called from inside the Swing background thread [1], since - * they themselves can cause events to be delivered. If they were called from outside the - * Swing thread, there could be dead locks etc. - * - * The proper way to call these methods is to implement a helper `java.lang.Runnable` - * class that does it, and pass an instance of it to `java.awt.EventQueue.invokeLater()`. - * - * [1]: [[http://en.wikipedia.org/wiki/Event_dispatching_thread]] - * - * @author Ralf Mitschke - * @author Peter Spieler - */ -class SwingMethodInvokedInSwingThread[Source] extends FindRealBugsAnalysis[Source] { - - override def description: String = - "Reports calls to certain Swing methods made from outside of the Swing thread." - - /** - * Runs this analysis on the given project. Reports the method calling swing functions - * outside of swing thread. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[MethodBasedReport[Source]] = { - - // Look for INVOKEVIRTUAL calls to show/pack/setVisible() methods on javax/swing/ - // objects from inside public static main() or methods containing "benchmark" in - // their name. - for { - classFile <- project.allProjectClassFiles - method @ MethodWithBody(body) <- classFile.methods - if (method.isPublic && - method.isStatic && - method.name == "main") || - (classFile.thisType.fqn.toLowerCase.indexOf("benchmark") >= 0) - (idx, INVOKEVIRTUAL(targetType, name, desc)) <- body.associateWithIndex - if targetType.isClassType && - targetType.asClassType.fqn.startsWith("javax/swing/") - if ((name, desc) match { - case ("show" | "pack", MethodDescriptor.NoArgsAndReturnVoid) => true - case ( - "setVisible", - MethodDescriptor( - IndexedSeq(BooleanType), - VoidType - ) - ) => true - case _ => false - }) - } yield { - MethodBasedReport( - project.source(classFile.thisType), - Severity.Error, - classFile.thisType, - method.descriptor, - method.name, - "Calls Swing methods while outside Swing thread" - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/SyncSetUnsyncGet.scala b/TOOLS/bp/src/TODO/SyncSetUnsyncGet.scala deleted file mode 100644 index 47f86535cd..0000000000 --- a/TOOLS/bp/src/TODO/SyncSetUnsyncGet.scala +++ /dev/null @@ -1,89 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* - -/** - * This analysis reports setter/getter pairs where the set method is synchronized and the - * get method is not synchronized. - * - * This indicates a bug because in a multi-threaded environment, the JVM may cache a - * field's value instead of reading it from memory everytime the getter is called. This - * means the getter may return a cached value which may differ from the value in memory. - * This must be prevented by using a synchronized getter, which guarantees to return the - * proper value. - * - * @author Michael Eichberg - * @author Daniel Klauer - */ -object SyncSetUnsyncGet { - - override def description: String = - "Reports getters that are unsynchronized while the setter is synchronized." - - /** - * Runs this analysis on the given project. Reports unsynced getter methods. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def apply( - project: SomeProject, - parameters: Seq[String] = List.empty, - isInterrupted: () => Boolean - ): Iterable[MethodBasedReport[Source]] = { - - // Look through non-static methods of all classes, collecting lists of - // unsynchronized getters and synchronized setters. - var unSyncedGetters = Map[String, Method]() - var syncedSetters = Map[String, (ClassFile, Method)]() - for { - classFile <- project.allProjectClassFiles - if !classFile.isInterfaceDeclaration - method <- classFile.methods - if !method.isAbstract - if !method.isStatic - if !method.isNative - if !method.isPrivate - } { - if (method.name.startsWith("get") && - !method.isSynchronized && - method.parameterTypes.length == 0 && - method.returnType != VoidType - ) { - unSyncedGetters += (( - classFile.thisType.fqn + "." + method.name.substring(3), - method - )) - } else if (method.name.startsWith("set") && - method.isSynchronized && - method.parameterTypes.length == 1 && - method.returnType == VoidType - ) { - syncedSetters += (( - classFile.thisType.fqn + "." + method.name.substring(3), - (classFile, method) - )) - } - } - - // Report only cases where both setter/getter for the same field were found. - // setters/getters that do not belong together are ignored. - for (field <- syncedSetters.keySet.intersect(unSyncedGetters.keySet)) yield { - val classFile = syncedSetters(field)._1 - val syncSet = syncedSetters(field)._2 - val unsyncGet = unSyncedGetters(field) - MethodBasedReport( - project.source(classFile.thisType), - Severity.Warning, - classFile.thisType, - unsyncGet, - "Is not synchronized like " + syncSet.name - ) - } - } -} diff --git a/TOOLS/bp/src/TODO/UrUninitReadCalledFromSuperConstructor.scala b/TOOLS/bp/src/TODO/UrUninitReadCalledFromSuperConstructor.scala deleted file mode 100644 index 79b325c7ec..0000000000 --- a/TOOLS/bp/src/TODO/UrUninitReadCalledFromSuperConstructor.scala +++ /dev/null @@ -1,216 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package frb -package analyses - -import br.* -import br.analyses.* -import br.instructions.* - -/** - * This analysis reports methods which access their class' fields and are called by - * their superclass' constructor. - * - * This is a bug, because while the super constructor is running, the derived class' - * constructor hasn't run yet, and the derived class' fields aren't initialized yet. - * Thus it's not safe to access them, and it's not safe for the superclass' constructor - * to call a method in the subclass which does that. - * - * TODO: Ideas for improvement: - * - Should also check all methods called from such methods - * - Don't complain about accesses to Static Final fields from such methods, assuming - * such fields don't need initialization by a constructor (find out whether that's - * correct) - * - Don't complain about accesses to fields if they don't have a specific initializer, - * then the constructor wouldn't do anything anyways and it doesn't make a difference - * whether the field is being accessed earlier or not. - * - Don't complain if the field is written before being read (or written only and never - * read) in such methods. If it's written first, then there's no "uninitialized" access. - * - Test on real Java projects and check whether/how many false-positives are reported - * - Should ignore methods that don't rely on any uninitialized fields. - * - * We only need to check abstract super classes, but no super interfaces here, because - * this analysis checks for a super constructor containing code calling the overridden - * method. Interfaces, however, can't have constructors. - * - * @author Roberts Kolosovs - * @author Ralf Mitschke - * @author Daniel Klauer - */ -class UrUninitReadCalledFromSuperConstructor[Source] extends FindRealBugsAnalysis[Source] { - - override def description: String = - "Reports methods that access their class'es static fields and are called by a " + - "super class constructor." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def doAnalyze( - project: Project[Source], - parameters: Seq[String] = Seq.empty, - isInterrupted: () => Boolean - ): Iterable[SourceLocationBasedReport[Source]] = { - - import project.classHierarchy - - /* - * Returns true if classFile declares the given Field - * - * @param classFile The ClassFile that is supposed to declare a given field - * @param name The name of the field supposedly declared. - * @param fieldType Type of the field supposedly declared. - */ - def declaresField( - classFile: ClassFile, - name: String, - fieldType: FieldType - ): Boolean = { - classFile.fields.exists { - case Field(_, `name`, `fieldType`) => true - case _ => false - } - } - - /* - * Check whether a method overrides a method in any super class. - * - * @param classFile Subclass with the supposed overriding method. - * @param method Method to be checked for being an overriding method. - * @return True if method in classFile is overriding a method in some superclass. - */ - def methodOverridesAnything(classFile: ClassFile, method: Method): Boolean = { - classHierarchy.allSupertypes(classFile.thisType). - filter(!classHierarchy.isInterface(_)). - exists( - classHierarchy.lookupMethodDefinition( - _, - method.name, - method.descriptor, - project - ).isDefined - ) - } - - /* - * Checks whether the source method contains calls to the given target method. - * - * @param source The method which may contain calls to other methods. - * @param targetType Type of the method supposedly called. - * @param target The name of the method supposedly called. - * @return True if source contains a call to target method of the given type. - */ - def calls(source: Method, targetType: Type, target: Method): Boolean = { - source.body.get.instructions.exists { - case MethodInvocationInstruction( - `targetType`, - target.name, - target.descriptor - ) => true - case _ => false - } - } - - var inconsistencyReports: Set[SourceLocationBasedReport[Source]] = Set.empty - - /* - * Looks up a method reference from an `INVOKESPECIAL` instruction by using - * `resolveMethodReference`, unless the given declaring class is an interface. - * - * @param classFile The class file containing the `INVOKESPECIAL` instruction. - * @param constructor The method containing the `INVOKESPECIAL` instruction. - * @param pc The `PC` of the `INVOKESPECIAL` instruction. - * @param declaringClass The class type referenced by the `INVOKESPECIAL`. - * @param name The method name referenced by the `INVOKESPECIAL`. - * @param descriptor The method signature referenced by the `INVOKESPECIAL`. - * @return The referenced `Method` or `None`. - */ - def maybeResolveMethodReference( - classFile: ClassFile, - constructor: Method, - pc: PC, - declaringClass: ClassType, - name: String, - descriptor: MethodDescriptor - ): Option[Method] = { - - // Excluding interfaces here, because resolveMethodReference() can't be called - // on interfaces, and normally, constructors are not being called on - // interfaces anyways. However, we've found a class file in the Qualitas - // Corpus containing an INVOKESPECIAL doing a constructor call on an - // interface. In this situation, we report that the project is inconsistent. - if (classHierarchy.isInterface(declaringClass)) { - inconsistencyReports += - LineAndColumnBasedReport( - project.source(classFile.thisType), - Severity.Error, - classFile.thisType, - constructor.descriptor, - constructor.name, - constructor.body.get.lineNumber(pc), - None, - "INVOKESPECIAL on interface type; inconsistent project." - ) - None - } else { - classHierarchy. - resolveMethodReference(declaringClass, name, descriptor, project) - } - } - - /* - * Returns the super class constructor called by the given constructor, or None. - * - * @param constructor Constructor which may or may not call a superconstructor. - * @return The first superconstructor to be called or None. - */ - def findCalledSuperConstructor( - classFile: ClassFile, - constructor: Method - ): Option[Method] = { - constructor.body.get.associateWithIndex.collectFirst({ - case (pc, INVOKESPECIAL(typ, name, desc)) => maybeResolveMethodReference( - classFile, - constructor, - pc, - typ, - name, - desc - ) - }).flatten - } - - var reports: Set[SourceLocationBasedReport[Source]] = Set.empty - - for { - classFile <- project.allProjectClassFiles - method @ MethodWithBody(body) <- classFile.methods - if !method.isStatic && - !method.isConstructor && - methodOverridesAnything(classFile, method) - GETFIELD(declaringClass, fieldName, fieldType) <- body.instructions - constructor <- classFile.constructors - if declaresField(classFile, fieldName, fieldType) - superConstructor <- findCalledSuperConstructor(classFile, constructor) - superClass = project.classFile(superConstructor) - if superConstructor.body.isDefined && - calls(superConstructor, superClass.thisType, method) - } { - reports += - MethodBasedReport( - project.source(classFile.thisType), - Severity.Error, - classFile.thisType, - method, - "Called by super constructor (" + superClass.thisType.toJava + "), " + - "while the class' fields are still uninitialized" - ) - } - - inconsistencyReports ++ reports - } -} diff --git a/TOOLS/bp/src/main/resources/application.conf b/TOOLS/bp/src/main/resources/application.conf deleted file mode 100644 index b54dad96fc..0000000000 --- a/TOOLS/bp/src/main/resources/application.conf +++ /dev/null @@ -1,34 +0,0 @@ -# Configuration for the BugPicker tool - -org.opalj { - - bugpicker.analysisParameter { - maxEvalTime = 10000 // default = 10000 - maxEvalFactor = 1.75d // default = 1.75d - maxCardinalityOfIntegerRanges = 16 // default = 16 - maxCardinalityOfLongSets = 2 // default = 2 - fpcfAnalyses = [ - "FieldAssignabilityAnalysis", - "MethodAccessibilityAnalysis", - "InstantiabilityAnalysis", - "CallableFromClassesInOtherPackagesAnalysis", - "PurityAnalysis" - ] - } - - bugpicker.analysis { - RootBugPickerAnalysisDomain { - maxCallChainLength = 1 // default = 1 - } - - FallbackBugPickerAnalysisDomain { - maxCardinalityOfIntegerRanges = 8 - maxCardinalityOfLongSets = 3 - } - } - - callgraph { - # specify additional entry points (e.g. called in native code, via reflection or by an framework) - entryPoints = [] - } -} diff --git a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.css b/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.css deleted file mode 100644 index a0e3f2080d..0000000000 --- a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.css +++ /dev/null @@ -1,117 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -body{ - margin:0px; - font-family: sans-serif; - font-size: 14px; -} - -h1{ - font-size:1.3em; -} - -h2,h3,h4,h5,h6{ - font-size:1.2em; -} - -details{ - padding:1em; -} - -summary{ - padding:0.5em; - background-color: rgb(128, 181, 235); - color:white; -} - -abbr { - border-bottom: 1px dotted black; -} - -.method_name { - color: rgb(19, 5, 248); - font-style: italic; -} - -.type { - color: rgb(11, 117, 11); -} - -.class_type{ - text-decoration: underline; -} - -.base_type { - font-style: italic; -} - -dl{ - margin: 0; -} -dt{ - font-weight: 300; - line-height: 1.0em; -} -dd{ - display:block; - margin-top: -1em; - margin-left: 6em; - margin-bottom: 0.3em; -} - -a.onclick{ - background-color: rgb(19, 91, 204); - padding: 0.3em; - line-height: 1em; - border: 1px solid; - border-radius: 3px; - margin: 0.3em; - width: 1em; - height: 1em; - text-align: center; - display: inline-block; -} - -a.onclick:hover{ - color: yellow; -} - -span.operator{ - font-weight: bolder; -} - -span.value{ - color: rgb(215, 145, 4); -} - -span.keyword{ - font-style: italic; -} - -table{ - white-space: inherit; - line-height: inherit; - font-weight: inherit; - font-size: inherit; - font-variant: inherit; - font-style: inherit; - border: 0; - margin: 0; - padding: 0; -} - -th{ - font-weight: bolder; - text-align: left; - word-wrap: break-word; -} - -td{ - word-break:break-all; - word-wrap: break-word; - vertical-align:top; -} - -.warning{ - color: rgb(242, 112, 46); - font-size: smaller; -} \ No newline at end of file diff --git a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.js b/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.js deleted file mode 100644 index 468f63b728..0000000000 --- a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/html.js +++ /dev/null @@ -1,2 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -NodeList.prototype.forEach = Array.prototype.forEach; diff --git a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.css b/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.css deleted file mode 100644 index b182c92dda..0000000000 --- a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.css +++ /dev/null @@ -1,123 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -/* details fallback */ -details { - display: block; -} - -.noDetails summary { - display: inherit; -} - -.noDetails details:not ([open] ) >*:not (:first-child ) { - display: none; -} - -/*VIEW SPECIFIC*/ -div#analysis_controls { - position: fixed; - top: 0px; - padding: 1em; - height: 0.9em; - margin: 0px; - width: 100%; - overflow: hidden; - background-color: rgba(8, 114, 215, 0.95); - color: white; -} - -div#analysis_controls div { - margin-bottom: .3em; -} - -div#analysis_controls div.issue_filter { - border: 1px white dotted; - margin-right: 2em; -} - -div#analysis_controls:hover { - height: initial; -} - -div#analysis_controls span#search_box { - position: absolute; - right: 50px; - top: 0px; - margin: 10px 20px; -} - -input#relevance { - transform: translate(0px, 6px); - -webkit-transform: translate(0px, 6px); - -moz-transform: translate(0px, 6px); -} - -div#analysis_parameters { - padding: 0em; - margin-top: 3em; -} - -div#analysis_results { - padding: 0em; -} - -dt.analysis { - color: rgb(78, 78, 78); -} -dt.analysis + dd { - color: rgb(78, 78, 78); -} - -.an_issue { - padding: 0.5em; - background-color: rgb(241, 244, 255); - border: 1px solid rgb(224, 222, 235); - border-top: 0px; - display: none; - word-break: break-word; -} - -div.an_issue.issue_visible { - display: block; -} - -.issue { - margin-top: 1em; -} - -.issue_message { - color: rgb(94, 94, 94); - font-weight: 300; -} - -div.issue_additional_info { - border-top: 1px dashed rgb(200, 200, 200); - margin-top: 0.3em; - padding-top: 0.3em; - font-weight: 300; -} - -div.declaring_class { - margin-left: 8em; -} - -div.declaring_class:before { - content: "class:"; -} - -details.locals { - padding: 0; - background-color: rgba(174, 177, 255, 0.24); - border: 1px solid rgb(172, 172, 205); -} - -details#analysis_parameters_summary summary { - background-color: rgb(223, 151, 75); -} - -details#analysis_parameters_summary ul { - background-color: rgb(247, 224, 197); - padding-top: 0.3em; - padding-bottom: 0.3em; - margin: 0; -} \ No newline at end of file diff --git a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.js b/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.js deleted file mode 100644 index e996b8bd14..0000000000 --- a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/report.js +++ /dev/null @@ -1,399 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -"use strict"; - -/* options for JSHint code quality: */ -/* global performance */ -if (typeof String.prototype.startsWith != 'function') { - String.prototype.startsWith = function(str) { - return this.indexOf(str) === 0; - }; -} - -function toggleDetailsOpen(event) { - var details = event.target.parentNode; - if (details.hasAttribute("open")) { - details.removeAttribute("open"); - } else { - details.setAttribute("open", ""); - } -} - -document.addEventListener("DOMContentLoaded", function(e) { - if (!('open' in document.createElement("details"))) { - e.target.documentElement.classList.add("noDetails"); - var parameters = document - .querySelector("details#analysis_parameters_summary"); - parameters.setAttribute("open", ""); - var summarys = document.querySelectorAll("details summary"); - summarys.forEach(function(e) { - e.addEventListener("click", toggleDetailsOpen); - }); - } -}, false); - -var debug_OFF = 0, debug_ERROR = -10, debug_WARNING = -20, debug_INFO = -30, debug_TRACE = -40, debug_ALL = -2147483648; -var debug = debug_OFF; - -function log(something, loglevel) { - if (loglevel === undefined) { - loglevel = debug_INFO; - } - if (debug > loglevel) - return; -// comment in for WebView Debug messages. (Also add the div in BugPickerAnalysis to the HTML) -// document.getElementById('debug_info').innerHTML = document -// .getElementById('debug_info').innerHTML -// + "
" + something; - console.log(something); -} - -/** - * Manages the active filters for the displayed issues. - * - * @namespace IssueFilter - * @author Tobias Becker - */ -var IssueFilter = function() { - /** - * The node that displays how many issues are currently displayed. - * - * @memberof IssueFilter - */ - var issuesDisplayNode; - - /** - * All issues paired with their containing package. - * - * @memberof IssueFilter - */ - var packagesWithIssues = []; - - /** - * The filter functions. - * - * @memberof IssueFilter - */ - var filterFuns = []; - - /** - * The initialization functions of the filter. Will be called once, when - * DOMContentLoaded-Event is fired - * - * @memberof IssueFilter - */ - var initFuns = []; - - /** - * Indicates if the filters are already initialized. - * - * @memberof IssueFilter - */ - var init = false; - var updating = false; - - function initialize() { - log("[IssueFilter] Initialization started."); - log(initFuns); - initFuns.forEach(function(f) { - log("START: " + f); - f(); - log("END: " + f); - }); - log("[IssueFilter] InitFuns executed."); - issuesDisplayNode = document.querySelector("#issues_displayed"); - var packages = document.querySelector("#analysis_results") - .querySelectorAll("details.package_summary"); - packages.forEach(function(p) { - packagesWithIssues.push([ p, p.querySelectorAll(".an_issue") ]); - }); - init = true; - log("[IssueFilter] All Filter initialized."); - openAllPackages(); - IssueFilter.update(); - } - - document.addEventListener("DOMContentLoaded", initialize, false); - - var object = { - - /** - * Registers a new Filter. - * - * @param {Function} - * Initialization function. Will be called when the - * DOMContentLoaded-Event is fired or instantly if it already - * fired. - * @param {Function} - * The filter function. Will be passed a single issue and - * should return a boolean indicating if the issue should be - * displayed (true) or not (false) - * - * @memberof IssueFilter - * @inner - */ - register : function(initFun, displayIssue) { - if (!(initFun instanceof Function)) { - log("[IssueFilter] register: Invalid Parameter 'initFun' " - + initFun, debug_ERROR); - return; - } - if (!(displayIssue instanceof Function)) { - log("[IssueFilter] register: Invalid Parameter 'displayIssue '" - + displayIssue, debug_ERROR); - return; - } - filterFuns.push(displayIssue); - if (init) - initFun(); - else - initFuns.push(initFun); - }, - - /** - * Updates the displayed issues by applying all filters. If an issue is - * considered not to be displayed by a filter, it will not be passed to - * the remaining filters. - * - * @memberof IssueFilter - * @inner - */ - update : function() { - if (!init) { - log( - "[IssueFilter] Update cancelled. IssueFilter not yet initialzed!", - debug_WARNING); - return; - } - if (updating) { - log("[IssueFilter] Update cancelled. Already updating!", - debug_WARNING); - return; - } - updating = true; - log("[IssueFilter] Update started."); - var startTime = performance.now(); - var issue_counter_all = 0; - log("[IssueFilter] Number of filter functions: " - + filterFuns.length); - packagesWithIssues - .forEach(function(packageIssue, pIndex) { - var thePackage = packageIssue[0]; - var issues = packageIssue[1]; - var issue_counter_package = 0; - issues.forEach(function(issue, index) { - log("[IssueFilter] Processing issue " + (index + 1) - + "/" + issues.length + " in package " - + (pIndex + 1) + "/" - + packagesWithIssues.length, debug_TRACE); - var display = true; - var i = 0; - while (display && i < filterFuns.length) { - log("[IssueFilter] Starting filter #" + i, - debug_TRACE); - display = filterFuns[i](issue); - if (typeof display !== "boolean") { - log("[IssueFilter] Filter #" + i - + " returned non boolean", - debug_TRACE); - } - log("[IssueFilter] Finished filter #" + i, - debug_TRACE); - i++; - } - - if (display) { - issue.classList.add("issue_visible"); - issue_counter_package++; - } else { - issue.classList.remove("issue_visible"); - } - }); - if (issue_counter_package > 0) { - thePackage.style.display = "block"; - } else { - thePackage.style.display = "none"; - } - issue_counter_all += issue_counter_package; - // update number of displayed issues in package summary: - var text = thePackage - .querySelector("summary.package_summary"); - var textNode = text - .querySelector("span.package_issues"); - if (!textNode) { - log("[IssueFilter] Creating package-textNode", - debug_TRACE); - text.innerHTML = text.innerHTML - + " "; - textNode = text - .querySelector("span.package_issues"); - } - textNode.innerHTML = " (Issues: " - + issue_counter_package + ")"; - }); - issuesDisplayNode.innerHTML = " [Relevance ≥ " - + inputRelevance.value + "] " + issue_counter_all; - var endTime = performance.now(); - log("[IssueFilter] Update ended. Took " + (endTime - startTime) - + " milliseconds."); - log("[IssueFilter] Applied " + filterFuns.length + " Filter"); - updating = false; - }, - - /** - * Convenience function to add the IssueFilter.update as an - * EventListener. - * - * @memberof IssueFilter - * @inner - */ - addListener : function(listenTarget, listenType) { - if (!init) { - log( - "[IssueFilter] addListener called. IssueFilter not yet initialized.", - debug_INFO); - } - if (!(listenTarget instanceof HTMLElement)) { - log( - "[IssueFilter] addListener: Invalid Parameter 'listenTarget' " - + listenTarget, debug_ERROR); - return; - } - if (typeof listenType !== "string") { - log( - "[IssueFilter] addListener: Invalid Parameter 'listenType' " - + listenType, debug_ERROR); - return; - } - listenTarget.addEventListener(listenType, this.update, false); - } - }; - return object; -}(); - -// Filter: relevance -// -var inputRelevance; -IssueFilter.register(function() { - inputRelevance = document.querySelector("input#relevance"); - inputRelevance.value = 75; - IssueFilter.addListener(inputRelevance, "change"); - log("[RelevanceFilter] Initialized."); -}, function(issue) { - return (issue.dataset.relevance >= inputRelevance.valueAsNumber); -}); - -/** - * Function which removes duplicates from an array. - * - * @param inputArray, which possibly includes duplicate values. - * @returns {Array}, an array with unique values. - */ -function removeDuplicates(inputArray) { - var seen = {}; - var out = []; - var len = inputArray.length; - var j = 0; - for (var i = 0; i < len; i++) { - var item = inputArray[i]; - if (seen[item] !== 1) { - seen[item] = 1; - out[j++] = item; - } - } - return out; -} - -// Filter: data-kind & data-category -// -function initDataFilter(dataType) { - var allValues = []; - - document.querySelectorAll('[data-' + dataType + ']').forEach( - function(entry) { - allValues = removeDuplicates(allValues.concat(entry.getAttribute("data-" + dataType) - .split(' '))); - }); - - document.querySelector("#filter_data-" + dataType).innerHTML = arrayJoin( - allValues.sort(), function(i, e) { - var name = "filter-data-" + dataType; - var id = name + i; - return "" + ""; - }); - document.querySelectorAll("input[name=filter-data-" + dataType + "]") - .forEach(function(input) { - IssueFilter.addListener(input, "change"); - }); -} - -function commonValue(a, b) { - var t; - if (b.length > a.length) { - t = b; - b = a; - a = t; - } - return a.filter(function(e) { - return (b.indexOf(e) !== -1); - }).length > 0; -} - -var inputDataKind; -IssueFilter.register(function() { - initDataFilter("kind"); - inputDataKind = document.querySelectorAll("input[name=filter-data-kind]"); - log("[DataKindFilter] Initialized."); -}, function(issue) { - var checked = []; - inputDataKind.forEach(function(input) { - if (input.checked) - checked.push(input.value); - }); - var actual = issue.getAttribute("data-kind").split(" "); - return commonValue(actual, checked); -}); - -var inputDataCategory; -IssueFilter.register(function() { - initDataFilter("category"); - inputDataCategory = document - .querySelectorAll("input[name=filter-data-category]"); - log("[DataCategoryFilter] Initialized."); -}, function(issue) { - var checked = []; - inputDataCategory.forEach(function(input) { - if (input.checked) - checked.push(input.value); - }); - var actual = issue.getAttribute("data-category").split(" "); - return commonValue(actual, checked); -}); - -function openAllPackages() { - document.querySelectorAll('div#analysis_results > details').forEach( - function(e) { - e.setAttribute('open', ''); - }); -} - -function closeAllPackages() { - document.querySelectorAll('div#analysis_results > details').forEach( - function(e) { - e.removeAttribute('open'); - }); -} - -/* - * Works similar to the join-method of Array, but uses a function for the join - */ -function arrayJoin(array, joinFunc) { - var arrayJoinIntern = function(internArray, index) { - var element = internArray.shift(); - return internArray.length > 0 ? joinFunc(index, element) - + arrayJoinIntern(internArray, index + 1) : joinFunc(index, - element); - }; - return arrayJoinIntern(array, 0); -} \ No newline at end of file diff --git a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/search.js b/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/search.js deleted file mode 100644 index 665f900404..0000000000 --- a/TOOLS/bp/src/main/resources/org/opalj/bugpicker/core/search.js +++ /dev/null @@ -1,92 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -"use strict"; - -/* options for JSHint code quality: */ -/* global performance */ - -// quotes RegExp special character in a String -RegExp.quote = function (str) { - return (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); -}; - -// Filter: text search -function findTextInIssue(issue, text, category) { - - var erg = false; - var rx = new RegExp(RegExp.quote(text), "gi"); - var processDD = function (dd) { - var attributes = dd.attributes; - var i = 0; - while (i < attributes.length) { - var attr = attributes[i]; - if (attr.name.startsWith("data-")) { - var attrText = attr.value.toLowerCase().replace(/\//g, "."); - if (attrText.indexOf(text.toLowerCase()) >= 0) { - erg = true; - } - } - i++; - } - var nodeIterator = document.createNodeIterator(dd, NodeFilter.SHOW_TEXT); - var currentNode; - while (currentNode = nodeIterator.nextNode()) { - if (currentNode.textContent.toLowerCase().indexOf(text.toLowerCase()) >= 0) { - erg = true; - } - } - }; - if (category === undefined) { - issue.querySelectorAll("dd:not(.issue_message)").forEach(processDD); - } else { - processDD(category); - } - return erg; -} - -var searchField; -var searchCategories = []; -IssueFilter.register( - function () { - searchField = document.querySelector("#search_field"); - // delay the event-listener - searchField.addEventListener("input", function () { - var searchString = searchField.value; - setTimeout(function () { - if (searchString == searchField.value) - IssueFilter.update(); - }, 300); - }, false); - document.querySelectorAll("dt").forEach(function (dt) { - if (searchCategories.indexOf(dt.innerText.replace(/\W/g, '')) < 0) - searchCategories.push(dt.innerText.replace(/\W/g, '')); - }); - searchField.disabled = false; - log("[TextSearchFilter] Initialized."); - }, - function (issue) { - var searchString = searchField.value; - if (searchString.length === 0) - return true; - var categoryLength = searchString.indexOf(":"); - var category = searchString.substring(0, categoryLength); - if (searchCategories.indexOf(category) !== -1) { - searchString = searchString.slice(categoryLength + 1); - } else { - category = ""; - } - var found = false; - if (category !== "") { - var elem; - issue.querySelectorAll("dt").forEach(function (dt) { - if (dt.innerText.replace(/\W/g, '') == category) { - elem = dt.nextSibling; - while (elem.nodeName != "DD") - elem = elem.nextSibling; - } - }); - found = findTextInIssue(issue, searchString, elem); - } else { - found = findTextInIssue(issue, searchString); - } - return found; - }); \ No newline at end of file diff --git a/TOOLS/bp/src/main/resources/reference.conf b/TOOLS/bp/src/main/resources/reference.conf deleted file mode 100644 index 1ed95b4375..0000000000 --- a/TOOLS/bp/src/main/resources/reference.conf +++ /dev/null @@ -1,3 +0,0 @@ -# Specifies the regexp that the packages for which issues should be reported has to be matched. -# If you use the regexp .* all issues will be reported. -org.opalj.bugpicker.issues.packages=".*" \ No newline at end of file diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/Console.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/Console.scala deleted file mode 100644 index e879dab1cd..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/Console.scala +++ /dev/null @@ -1,330 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core - -import java.io.File -import java.lang.Integer.parseInt -import java.net.URL -import java.nio.charset.StandardCharsets -import java.nio.file.Files -import scala.xml.Node - -import com.typesafe.config.Config - -import org.opalj.ai.util.XHTML -import org.opalj.br.analyses.Analysis -import org.opalj.br.analyses.AnalysisApplication -import org.opalj.br.analyses.BasicReport -import org.opalj.br.analyses.ProgressManagement -import org.opalj.br.analyses.Project -import org.opalj.bugpicker.core.analyses.BugPickerAnalysis -import org.opalj.bugpicker.core.analyses.BugPickerAnalysis.resultsAsXHTML -import org.opalj.io.process -import org.opalj.io.writeAndOpen -import org.opalj.issues.IssueKind -import org.opalj.log.GlobalLogContext -import org.opalj.log.LogContext -import org.opalj.log.OPALLogger - -/** - * The command line interface of the bug picker. - * - * @author Michael Eichberg - */ -object Console extends Analysis[URL, BasicReport] with AnalysisApplication { - - val analysis = this - - final val IDLFileOutputNameMatcher = """-idl=([\w-_\.\:/\\]+)""".r - - final val HTMLFileOutputNameMatcher = """-html=([\w-_\.\:/\\]+)""".r - - final val DebugFileOutputNameMatcher = """-debug=([\w-_\.\:/\\]+)""".r - - final val MinRelevancePattern = """-minRelevance=(\d\d?)""".r - final val MinRelevance = 0 - - final val IssueKindsPattern = """-kinds=([\w_,]+)""".r - - override def main(unparsedArgs: Array[String]): Unit = { - try { - super.main(unparsedArgs) - } catch { - case t: Throwable => t.printStackTrace() - } - } - - override final val analysisSpecificParametersDescription: String = - """[-maxEvalFactor= determines the maximum effort that - | the analysis will spend when analyzing a specific method. The effort is - | always relative to the size of the method. For the vast majority of methods - | a value between 0.5 and 1.5 is sufficient to completely analyze a single - | method using the default settings. - | A value greater than 1.5 can already lead to very long evaluation times. - | If the threshold is exceeded the analysis of the method is aborted and no - | result can be drawn.] - |[-maxEvalTime= determines the time (in ms) that the analysis - | is allowed to take for one method before the analysis is terminated.] - |[-maxCardinalityOfIntegerRanges= basically determines for each integer - | value how long the value is "precisely" tracked. Internally the analysis - | computes the range of values that an integer value may have at runtime. The - | maximum size/cardinality of this range is controlled by this setting. If - | the range is exceeded the precise tracking of the respective value is - | terminated. - | Increasing this value may significantly increase the analysis time and - | may require the increase of maxEvalFactor.] - |[-maxCardinalityOfLongSets= basically determines for each long - | value how long the value is "precisely" tracked. - | The maximum size/cardinality of this set is controlled by this setting. If - | the set's size is tool large the precise tracking of the respective value is - | terminated. - | Increasing this value may significantly increase the analysis time and - | may require the increase of maxEvalFactor.] | - |[-maxCallChainLength= determines the maximum length of the call chain - | that is analyzed. - | If you increase this value by one, it is typically also necessary - | to increase the maxEvalFactor by a factor of 2 to 3. Otherwise it - | may happen that many analyses are aborted because the evaluation time - | is exhausted and – overall – the analysis reports less issues!] - |[-minRelevance= the minimum relevance of the shown issues.] - |[-kinds= a comma seperated list of issue kinds - | that should be reported.] - |[-eclipse creates an eclipse console compatible output.] - |[-idl creates an idl report.] - |[-html[=] generates an HTML report which is written to the optionally - | specified location.] - |[-debug[=] turns on the debug mode (more information are logged and - | internal, recoverable exceptions are logged) the report is optionally - | written to the specified location.]""".stripMargin('|') - - private final val bugPickerAnalysis = new BugPickerAnalysis - - override def title: String = bugPickerAnalysis.title - - override def description: String = bugPickerAnalysis.description - - private var cpFiles: Iterable[File] = null - private var libcpFiles: Iterable[File] = null - - override def setupProject( - cpFiles: Iterable[File], - libcpFiles: Iterable[File], - completelyLoadLibraries: Boolean, - analysisMode: AnalysisMode, - fallbackConfiguration: Config - )( - implicit initialLogContext: LogContext - ): Project[URL] = { - this.cpFiles = cpFiles - this.libcpFiles = libcpFiles - super.setupProject( - cpFiles, - libcpFiles, - completelyLoadLibraries, - analysisMode, - fallbackConfiguration - ) - } - - override def analyze( - theProject: Project[URL], - parameters: Seq[String], - initProgressManagement: (Int) => ProgressManagement - ): BasicReport = { - - import theProject.logContext - - OPALLogger.info("analysis progress", "starting analysis") - - val (analysisTime, issues0, exceptions) = - bugPickerAnalysis.analyze(theProject, parameters, initProgressManagement) - - // - // PREPARE THE GENERATION OF THE REPORT OF THE FOUND ISSUES - // (HTML/Eclipse) - // - - // Filter the report - val minRelevance: Int = - parameters. - collectFirst { case MinRelevancePattern(i) => parseInt(i) }. - getOrElse(MinRelevance) - val issues1 = issues0.filter { i => i.relevance.value >= minRelevance } - - val issues = parameters.collectFirst { case IssueKindsPattern(ks) => ks } match { - case Some(ks) => - val relevantKinds = ks.split(',').map(_.replace('_', ' ')).toSet - issues1.filter(issue => (issue.kinds intersect (relevantKinds)).nonEmpty) - case None => - issues1 - } - - // Generate the report well suited for the eclipse console - // - if (parameters.contains("-eclipse")) { - val formattedIssues = issues.map { issue => issue.toEclipseConsoleString } - println(formattedIssues.toSeq.sorted.mkString("\n")) - } - - // Generate a report using the bug description language - // - if (parameters.contains("-idl")) { - val formattedIssues = issues.map { issue => issue.toIDL.toString } - println(s"Analysis of " + cpFiles.mkString(", ")) - println("Parameters") - println(parameters.mkString("\n")) - println("Issues") - val idlReport = "[" + formattedIssues.toSeq.mkString(",\n") + "]" - println(idlReport) - - writeAndOpen(idlReport, "BugPickerAnalysisResults", ".json") - } - - // Generate the HTML report - // - - lazy val htmlReport = resultsAsXHTML(parameters, issues, showSearch = false, analysisTime).toString - parameters.collectFirst { case HTMLFileOutputNameMatcher(name) => name } match { - case Some(fileName) => - val file = new File(fileName).toPath - process { Files.newBufferedWriter(file, StandardCharsets.UTF_8) } { fos => - fos.write(htmlReport, 0, htmlReport.length) - } - case _ => // Nothing to do - } - if (parameters.contains("-html")) { - writeAndOpen(htmlReport, "BugPickerAnalysisResults", ".html") - } - - // - // PREPARE THE GENERATION OF THE REPORT OF THE OCCURED EXCEPTIONS - // - if (exceptions.nonEmpty) { - OPALLogger.error( - "internal error", - s"the analysis threw ${exceptions.size} exceptions" - ) - exceptions.foreach { e => - OPALLogger.error( - "internal error", - "the analysis failed", - e - ) - } - - var exceptionsReport: Node = null - def getExceptionsReport = { - if (exceptionsReport eq null) { - val exceptionNodes = - exceptions.take(10).map { e =>

{XHTML.throwableToXHTML(e)}

} - exceptionsReport = - XHTML.createXHTML( - Some(s"${exceptions.size}/${exceptionNodes.size} Thrown Exceptions"), -
{exceptionNodes}
- ) - } - exceptionsReport - } - parameters.collectFirst { case DebugFileOutputNameMatcher(name) => name } match { - case Some(fileName) => - process { new java.io.FileOutputStream(fileName) } { fos => - fos.write(getExceptionsReport.toString.getBytes("UTF-8")) - } - case _ => // Nothing to do - } - if (parameters.contains("-debug")) { - org.opalj.io.writeAndOpen(getExceptionsReport, "Exceptions", ".html") - } - } - - // - // Print some statistics and "return" - // - val groupedIssues = - issues.groupBy(_.relevance).toList. - sortWith((e1, e2) => e1._1.value < e2._1.value) - val groupedAndCountedIssues = groupedIssues.map(e => e._1 + ": " + e._2.size) - - BasicReport( - groupedAndCountedIssues.mkString( - s"Issues (∑${issues.size}):\n\t", - "\n\t", - s"\nIdentified in: ${analysisTime.toSeconds}.\n" - ) - ) - } - - override def checkAnalysisSpecificParameters(parameters: Seq[String]): Seq[String] = { - - OPALLogger.info("analysis progress", "checking parameters")(GlobalLogContext) - - var outputFormatGiven = false - - import org.opalj.bugpicker.core.analyses.BugPickerAnalysis.* - - val issues = - parameters.filterNot(parameter => - parameter match { - case MaxEvalFactorPattern(d) => - try { - val factor = java.lang.Double.parseDouble(d).toDouble - (factor >= 0.1d && factor < 100.0d) || - factor == Double.PositiveInfinity - } catch { - case _: NumberFormatException => false - } - case MaxEvalTimePattern(l) => - try { - val maxTime = java.lang.Long.parseLong(l).toLong - maxTime >= 10L && maxTime <= 1000000L - } catch { - case _: NumberFormatException => false - } - case MaxCardinalityOfIntegerRangesPattern(i) => - try { - val cardinality = java.lang.Long.parseLong(i).toLong - cardinality >= 1L && cardinality <= 4294967295L - } catch { - case _: NumberFormatException => false - } - case MaxCardinalityOfLongSetsPattern(i) => - try { - val cardinality = java.lang.Integer.parseInt(i).toInt - cardinality >= 1 && cardinality <= 1024 - } catch { - case _: NumberFormatException => false - } - case MaxCallChainLengthPattern(_) => - // the pattern ensures that the value is legal... - true - - case IssueKindsPattern(ks) => - val kinds = ks.split(',').map(_.replace('_', ' ')) - kinds.nonEmpty && kinds.forall { IssueKind.AllKinds.contains(_) } - - case MinRelevancePattern(_) => - // the pattern ensures that the value is legal... - true - - case HTMLFileOutputNameMatcher(_) => - outputFormatGiven = true; true - case "-html" => - outputFormatGiven = true; true - case "-eclipse" => - outputFormatGiven = true; true - case "-idl" => - outputFormatGiven = true; true - case "-debug" => true - case DebugFileOutputNameMatcher(_) => true - case _ => false - } - ) - - if (!outputFormatGiven) - OPALLogger.warn("analysis configuration", "no output format specified")(GlobalLogContext) - - issues.map("unknown or illegal parameter: " + _) - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnalysisParameters.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnalysisParameters.scala deleted file mode 100644 index 872ea0a4ce..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnalysisParameters.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.bugpicker.core.analyses.BugPickerAnalysis.* -import org.opalj.util.Milliseconds - -case class AnalysisParameters( - maxEvalTime: Milliseconds = DefaultMaxEvalTime, - maxEvalFactor: Double = DefaultMaxEvalFactor, - maxCardinalityOfIntegerRanges: Long = DefaultMaxCardinalityOfIntegerRanges, - maxCardinalityOfLongSets: Int = DefaultMaxCardinalityOfLongSets, - maxCallChainLength: Int = DefaultMaxCallChainLength, - fixpointAnalyses: Seq[String] = DefaultFixpointAnalyses -) { - - def toStringParameters: Seq[String] = Seq( - s"-maxEvalFactor=$maxEvalFactor", - s"-maxEvalTime=$maxEvalTime", - s"-maxCardinalityOfIntegerRanges=$maxCardinalityOfIntegerRanges", - s"-maxCardinalityOfLongSets=$maxCardinalityOfLongSets", - s"-maxCallChainLength=$maxCallChainLength", - s"-fixpointAnalyses=${fixpointAnalyses.mkString(";")}" - ) -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnonymousInnerClassShouldBeStatic.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnonymousInnerClassShouldBeStatic.scala deleted file mode 100644 index b9fa98c099..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/AnonymousInnerClassShouldBeStatic.scala +++ /dev/null @@ -1,187 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.br.* -import org.opalj.br.analyses.* -import org.opalj.br.instructions.* -import org.opalj.issues.ClassLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Relevance - -/** - * This analysis reports anonymous inner classes that do not use their reference to the - * parent class and as such could be made `static` in order to save some memory and - * to improve overall comprehension. - * - * Since anonymous inner classes cannot be declared `static`, they must be refactored to - * named inner classes first. - * - * @author Ralf Mitschke - * @author Daniel Klauer - * @author Peter Spieler - * @author Florian Brandherm - * @author Michael Eichberg - */ -object AnonymousInnerClassShouldBeStatic { - - def description: String = "Identifies anonymous inner classes that should be made static." - - private val withinAnonymousClass = "[$][0-9].*[$]".r - - /** - * A heuristic for determining whether an inner class is inside an anonymous inner - * class based on the class name. - * - * @param classFile The inner class to check. - * @return Whether the inner class is inside an anonymous inner class. - */ - private def isWithinAnonymousInnerClass(classFile: ClassFile): Boolean = { - withinAnonymousClass.findFirstIn(classFile.thisType.fqn).isDefined - } - - /** - * Finds the last occurrence of either '$' or '+' in a class name string. - * - * @param fqn The class name to check. - * @return The index of the last occurring '$' or '+', whichever is closer to the end. - */ - private def lastIndexOfInnerClassEncoding(fqn: String): Int = { - math.max(fqn.lastIndexOf('$'), fqn.lastIndexOf('+')) - } - - /** - * A heuristic for determining anonymous inner classes by the encoding in the name. - * - * @param classFile The class to check. - * @return Whether the class is an anonymous inner class. - */ - private def isAnonymousInnerClass(classFile: ClassFile): Boolean = { - val fqn = classFile.thisType.fqn - - val lastSpecialChar = lastIndexOfInnerClassEncoding(fqn) - if (lastSpecialChar < 0) { - return false - } - - val digitChar = lastSpecialChar + 1; - digitChar < fqn.length && Character.isDigit(fqn.charAt(digitChar)) - } - - /** - * A heuristic for determining whether the field points to the enclosing instance - * by checking if its name starts with "this". - * - * @param field The field to check. - * @return Whether the field is the inner class' reference to the parent object. - */ - private def isOuterThisField(field: Field): Boolean = { - field.name.startsWith("this$") || field.name.startsWith("this+") - } - - /** - * Checks whether a class has any methods which read the given field. - * - * Note: This assumes the class also declares this field, and that it's enough to - * check for accesses through the context of that class. In other words, accesses - * through the context of subclasses would not be detected, but that's not required - * when checking the outer class reference field of an anonymous inner class. - */ - private def hasMethodsReadingField(classFile: ClassFile, field: Field): Boolean = { - for (MethodWithBody(body) <- classFile.methods) { - if (body.instructions.exists { - case FieldReadAccess(classFile.thisType, field.name, field.fieldType) => true - case _ => false - } - ) { - return true; - } - } - false - } - - /** - * Checks whether a class has any constructors with multiple ALOAD_1 instructions. - */ - private def hasConstructorsWithMultipleALOAD_1s(classFile: ClassFile): Boolean = { - for (method <- classFile.constructors; body <- method.body) { - var count = 0 - body.instructions.foreach { - case ALOAD_1 => - count += 1; - if (count > 1) { - return true; - } - case _ => - } - } - false - } - - private def isOuterClassReferenceUsed(classFile: ClassFile): Answer = { - // Try to find the outer class reference field. - val outerClassReference = classFile.fields.find(isOuterThisField(_)) - if (outerClassReference.isEmpty) { - return Unknown - } - - // Any constructors with more than one access to their outer class reference - // parameter? It's always read at least once, to store the outer class reference - // into the outer class reference field. - if (hasConstructorsWithMultipleALOAD_1s(classFile)) { - return Yes - } - - // Any methods reading the outer class reference field? - if (hasMethodsReadingField(classFile, outerClassReference.get)) { - return Yes - } - - No - } - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def apply(project: SomeProject, classFile: ClassFile): Iterable[Issue] = { - if (project.isLibraryType(classFile) || classFile.isSynthetic) - return None; - - if (!(isAnonymousInnerClass(classFile) && - !isWithinAnonymousInnerClass(classFile) && - isOuterClassReferenceUsed(classFile).isNo) - ) - return None; - - var supertype = classFile.superclassType.get.toJava - - if (classFile.interfaceTypes.nonEmpty) { - val superInterfacetypes = classFile.interfaceTypes.map(_.toJava).mkString(" with ") - - if (classFile.superclassType.get == ClassType.Object) - supertype = superInterfacetypes - else - supertype += " implements " + superInterfacetypes - - } - - Some( - Issue( - "AnonymousInnerClassShouldBeStatic", - Relevance.Low, - s"this inner class of type $supertype should be made static", - Set(IssueCategory.Comprehensibility, IssueCategory.Performance), - Set(IssueKind.MissingStaticModifier), - List(new ClassLocation(None, project, classFile)) - ) - ) - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysis.scala deleted file mode 100644 index 5521065afa..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysis.scala +++ /dev/null @@ -1,605 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import java.net.URL -import java.util.Date -import java.util.concurrent.ConcurrentLinkedQueue -import java.util.concurrent.atomic.AtomicInteger -import scala.collection.JavaConverters.* -import scala.collection.JavaConverters.collectionAsScalaIterableConverter -import scala.xml.Node -import scala.xml.NodeSeq -import scala.xml.Unparsed - -import com.typesafe.config.Config -import com.typesafe.config.ConfigRenderOptions - -import org.opalj.ai.BoundedInterruptableAI -import org.opalj.ai.InterpretationFailedException -import org.opalj.ai.analyses.FieldValuesKey -import org.opalj.ai.analyses.MethodReturnValuesKey -import org.opalj.ai.analyses.cg.CallGraphCache -import org.opalj.ai.analyses.cg.VTACallGraphKey -import org.opalj.ai.util.XHTML -import org.opalj.br.ClassFile -import org.opalj.br.Code -import org.opalj.br.Method -import org.opalj.br.MethodSignature -import org.opalj.br.analyses.Analysis -import org.opalj.br.analyses.AnalysisException -import org.opalj.br.analyses.FieldAccessInformationKey -import org.opalj.br.analyses.ProgressManagement -import org.opalj.br.analyses.Project -import org.opalj.br.analyses.PropertyStoreKey -import org.opalj.br.analyses.StringConstantsInformationKey -import org.opalj.br.analyses.cg.InstantiableClassesKey -import org.opalj.fpcf.FPCFAnalysesManagerKey -import org.opalj.fpcf.FPCFAnalysesRegistry -import org.opalj.issues.Issue -import org.opalj.issues.IssueOrdering -import org.opalj.issues.PackageLocation -import org.opalj.issues.ProjectLocation -import org.opalj.issues.Relevance -import org.opalj.log.OPALLogger -import org.opalj.util.Milliseconds -import org.opalj.util.Nanoseconds -import org.opalj.util.PerformanceEvaluation.time - -import net.ceedubs.ficus.Ficus.* - -/** - * Wrapper around several analyses that analyze the control- and data-flow to identify - * various issues in the source code of projects. - * - * ==Precision== - * The analyses are designed such that they try to avoid to report false positives to facilitate - * usage of the BugPicker. However, given - * that we analyze Java bytecode, some findings may be the result of the compilation - * scheme employed by the compiler and, hence, cannot be resolved at the - * source code level. This is in particular true for finally blocks in Java programs. In - * this case compilers typically include the same block two (or more) times in the code. - * Furthermore, Java reflection and reflection-like mechanisms are also a source of - * false positives. - * - * @author Michael Eichberg - */ -class BugPickerAnalysis extends Analysis[URL, BugPickerResults] { - - import BugPickerAnalysis.* - - override def title: String = "BugPicker" - - override def description: String = "Finds code smells in Java (byte) code." - - /** - * Executes the analysis of the project's concrete methods. - * - * @param parameters A list of (optional) parameters. The parameters that are - * matched are defined by: - * [[BugPickerAnalysis.MaxEvalFactorPattern]], - * [[BugPickerAnalysis.MaxEvalTimePattern]], - * [[BugPickerAnalysis.MaxCardinalityOfIntegerRangesPattern]], - * [[BugPickerAnalysis.MaxCardinalityOfLongSetsPattern]], - * [[BugPickerAnalysis.MaxCallChainLengthPattern]], and "`-debug`". - */ - override def analyze( - theProject: Project[URL], - parameters: Seq[String], - initProgressManagement: (Int) => ProgressManagement - ): BugPickerResults = { - - import theProject.config - - implicit val project: Project[URL] = theProject - implicit val logContext: LogContext = theProject.logContext - - // related to managing the analysis progress - val classFilesCount = theProject.projectClassFilesCount - - val progressManagement = initProgressManagement(PreAnalysesCount + classFilesCount) - import progressManagement.step - - val analysisParameters = theProject.config.as[Config]("org.opalj.bugpicker.analysisParameter") - - val maxEvalFactor = analysisParameters.as[Double]("maxEvalFactor") - val maxEvalTime = new Milliseconds(analysisParameters.as[Long]("maxEvalTime")) - val maxCardinalityOfIntegerRanges = analysisParameters.as[Long]("maxCardinalityOfLongSets") - val maxCardinalityOfLongSets = analysisParameters.as[Int]("maxCardinalityOfLongSets") - val configuredAnalyses = analysisParameters.as[List[String]]("fpcfAnalyses") - val fpcfAnalyses = configuredAnalyses.map { a => FPCFAnalysesRegistry.factory(a) } - val maxCallChainLength = theProject.config.as[Int]( - "org.opalj.bugpicker.analysis.RootBugPickerAnalysisDomain.maxCallChainLength" - ) - - val debug = parameters.contains("-debug") - if (debug) { - val cp = System.getProperty("java.class.path") - val cpSorted = cp.split(java.io.File.pathSeparatorChar).sorted - val renderingOptions = - ConfigRenderOptions.defaults(). - setOriginComments(false). - setComments(true). - setJson(false) - val bugpickerConf = theProject.config.withOnlyPath("org.opalj") - val settings = bugpickerConf.root().render(renderingOptions) - OPALLogger.info( - "configuration", - cpSorted.mkString("System ClassPath:\n\t", "\n\t", "\n") + "\n" + - "Settings:" + "\n" + - settings - ) - } - - // - // - // PREANALYSES - // - // - - step(1, "[Pre-Analysis] Identifying non-instantiable classes") { - (theProject.get(InstantiableClassesKey), None) - } - - val fieldAccessInformation = step(2, "[Pre-Analysis] Analyzing field accesses") { - (theProject.get(FieldAccessInformationKey), None) - } - - val stringConstantsInformation = step(3, "[Pre-Analysis] Analyzing the usage of string constants") { - (theProject.get(StringConstantsInformationKey), None) - } - - step(4, "[Pre-Analysis] Analyzing field declarations to derive more precise field value information") { - (theProject.get(FieldValuesKey), None) - } - - step(5, "[Pre-Analysis] Analyzing methods to get more precise return type information") { - (theProject.get(MethodReturnValuesKey), None) - } - - val computedCallGraph = step(6, "[Pre-Analysis] Creating the call graph") { - (theProject.get(VTACallGraphKey), None) - } - val callGraph = computedCallGraph.callGraph - val callGraphEntryPoints = computedCallGraph.entryPoints().toSet - - // - // - // Compute Fixpoint properties - // - // - - val analysesManager = theProject.get(FPCFAnalysesManagerKey) - val propertyStore = theProject.get(PropertyStoreKey) - step(7, "[FPCF-Analysis] executing fixpoint analyses") { - ( - { - fpcfAnalyses.foreach(analysesManager.run(_, false)) - propertyStore.waitOnPropertyComputationCompletion(true) - }, - None - ) - } - - // - // - // MAIN ANALYSIS - // - // - - val doInterrupt: () => Boolean = progressManagement.isInterrupted _ - - val filteredResults = new ConcurrentLinkedQueue[Issue]() - val issuesPackageFilterString = config.as[String]("org.opalj.bugpicker.issues.packages") - OPALLogger.debug( - "project configuration", - s"only issues in packages matching $issuesPackageFilterString are shown" - ) - val issuesPackageFilter = issuesPackageFilterString.r - def addResults(issues: Iterable[Issue]): Unit = { - if (issues.nonEmpty) { - val filteredIssues = issues.filter { issue => - issue.locations.head match { - case l: PackageLocation => - val packageName = l.thePackage - val allMatches = issuesPackageFilter.findFirstIn(packageName) - allMatches.isDefined && packageName == allMatches.get - case _ => - // the issue is a project level issue and hence kept - true - } - } - filteredResults.addAll(filteredIssues.asJavaCollection) - } - } - - val fieldValueInformation = theProject.get(FieldValuesKey) - val methodReturnValueInformation = theProject.get(MethodReturnValuesKey) - - val cache = new CallGraphCache[MethodSignature, scala.collection.Set[Method]](theProject) - - def analyzeMethod(method: Method, body: Code): Unit = { - val classFile: ClassFile = method.classFile - // USED DURING DEVELEOPMENT; e.g., if we see a specific method. - val debug = false - - // --------------------------------------------------------------------------- - // Analyses that don't require an abstract interpretation - // --------------------------------------------------------------------------- - - // - // CHECK IF THE METHOD IS USED - // - addResults( - UnusedMethodsAnalysis(theProject, computedCallGraph, callGraphEntryPoints, method) - ) - - // --------------------------------------------------------------------------- - // Analyses that are dependent on the result of the abstract interpretation - // --------------------------------------------------------------------------- - - val analysisDomain = - new RootBugPickerAnalysisDomain( - theProject, - // Map.empty, Map.empty, - fieldValueInformation, - methodReturnValueInformation, - cache, - maxCardinalityOfIntegerRanges, - maxCardinalityOfLongSets, - maxCallChainLength, - method, - debug - ) - val ai0 = - new BoundedInterruptableAI[analysisDomain.type]( - body, - maxEvalFactor, - maxEvalTime, - doInterrupt - ) - val result = { - val result0 = ai0(method, analysisDomain) - if (result0.wasAborted && maxCallChainLength > 0) { - val logMessage = - s"analysis of ${method.fullyQualifiedSignature} with method call execution aborted " + - s"after ${ai0.currentEvaluationCount} steps " + - s"(code size: ${method.body.get.instructions.length})" - // let's try it again, but without performing method calls; - // let's reuse the current state - val fallbackAnalysisDomain = - new FallbackBugPickerAnalysisDomain( - theProject, - fieldValueInformation, - methodReturnValueInformation, - cache, - maxCardinalityOfIntegerRanges, - maxCardinalityOfLongSets, - method - ) - - val ai1 = - new BoundedInterruptableAI[fallbackAnalysisDomain.type]( - body, - maxEvalFactor, - maxEvalTime, - doInterrupt - ) - - val result1 = ai1(method, fallbackAnalysisDomain) - - if (result1.wasAborted) - OPALLogger.warn( - "configuration", - logMessage + ": retry without performing invocations also failed" - ) - else - OPALLogger.info("configuration", logMessage) - - result1 - } else - result0 - - } - - if (!result.wasAborted) { - if (debug) { - import result.* - val domainName = domain.getClass.getName - org.opalj.io.writeAndOpen( - org.opalj.ai.common.XHTML.dump( - Some(classFile), - Some(method), - method.body.get, - Some( - s"Created: ${new Date}
Domain: $domainName
" + - XHTML.evaluatedInstructionsToXHTML(result.evaluated) - ), - domain - )(cfJoins, result.operandsArray, result.localsArray), - "AIResult", - ".html" - ) - } - - // - // FIND DEAD CODE - // - addResults(DeadEdgesAnalysis(theProject, method, result)) - - // - // FIND SUSPICIOUS CODE - // - addResults(GuardedAndUnguardedAccessAnalysis(theProject, method, result)) - - // - // FIND INSTRUCTIONS THAT ALWAYS THROW AN EXCEPTION - // - addResults(ThrowsExceptionAnalysis(theProject, method, result).toIterable) - - // - // FIND USELESS COMPUTATIONS - // - addResults(UselessComputationsAnalysis(theProject, method, result)) - - // - // FIND USELESS REEVALUATIONS OF COMPUTATIONS - // - addResults(UselessReComputationsAnalysis(theProject, method, result)) - - // - // FIND UNUSED LOCAL VARIABLES - // - addResults( - UnusedLocalVariables(theProject, propertyStore, callGraph, method, result) - ) - - // - // FIND STRANGE USES OF THE COLLECTIONS API - // - addResults( - CollectionsUsage(theProject, propertyStore, callGraph, method, result) - ) - - } else if (!doInterrupt()) { - OPALLogger.error( - "internal error", - s"analysis of ${method.fullyQualifiedSignature} aborted " + - s"after ${ai0.currentEvaluationCount} steps " + - s"(code size: ${method.body.get.instructions.length})" - ) - } /* else (doInterrupt === true) the analysis as such was interrupted*/ - } - - val exceptions = new ConcurrentLinkedQueue[AnalysisException] - var analysisTime = Nanoseconds.None - val identifiedIssues = time { - val stepIds = new AtomicInteger(PreAnalysesCount + 1) - - theProject.parForeachProjectClassFile(doInterrupt) { classFile => - val stepId = stepIds.getAndIncrement() - try { - progressManagement.start(stepId, classFile.thisType.toJava) - - // --------------------------------------------------------------------------- - // Class based analyses - // --------------------------------------------------------------------------- - - addResults(AnonymousInnerClassShouldBeStatic(theProject, classFile)) - addResults(ManualGarbageCollection(theProject, classFile)) - addResults(CovariantEquals(classFile)) - - // - // FIND UNUSED FIELDS - // - addResults( - UnusedFields( - theProject, - propertyStore, - fieldAccessInformation, - stringConstantsInformation, - classFile - ) - ) - - // --------------------------------------------------------------------------- - // Analyses of the methods - // --------------------------------------------------------------------------- - - for (method <- classFile.methods; body <- method.body) { - try { - analyzeMethod(method, body) - } catch { - case afe: InterpretationFailedException => - val ms = method.fullyQualifiedSignature - val steps = afe.ai.asInstanceOf[BoundedInterruptableAI[?]].currentEvaluationCount - val message = - s"the analysis of $ms failed/was aborted after $steps steps" - exceptions add (AnalysisException(message, afe)) - case b: Break[?] => throw b - case t: Throwable => - val ms = method.fullyQualifiedSignature - val message = s"the analysis of ${ms} failed" - exceptions add (AnalysisException(message, t)) - } - } - } catch { - case t: Throwable => - OPALLogger.error( - "internal error", - s"evaluation step $stepId failed", - t - ) - throw t - } finally { - progressManagement.end(stepId) - } - } - filteredResults.asScala.toSeq - } { t => analysisTime = t } - - OPALLogger.info( - "analysis progress", - s"the analysis took ${analysisTime.toSeconds} " + - s"and found ${identifiedIssues.size} unique issues" - ) - import scala.collection.JavaConverters.* - (analysisTime, identifiedIssues, exceptions.asScala) - } -} - -/** - * Common constants and helper methods related to the configuration of the BugPicker and - * generating reports. - * - * @author Michael Eichberg - */ -object BugPickerAnalysis { - - // 1: InstantiableClasses analysis - // 2: FieldAccessInformation - // 3: StringConstantsInformation - // 4: FieldValues analysis - // 5: MethodReturnValues analysis - // 6: Callgraph - // 7: FPCF properties - final val PreAnalysesCount = 7 - - // We want to match expressions such as: - // -maxEvalFactor=1 - // -maxEvalFactor=20 - // -maxEvalFactor=1.25 - // -maxEvalFactor=10.5 - // -maxEvalFactor=Infinity - final val MaxEvalFactorPattern = """-maxEvalFactor=(\d+(?:.\d+)?|Infinity)""".r - final val DefaultMaxEvalFactor = 1.75d - - final val MaxEvalTimePattern = """-maxEvalTime=(\d+)""".r - final val DefaultMaxEvalTime: Milliseconds = new Milliseconds(10000L) // in ms => 10secs. - - final val MaxCallChainLengthPattern = """-maxCallChainLength=(\d)""".r - final val DefaultMaxCallChainLength = 1 - - final val MaxCardinalityOfIntegerRangesPattern = - """-maxCardinalityOfIntegerRanges=(\d+)""".r - final val DefaultMaxCardinalityOfIntegerRanges = 16L - - final val MaxCardinalityOfLongSetsPattern = - """-maxCardinalityOfLongSets=(\d+)""".r - final val DefaultMaxCardinalityOfLongSets = 2 - - final val FixpointAnalysesPattern = """-fixpointAnalyses=(.+)""".r - final val DefaultFixpointAnalyses = Seq.empty[String] - - def resultsAsXHTML( - config: Seq[String], - theIssues: Iterable[Issue], - showSearch: Boolean, - analysisTime: Nanoseconds - ): Node = { - // TODO Make the filtering a configurable property!!! - val issuesCount = theIssues.size - val issues = - if (issuesCount > 1000) { - theIssues.filter(_.relevance.value >= Relevance.VeryLow.value) - } else { - theIssues - } - val basicInfoOnly = issuesCount > 15000 - - val totalIssues = { - var is = s"(Total issues: $issuesCount)" - if (issues.size < theIssues.size) - is += "(Due to the number of identified issues all those that are most likely completely irrelevant are filtered.)" - if (basicInfoOnly) - is += "(Due to the number of remaining issues an abbreviated report is shown.)" - - is - } - - val issuesNode: Iterable[Node] = { - import scala.collection.SortedMap - val groupedMessages = - SortedMap.empty[String, List[Issue]] ++ - issues.groupBy { i => - i.locations.head match { - case thePackage: PackageLocation => thePackage.thePackage - case _: ProjectLocation => "" - } - } - val result = - (for { (pkg, mdc) <- groupedMessages } yield { -
- {pkg.replace('/', '.')} - {mdc.toSeq.sorted(IssueOrdering).map(_.toXHTML(basicInfoOnly))} -
- }) - result.seq - } - - val (searchJS: NodeSeq, searchBox: NodeSeq) = - if (showSearch) { - ( - , - - ) - } else { - (NodeSeq.Empty, NodeSeq.Empty) - } - - - - - - {searchJS} - - - - -
-
- Number of issues currently displayed: {issuesCount} { - totalIssues - } - {searchBox} -
-
- Suppress issues with an estimated - importance - less than: - 1 - - 100 -
-
- Manifestation in the Code:
- -
-
- Software Quality Attributes:
- -
-
- Show all Packages:+- -
-
-
-
- Parameters -
    - { - config.filterNot(_.contains("debug")).map(p =>
  • {p}
  • ) - } -
-
-
-
- {issuesNode} -
- - - } - //
<-- add if you want to debug -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysisDomain.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysisDomain.scala deleted file mode 100644 index 6997c3d641..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/BugPickerAnalysisDomain.scala +++ /dev/null @@ -1,274 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import java.net.URL - -import org.opalj.ai.AIResult -import org.opalj.ai.CorrelationalDomain -import org.opalj.ai.TheAI -import org.opalj.ai.TheMemoryLayout -import org.opalj.ai.analyses.FieldValueInformation -import org.opalj.ai.analyses.MethodReturnValueInformation -import org.opalj.ai.analyses.cg.CallGraphCache -import org.opalj.ai.domain -import org.opalj.ai.domain.l2.CalledMethodsStore -import org.opalj.ai.domain.l2.ChildPerformInvocationsWithRecursionDetection -import org.opalj.ai.domain.l2.PerformInvocationsWithRecursionDetection -import org.opalj.ai.domain.la.PerformInvocationsWithBasicVirtualMethodCallResolution -import org.opalj.ai.mapOperands -import org.opalj.ai.util.XHTML -import org.opalj.br.Method -import org.opalj.br.MethodDescriptor -import org.opalj.br.MethodSignature -import org.opalj.br.PC -import org.opalj.br.ReferenceType -import org.opalj.br.analyses.Project -import org.opalj.collection.immutable.Chain - -/** - * The base domain that is shared by all domains that are used to perform abstract - * interpretations of methods. - * - * @author Michael Eichberg - */ -trait BaseBugPickerAnalysisDomain - extends CorrelationalDomain - with domain.TheProject - with domain.TheMethod - with domain.DefaultSpecialDomainValuesBinding - with domain.ThrowAllPotentialExceptionsConfiguration - // with domain.l0.TypeLevelFieldAccessInstructions - with domain.la.RefinedTypeLevelFieldAccessInstructions - with domain.l0.TypeLevelInvokeInstructions - with domain.la.RefinedTypeLevelInvokeInstructions - with domain.SpecialMethodsHandling - with domain.l1.DefaultIntegerRangeValues - // with domain.l1.DefaultIntegerSetValues - // [CURRENTLY ONLY A WASTE OF RESOURCES] with domain.l1.ConstraintsBetweenIntegerValues - with domain.l1.DefaultLongSetValues - with domain.l1.LongSetValuesShiftOperators - with domain.l0.DefaultTypeLevelFloatValues - with domain.l0.DefaultTypeLevelDoubleValues - with domain.l1.ConcretePrimitiveValuesConversions - // with domain.l1.DefaultReferenceValuesBinding [implicitly mixed in via StringValuesBinding] - // with domain.l1.DefaultStringValuesBinding [implicitly mixed in via ClassValuesBinding] - with domain.l1.NullPropertyRefinement - with domain.l1.MaxArrayLengthRefinement - with domain.DefaultHandlingOfMethodResults - with domain.IgnoreSynchronization { - // We want to get the special treatment of calls on "Class" objects - // and do not want to perform invocations in this case; - // hence, we have to mix in this domain AFTER the PerformInvocations domain! - this: domain.l1.DefaultClassValuesBinding => -} - -/** - * This is the fall back domain that is used to perform an abstract interpretation of - * a method without invoking called methods. - */ -class FallbackBugPickerAnalysisDomain( - val project: Project[URL], - val fieldValueInformation: FieldValueInformation, - val methodReturnValueInformation: MethodReturnValueInformation, - val cache: CallGraphCache[MethodSignature, scala.collection.Set[Method]], - override val maxCardinalityOfIntegerRanges: Long, - override val maxCardinalityOfLongSets: Int, - val /*current*/ method: Method -) extends BaseBugPickerAnalysisDomain - with domain.l1.DefaultClassValuesBinding - with domain.l1.RecordAllThrownExceptions - with domain.RecordCFG - with domain.RecordDefUse - -/** - * The base domain that is shared by all domains that are used to perform abstract - * interpretations of methods where methods are potentially called. - */ -trait BasePerformInvocationBugPickerAnalysisDomain - extends BaseBugPickerAnalysisDomain - with PerformInvocationsWithRecursionDetection - with PerformInvocationsWithBasicVirtualMethodCallResolution - with domain.l1.DefaultClassValuesBinding { callingDomain => - - def debug: Boolean - - type CalledMethodDomain = InvocationBugPickerAnalysisDomain - - override protected def doInvoke( - method: Method, - calledMethodDomain: CalledMethodDomain - )( - parameters: calledMethodDomain.Locals - ): AIResult { val domain: calledMethodDomain.type } = { - val result = super.doInvoke(method, calledMethodDomain)(parameters) - if (debug) { - import result.* - org.opalj.io.writeAndOpen( - org.opalj.ai.common.XHTML.dump( - Some(method.classFile), - Some(method), - method.body.get, - Some( - "Created: " + (new java.util.Date).toString + "
" + - "Domain: " + result.domain.getClass.getName + "
" + - XHTML.evaluatedInstructionsToXHTML(result.evaluated) - ), - result.domain - )(cfJoins, result.operandsArray, result.localsArray), - "AIResult", - ".html" - ) - } - result - } - - override def doInvoke( - pc: PC, - method: Method, - operands: callingDomain.Operands, - fallback: () => MethodCallResult - ): MethodCallResult = { - val result = super.doInvoke(pc, method, operands, fallback) - if (debug) { - println("the result of calling " + method.toJava + " is " + result) - } - result - } - - val maxCallChainLength: Int - - def currentCallChainLength: Int - - def shouldInvocationBePerformed(calledMethod: Method): Boolean = { - val result = - maxCallChainLength > currentCallChainLength && - // TODO check me if the following makes sense: - calledMethod.isPrivate && calledMethod.actualArgumentsCount != 1 - if (debug) { - val i = if (result) " invokes " else " does not invoke " - println(s"[$currentCallChainLength]" + - method.toJava + - i + - calledMethod.toJava) - } - result - } - - abstract override def invokevirtual( - pc: PC, - declaringClass: ReferenceType, - name: String, - descriptor: MethodDescriptor, - operands: Operands - ): MethodCallResult = { - - val result = super.invokevirtual(pc, declaringClass, name, descriptor, operands) - if (debug) { - println(s"[$currentCallChainLength] call result of " + - declaringClass.toJava + " " + descriptor.toJava(name) + result) - } - result - } -} - -class InvocationBugPickerAnalysisDomain( - val project: Project[URL], - val fieldValueInformation: FieldValueInformation, - val methodReturnValueInformation: MethodReturnValueInformation, - val cache: CallGraphCache[MethodSignature, scala.collection.Set[Method]], - override val maxCardinalityOfIntegerRanges: Long, - override val maxCardinalityOfLongSets: Int, - val maxCallChainLength: Int, - val callerDomain: BasePerformInvocationBugPickerAnalysisDomain, - val /*current*/ method: Method, - val currentCallChainLength: Int, - val debug: Boolean -) extends BasePerformInvocationBugPickerAnalysisDomain - with domain.RecordMethodCallResults - with domain.RecordLastReturnedValues - with domain.RecordAllThrownExceptions - with ChildPerformInvocationsWithRecursionDetection { - callingDomain => - - override def calledMethodDomain(method: Method) = { - new InvocationBugPickerAnalysisDomain( - project, - fieldValueInformation, - methodReturnValueInformation, - cache, - maxCardinalityOfIntegerRanges, - maxCardinalityOfLongSets, - maxCallChainLength, - callingDomain, - method, - currentCallChainLength + 1, - debug - ) {} - } - - def calledMethodAI = callerDomain.calledMethodAI - -} - -/** - * The domain that is used to identify the issues. - * - * @author Michael Eichberg - */ -class RootBugPickerAnalysisDomain( - val project: Project[URL], - val fieldValueInformation: FieldValueInformation, - val methodReturnValueInformation: MethodReturnValueInformation, - val cache: CallGraphCache[MethodSignature, scala.collection.Set[Method]], - override val maxCardinalityOfIntegerRanges: Long, - override val maxCardinalityOfLongSets: Int, - val maxCallChainLength: Int, - val /*current*/ method: Method, - val debug: Boolean, - val frequentEvaluationWarningLevel: Int = 256 -) extends BasePerformInvocationBugPickerAnalysisDomain - with TheAI[BaseBugPickerAnalysisDomain] - with TheMemoryLayout // required to extract the initial operands - // the following two are required to detect instructions that always throw - // an exception (such as div by zero, a failing checkcast, a method call that - // always fails etc.) - with domain.l1.RecordAllThrownExceptions - with domain.RecordCFG - with domain.RecordDefUse { callingDomain => - - final def currentCallChainLength: Int = 0 - final def calledMethodAI = ai - final val coordinatingDomain = this - - // The called methods store is always only required at analysis time, at this point - // in time the initial operands are available! - lazy val calledMethodsStore: CalledMethodsStore { val domain: coordinatingDomain.type } = { - val operands = - localsArray(0).foldLeft(Chain.empty[DomainValue])((l, n) => - if (n ne null) n :&: l else l - ) - CalledMethodsStore(coordinatingDomain, frequentEvaluationWarningLevel)( - method, - mapOperands(operands, coordinatingDomain) - ) - } - - override def calledMethodDomain(method: Method) = - new InvocationBugPickerAnalysisDomain( - project, - fieldValueInformation, - methodReturnValueInformation, - cache, - maxCardinalityOfIntegerRanges, - maxCardinalityOfLongSets, - maxCallChainLength, - callingDomain, - method, - currentCallChainLength + 1, - debug - ) - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CollectionsUsage.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CollectionsUsage.scala deleted file mode 100644 index 1ba93a0270..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CollectionsUsage.scala +++ /dev/null @@ -1,159 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.Domain -import org.opalj.ai.analyses.cg.CallGraph -import org.opalj.ai.domain.RecordDefUse -import org.opalj.ai.domain.TheCode -import org.opalj.br.ClassType -import org.opalj.br.Method -import org.opalj.br.MethodDescriptor -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.INVOKEINTERFACE -import org.opalj.br.instructions.INVOKESPECIAL -import org.opalj.br.instructions.INVOKESTATIC -import org.opalj.br.instructions.INVOKEVIRTUAL -import org.opalj.br.instructions.NEW -import org.opalj.fpcf.PropertyStore -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Relevance - -/** - * Identifies cases where the collections API is not used as intended. - * - * @author Michael Eichberg - */ -object CollectionsUsage { - - final val UnmodifiableCollectionMethodDescriptor = MethodDescriptor(ClassType.Collection, ClassType.Collection) - - def apply( - theProject: SomeProject, - propertyStore: PropertyStore, - callGraph: CallGraph, - method: Method, - result: AIResult { val domain: Domain with TheCode with RecordDefUse } - ): Seq[Issue] = { - - if (method.isSynthetic) - return Nil; - // - // - // IDENTIFYING RAW ISSUES - // - // - var issues = List.empty[Issue] - val domain = result.domain - val code = domain.code - val instructions = code.instructions - code iterate { (pc, instruction) => - instruction match { - - case INVOKESTATIC( - ClassType.Collections, - false, - "unmodifiableCollection", - UnmodifiableCollectionMethodDescriptor - ) => - val origins = domain.operandOrigin(pc, 0) - if ((origins ne null) && // the instruction is not dead - origins.size == 1 && - origins.head >= 0 && // the origin is not a parameter - instructions(origins.head).opcode == NEW.opcode - ) { - // FIXME Add check if something is done in a loop - // there is just one path on which the value is initialized - val usages = domain.usedBy(origins.head) - if (usages.size == 2) { - // one for the call of the initializer and for the call to Coll... - instructions(usages.withFilter(_ != pc).head) match { - - // TODO Support the matching of other constructors... (e.g., which take a size hint) - case INVOKESPECIAL(_, false, _, MethodDescriptor.NoArgsAndReturnVoid) => - issues ::= Issue( - "CollectionsUsage", - Relevance.DefaultRelevance, - "useless creation of standard collection class", - Set(IssueCategory.Comprehensibility, IssueCategory.Performance), - Set(IssueKind.JavaCollectionAPIMisusage), - List( - new InstructionLocation( - Some("directly use Collections.emptyList/Collections.emptySet"), - theProject, - method, - pc - ), - new InstructionLocation( - Some("useless"), - theProject, - method, - origins.head - ) - ) - ) - - case _ => // other constructors are ignored - } - - } else if (usages.size == 3) { - var foundConstructorCall = false - var foundAddCall = false - val previousUsages = usages.withFilter(_ != pc) - previousUsages.foreach { pc => - instructions(pc) match { - - // TODO Support the matching of other constructors... (e.g., which take a size hint) - case INVOKESPECIAL(_, false, _, MethodDescriptor.NoArgsAndReturnVoid) => - foundConstructorCall = true - - // TODO Support the case of a call to addElement - case INVOKEVIRTUAL(_, "add", MethodDescriptor(IndexedSeq(ClassType.Object), _)) | - INVOKEINTERFACE(_, "add", MethodDescriptor(IndexedSeq(ClassType.Object), _)) => - // is it the receiver or the parameter (in relation to a different collection? - if (domain.operandOrigin(pc, 1) == origins) { - foundAddCall = true - } - - case i => // other calls are ignored - println("let's see" + i) - } - } - if (foundAddCall && foundConstructorCall) { - issues ::= Issue( - "CollectionsUsage", - Relevance.DefaultRelevance, - "useless creation of standard collection class", - Set(IssueCategory.Comprehensibility, IssueCategory.Performance), - Set(IssueKind.JavaCollectionAPIMisusage), - List( - new InstructionLocation( - Some("directly use Collections.singletonList/Collections.singletonSet"), - theProject, - method, - pc - ), - new InstructionLocation( - Some("useless"), - theProject, - method, - origins.head - ) - ) - ) - } - } - } - case _ => // don't care - } - } - - issues - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CovariantEquals.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CovariantEquals.scala deleted file mode 100644 index 3b7ba78e58..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/CovariantEquals.scala +++ /dev/null @@ -1,114 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.br.BooleanType -import org.opalj.br.ClassFile -import org.opalj.br.ClassType -import org.opalj.br.IntegerType -import org.opalj.br.Method -import org.opalj.br.MethodDescriptor -import org.opalj.br.analyses.SomeProject -import org.opalj.issues.ClassLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Relevance - -/** - * This analysis reports classes that have some `equals()` method(s), but not - * `equals(Object)`. This is bad practice and can lead to unexpected behavior, because - * without an `equals(Object)` method, `Object.equals(Object)` is not properly overridden. - * However, the relevance is determined by the presence of a hashCode method. - * - * @author Daniel Klauer - * @author Michael Eichberg - */ -object CovariantEquals { - - def description: String = - "Reports classes with one (or more) equals() methods but without equals(Object)." - - /** - * Checks whether a class has `equals()` methods but not `equals(Object)`. - * - * @param classFile The class to check. - * @return Whether the class has `equals()` methods but not `equals(Object)`. - */ - private def hasEqualsButNotEqualsObject(classFile: ClassFile): Boolean = { - val paramTypes = classFile.methods.collect { - case Method(_, "equals", MethodDescriptor(Seq(paramType), BooleanType)) => paramType - } - - paramTypes.size > 0 && !paramTypes.exists(_ == ClassType.Object) - } - - private def hasHashCode(classFile: ClassFile): Boolean = { - classFile.methods.exists { - case Method(_, "hashCode", MethodDescriptor(Seq(), IntegerType)) => true - case _ => false - } - } - - private def superClassHasCustomHashCode( - classFile: ClassFile - )( - implicit project: SomeProject - ): Boolean = { - - if (classFile.thisType eq ClassType.Object) - return false; - - val superclassType = classFile.superclassType.get - if (superclassType eq ClassType.Object) - return false; - - import MethodDescriptor.JustReturnsInteger - project.resolveClassMethodReference(superclassType, "hashCode", JustReturnsInteger) match { - case Success(m) => m.classFile.thisType ne ClassType.Object - case _ => false - } - } - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @return A list of reports, or an empty list. - */ - def apply( - classFile: ClassFile - )( - implicit project: SomeProject - ): Iterable[Issue] = { - if (classFile.isInterfaceDeclaration) - return Iterable.empty; - - if (hasEqualsButNotEqualsObject(classFile)) { - var message = "missing equals(Object) to override Object.equals(Object)" - val relevance = - if (hasHashCode(classFile)) { - message += " (the class overrides the standard hashCode method)" - Relevance.VeryHigh - } else if (superClassHasCustomHashCode(classFile)) { - message += " (a superclass overrides the standard hashCode method)" - Relevance.High - } else { - Relevance.Low - } - - Iterable(Issue( - "CovariantEquals", - relevance, - message, - Set(IssueCategory.Correctness), - Set(IssueKind.DubiousMethodDefinition), - List(new ClassLocation(None, project, classFile)) - )) - } else - Nil - - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/DeadEdgesAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/DeadEdgesAnalysis.scala deleted file mode 100644 index b140c7a74d..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/DeadEdgesAnalysis.scala +++ /dev/null @@ -1,362 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.BaseAI -import org.opalj.ai.Domain -import org.opalj.ai.analyses.cg.Callees -import org.opalj.ai.domain.Origin -import org.opalj.ai.domain.RecordCFG -import org.opalj.ai.domain.ThrowNoPotentialExceptionsConfiguration -import org.opalj.ai.domain.l0.ZeroDomain -import org.opalj.br.ClassType -import org.opalj.br.Code -import org.opalj.br.ExceptionHandler -import org.opalj.br.Method -import org.opalj.br.PC -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.ATHROW -import org.opalj.br.instructions.CompoundConditionalBranchInstruction -import org.opalj.br.instructions.ConditionalBranchInstruction -import org.opalj.br.instructions.GotoInstruction -import org.opalj.br.instructions.MethodInvocationInstruction -import org.opalj.br.instructions.NEW -import org.opalj.br.instructions.PopInstruction -import org.opalj.br.instructions.RET -import org.opalj.br.instructions.ReturnInstruction -import org.opalj.collection.immutable.Chain -import org.opalj.collection.immutable.Naught -import org.opalj.issues.FieldValues -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.IssueOrdering -import org.opalj.issues.LocalVariables -import org.opalj.issues.MethodReturnValues -import org.opalj.issues.Operands -import org.opalj.issues.Relevance - -/** - * Identifies dead edges in code. - * - * @author Michael Eichberg - */ -object DeadEdgesAnalysis { - - def apply( - theProject: SomeProject, - method: Method, - result: AIResult { val domain: Domain with Callees with RecordCFG with Origin } - ): Seq[Issue] = { - if (method.isSynthetic) - return Seq.empty; - - import result.domain - import result.operandsArray - import result.localsArray - val evaluatedInstructions = result.evaluatedInstructions - implicit val body: Code = result.code - val instructions = body.instructions - import result.cfJoins - import result.domain.regularSuccessorsOf - import result.domain.hasMultiplePredecessors - import result.domain.isRegularPredecessorOf - - /* - * Helper function to test if this code will always throw – independent - * of any data-flow - an exception if executed. - */ - def isAlwaysExceptionThrowingMethodCall(pc: PC): Boolean = { - instructions(pc) match { - case MethodInvocationInstruction(receiver: ClassType, isInterface, name, descriptor) => - val callees = domain.callees(method, receiver, isInterface, name, descriptor) - if (callees.size != 1) - return false; - - // We are only handling the special idiom where the call site is - // monomorphic and where the target method is used to create and throw - // a special exception object - // ... - // catch(Exception e) { - // /*return|athrow*/ handleException(e); - // } - callees.head.body.map(code => !code.exists { (pc, i) => i.isReturnInstruction }).getOrElse(false) - - case _ => - false - } - } - - /* - * A return/goto/athrow instruction is considered useless if the preceding - * instruction is a method call with a single target that _context-independently_ - * always just throws (an) exception(s). This is common pattern found in the JDK. - */ - // We want to suppress false warning as found in JDK 1.8.0_25 - // javax.xml.bind.util.JAXBResult - // when the method - // assertFailed - // is called and afterwards a jump is done to a non-dead instruction. - def requiredUselessJumpOrReturnFromMethod(currentPC: PC, nextPC: PC): Boolean = { - val nextInstruction = body.instructions(nextPC) - ( - nextInstruction.isInstanceOf[ReturnInstruction] || ( - nextInstruction.isInstanceOf[PopInstruction] && - body.instructions(body.pcOfNextInstruction(nextPC)).isInstanceOf[ReturnInstruction] - ) || nextInstruction == ATHROW || ( - nextInstruction.isInstanceOf[GotoInstruction] && - evaluatedInstructions.contains(body.nextNonGotoInstruction(nextPC)) - ) - ) && - isAlwaysExceptionThrowingMethodCall(currentPC) - } - - def mostSpecificFinallyHandlerOfPC(pc: PC): Seq[ExceptionHandler] = { - val candidateHandlers = - body.exceptionHandlers.filter { eh => eh.catchType.isEmpty && isRegularPredecessorOf(eh.handlerPC, pc) } - if (candidateHandlers.size > 1) { - candidateHandlers.tail.foldLeft(List(candidateHandlers.head)) { (c, n) => - var mostSpecificHandlers: List[ExceptionHandler] = List.empty - var addN = false - c.foreach { c => - if (isRegularPredecessorOf(c.handlerPC, n.handlerPC)) { - addN = true - } else if (isRegularPredecessorOf(n.handlerPC, c.handlerPC)) { - mostSpecificHandlers = c :: mostSpecificHandlers - } else { - mostSpecificHandlers = c :: mostSpecificHandlers - addN = true - } - } - if (addN) { - mostSpecificHandlers = n :: mostSpecificHandlers - } - mostSpecificHandlers - } - } else - candidateHandlers - } - - var issues = List.empty[Issue] - for { - pc <- body.programCounters.iterator - if evaluatedInstructions.contains(pc) - instruction = instructions(pc) - opcode = instruction.opcode - // Let's filter those instructions for which we cannot statically determine - // the set of meaningful successors: - // (I) In case of RET we don't know the next one, but the next one - // is not dead... (ever) if we reach the RET instruction - if opcode != RET.opcode - // (II) We don't have an analysis in place that enables us to determine - // the meaningful set of successors. - if opcode != ATHROW.opcode - - // Let's check if a path is never taken: - nextPC <- instruction.nextInstructions(pc, regularSuccessorsOnly = true).toIterator - if !regularSuccessorsOf(pc).contains(nextPC) - - // If we are in a subroutine, we don't have sufficient information - // to draw any conclusion; hence, we cannot derive any results. - allOperands = operandsArray(pc) - if allOperands ne null // null if we are in a subroutine (java < 1.5) - } { - // identify those dead edges that are pure technical artifacts - val isLikelyFalsePositive = requiredUselessJumpOrReturnFromMethod(pc, nextPC) - - def isRelatedToCompilationOfFinally: Boolean = { - // There has to be at least one finally statement. - if (!body.exceptionHandlers.exists(_.catchType.isEmpty)) - return false; - - // All issues related to the compilation of finally manifest - // themselves in dead edges related to conditional branch instructions - if (!instruction.isInstanceOf[ConditionalBranchInstruction]) - return false; - - // Let's determine the index of the local variable that is evaluated - val lvIndexOption = localsArray(pc).indexOf(allOperands.head) - if (lvIndexOption.isEmpty) - return false; - - // Let's find all other if instructions that also access the same - // local variable and which are not in a predecessor /successor relation - val finallyHandler = mostSpecificFinallyHandlerOfPC(pc) - val lvIndex = lvIndexOption.get - val correspondingPCs = body.collectWithIndex { - case (otherPC, _: ConditionalBranchInstruction) - if otherPC != pc && - (operandsArray(otherPC) ne null) && - (operandsArray(otherPC).head eq localsArray(otherPC)(lvIndex)) && - body.haveSameLineNumber(pc, otherPC).getOrElse(true) && - !isRegularPredecessorOf(pc, otherPC) && - !isRegularPredecessorOf(otherPC, pc) && - (finallyHandler intersect mostSpecificFinallyHandlerOfPC(otherPC)).isEmpty => - (otherPC) - } - correspondingPCs.nonEmpty - } - - lazy val isProvenAssertion = { - instructions(nextPC) match { - case NEW(AssertionError) => true - case _ => false - } - } - - // Identify those dead edges that are the result of common programming - // idioms; e.g., - // switch(v){ - // ... - // default: - // 1: throw new XYZError(...); - // 2: throw new IllegalStateException(...); - // 3: assert(false); - // 4: stateError(); - // AN ALWAYS (PRIVATE AND/OR STATIC) EXCEPTION - // THROWING METHOD - // HERE, THE DEFAULT CASE MAY EVEN FALL THROUGH! - // } - // - lazy val isDefaultBranchOfSwitch = - instruction.isInstanceOf[CompoundConditionalBranchInstruction] && - nextPC == pc + instruction.asInstanceOf[CompoundConditionalBranchInstruction].defaultOffset - - lazy val isNonExistingDefaultBranchOfSwitch = isDefaultBranchOfSwitch && - hasMultiplePredecessors( - pc + instruction.asInstanceOf[CompoundConditionalBranchInstruction].defaultOffset - ) - - lazy val isLikelyIntendedDeadDefaultBranch = isDefaultBranchOfSwitch && - // this is the default branch of a switch instruction that is dead - body.alwaysResultsInException( - nextPC, - cfJoins, - (invocationPC) => { - isAlwaysExceptionThrowingMethodCall(invocationPC) - }, - (athrowPC) => { - // Let's do a basic analysis to determine the type of - // the thrown exception. - // What we do next is basic a local data-flow analysis that - // starts with the first instruction of the default branch - // of the switch instruction and which uses - // the most basic domain available. - val codeLength = body.instructions.length - class ZDomain extends { // we need the "early initializer - val project: SomeProject = theProject - val code: Code = body - } with ZeroDomain with ThrowNoPotentialExceptionsConfiguration - val zDomain = new ZDomain - val zOperandsArray = new zDomain.OperandsArray(codeLength) - val zInitialOperands = - operandsArray(pc).tail.map(_.adapt(zDomain, Int.MinValue)) - zOperandsArray(nextPC) = zInitialOperands - val zLocalsArray = new zDomain.LocalsArray(codeLength) - zLocalsArray(nextPC) = - localsArray(pc) map { l => - if (l ne null) - l.adapt(zDomain, Int.MinValue) - else - null - } - BaseAI.continueInterpretation( - result.code, - result.cfJoins, - result.liveVariables, - zDomain - )( - /*initialWorkList =*/ Chain(nextPC), - /*alreadyEvaluated =*/ Naught, - /*subroutinesWereEvaluated=*/ false, - zOperandsArray, - zLocalsArray, - Naught, - null, - null // we don't care about the state of subroutines - ) - val exceptionValue = zOperandsArray(athrowPC).head - val throwsError = - ( - zDomain.asReferenceValue(exceptionValue). - isValueASubtypeOf(ClassType.Error). - isYesOrUnknown - ) || - zDomain.asReferenceValue(exceptionValue). - isValueASubtypeOf(ClassType.IllegalStateException). - isYesOrUnknown - - throwsError - } - ) - - val poppedOperandsCount = - instruction.numberOfPoppedOperands { index => allOperands(index).computationalType.category } - val operands = allOperands.take(poppedOperandsCount) - - val line = body.lineNumber(nextPC).map(l => s" (line=$l)").getOrElse("") - - val isJustDeadPath = evaluatedInstructions.contains(nextPC) - val isTechnicalArtifact = - isLikelyFalsePositive || - isNonExistingDefaultBranchOfSwitch || - isRelatedToCompilationOfFinally - val localVariables = result.localsArray(pc) - val relevance = - if (isTechnicalArtifact) - Relevance.TechnicalArtifact - else if (isProvenAssertion) - Relevance.ProvenAssertion - else if (isLikelyIntendedDeadDefaultBranch) - Relevance.CommonIdiom - else if (isJustDeadPath) - Relevance.UselessDefensiveProgramming - else - Relevance.OfUtmostRelevance - - val summary = - if (isJustDeadPath) - s"dead path found; the direct runtime successor instruction is never immediately executed after this instruction: pc=$nextPC$line" - else - s"dead code found; the successor instruction is dead: pc=$nextPC$line" - issues ::= Issue( - "DeadEdgesAnalysis", - relevance, - summary, - Set(IssueCategory.Correctness), - Set(IssueKind.DeadPath), - List(new InstructionLocation( - Some( - "The evaluation of the instruction never leads to the evaluation of the specified instruction." + ( - if (isTechnicalArtifact) - "\n(This seems to be a technical artifact that cannot be avoided; i.e., there is nothing to fix.)" - else if (isProvenAssertion) - "\n(We seem to have proven that an assertion always holds (unless an exeption is throw).)" - else if (isLikelyIntendedDeadDefaultBranch) - "\n(This seems to be a deliberately dead default branch of a switch instruction; i.e., there is probably nothing to fix!)" - else - "" - ) - ), - theProject, - method, - pc, - List( - new Operands(body, pc, operands, localVariables), - new LocalVariables(body, pc, localVariables) - ) - )), - List( - new FieldValues(method, result), - new MethodReturnValues(method, result) - ) - ) - } - issues.sorted(IssueOrdering) - } - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/GuardedAndUnguardedAccessAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/GuardedAndUnguardedAccessAnalysis.scala deleted file mode 100644 index be839481a6..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/GuardedAndUnguardedAccessAnalysis.scala +++ /dev/null @@ -1,193 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.Domain -import org.opalj.ai.ValueOrigin -import org.opalj.ai.domain.RecordCFG -import org.opalj.ai.domain.l1.RecordAllThrownExceptions -import org.opalj.ai.domain.l1.ReferenceValues -import org.opalj.br.Method -import org.opalj.br.PC -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.AALOAD -import org.opalj.br.instructions.AASTORE -import org.opalj.br.instructions.ARRAYLENGTH -import org.opalj.br.instructions.GETFIELD -import org.opalj.br.instructions.IFNONNULL -import org.opalj.br.instructions.IFNULL -import org.opalj.br.instructions.IFXNullInstruction -import org.opalj.br.instructions.INVOKEINTERFACE -import org.opalj.br.instructions.INVOKESPECIAL -import org.opalj.br.instructions.INVOKEVIRTUAL -import org.opalj.br.instructions.MONITORENTER -import org.opalj.br.instructions.NEW -import org.opalj.br.instructions.PUTFIELD -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.IssueLocation -import org.opalj.issues.Relevance - -/** - * Identifies accesses to local reference variables that are once done in a guarded context - * (w.r.t. its nullness property; guarded by an if instruction) and that are also done in - * an unguarded context. - * - * This is only a very shallow analysis that is subject to false positives; to filter - * potential false positives we filter all those issues where we can identify a - * control and data-dependency to a derived value. E.g., - * {{{ - * def printSize(f : File) : Unit = { - * val name = if(f eq null) null else f.getName - * if(name == null) throw new NullPointerException; - * // here... f is not null; because if f is null at the beginning, name would be null to - * // and the method call would have returned abnormally (raised a NullPointerException). - * println(f.size) - * } - * }}} - * - * @author Michael Eichberg - */ -object GuardedAndUnguardedAccessAnalysis { - - type UnGuardedAccessAnalysisDomain = Domain with ReferenceValues with RecordCFG with RecordAllThrownExceptions - - def apply( - theProject: SomeProject, - method: Method, - result: AIResult { val domain: UnGuardedAccessAnalysisDomain } - ): List[Issue] = { - - import result.domain - val operandsArray = result.operandsArray - val code = result.code - - var origins = Map.empty[ValueOrigin, PC] - var refIds = Map.empty[domain.RefId, PC] - - // TODO We should also log those that are assertions related! - - for { - (pc, instr: IFXNullInstruction[?]) <- code - if operandsArray(pc) ne null - } { - - import code.instructions - import code.pcOfNextInstruction - // let's check if the guard is related to an assert statement - val isAssertionRelated: Boolean = - (instr match { - case _: IFNONNULL => Some(instructions(pcOfNextInstruction(pc))) - case IFNULL(branchOffset) => Some(instructions(pc + branchOffset)) - case _ => None - }) match { - case Some(NEW(AssertionError)) => true - case _ => false - } - - if (!isAssertionRelated) - operandsArray(pc).head match { - case domain.DomainSingleOriginReferenceValue(sov) => - origins += ((sov.origin, pc)) - refIds += ((sov.refId, pc)) - case domain.DomainMultipleReferenceValues(mov) => - refIds += ((mov.refId, pc)) - } - - } - - if (origins.isEmpty && refIds.isEmpty) - // we don't have any "guard instructions" - return List.empty; - - val unguardedAccesses = - for { - (pc, domain.AReferenceValue(receiver)) <- code.collectWithIndex { - case (pc, ARRAYLENGTH | MONITORENTER) if operandsArray(pc) != null => - (pc, operandsArray(pc).head) - - case (pc, AASTORE) if operandsArray(pc) != null => - (pc, operandsArray(pc)(2)) - - case (pc, AALOAD) if operandsArray(pc) != null => - (pc, operandsArray(pc)(1)) - - case (pc, _: GETFIELD) if operandsArray(pc) != null => - (pc, operandsArray(pc).head) - - case (pc, _: PUTFIELD) if operandsArray(pc) != null => - (pc, operandsArray(pc)(1)) - - case (pc, i: INVOKEVIRTUAL) if operandsArray(pc) != null => - (pc, operandsArray(pc)(i.methodDescriptor.parametersCount)) - - case (pc, i: INVOKEINTERFACE) if operandsArray(pc) != null => - (pc, operandsArray(pc)(i.methodDescriptor.parametersCount)) - - case (pc, i: INVOKESPECIAL) if operandsArray(pc) != null => - (pc, operandsArray(pc)(i.methodDescriptor.parametersCount)) - } - if receiver.isNull.isUnknown - if refIds.contains(receiver.refId) || - (receiver.isInstanceOf[domain.SingleOriginValue] && - origins.contains(receiver.asInstanceOf[domain.SingleOriginValue].origin)) - } yield { - if (refIds.contains(receiver.refId)) - ( - refIds(receiver.refId), - Relevance.OfUtmostRelevance, - pc - ) - else - ( - origins(receiver.asInstanceOf[domain.SingleOriginValue].origin), - Relevance.High, - pc - ) - } - - val unguardedAccessesIssues = - for { - (guardPC, unguardedAccesses) <- unguardedAccesses.groupBy(f => f._1 /*by guard*/ ) - } yield { - val relevance = unguardedAccesses.toIterator.map(_._2.value).max - - val unguardedLocations: Seq[IssueLocation] = - unguardedAccesses.map { ua => - val unguardedAccessPC = ua._3 - new InstructionLocation( - Some("unguarded access"), - theProject, - method, - unguardedAccessPC - ) - }.toSeq - - val locations = - unguardedLocations :+ - new InstructionLocation( - Some("guard"), - theProject, - method, - guardPC - ) - - Issue( - "GuardedAndUnguardedAccessAnalysis", - Relevance(relevance), - "a local variable is accessed in a guarded (using an explicit check) and also in an unguarded context", - Set(IssueCategory.Correctness), - Set(IssueKind.UnguardedUse), - locations - ) - } - - unguardedAccessesIssues.toList - } - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ManualGarbageCollection.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ManualGarbageCollection.scala deleted file mode 100644 index 157e0dac26..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ManualGarbageCollection.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.br.ClassFile -import org.opalj.br.ClassType -import org.opalj.br.MethodDescriptor -import org.opalj.br.MethodWithBody -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.INVOKESTATIC -import org.opalj.br.instructions.INVOKEVIRTUAL -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Relevance - -/** - * This analysis reports calls to `java.lang.System/Runtime.gc()` that seem to be made - * manually in code outside the core of the JRE. - * - * Manual invocations of garbage collection are usually unnecessary and can lead to - * performance problems. This heuristic tries to detect such cases. - * - * @author Ralf Mitschke - * @author Peter Spieler - * @author Michael Eichberg - */ -object ManualGarbageCollection { - - def description: String = - "Reports methods outside of java.lang that explicitly invoke the garbage collector." - - /** - * Runs this analysis on the given project. - * - * @param project The project to analyze. - * @param parameters Options for the analysis. Currently unused. - * @return A list of reports, or an empty list. - */ - def apply(theProject: SomeProject, classFile: ClassFile): Iterable[Issue] = { - - import MethodDescriptor.NoArgsAndReturnVoid - - if (classFile.thisType.fqn.startsWith("java/lang")) - return Seq.empty; - - for { - method @ MethodWithBody(body) <- classFile.methods - (pc, gcCall) <- body.collectWithIndex { - case (pc, INVOKESTATIC(ClassType.System, false, "gc", NoArgsAndReturnVoid)) => - (pc, "System.gc()") - case (pc, INVOKEVIRTUAL(ClassType.Runtime, "gc", NoArgsAndReturnVoid)) => - (pc, "Runtime.gc()") - } - } yield Issue( - "ManualGarbageCollection", - Relevance.Low, - s"contains dubious call to $gcCall", - Set(IssueCategory.Performance), - Set(IssueKind.DubiousMethodCall), - List(new InstructionLocation(None, theProject, method, pc)) - ) - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ThrowsExceptionAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ThrowsExceptionAnalysis.scala deleted file mode 100644 index d7b34b8e17..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/ThrowsExceptionAnalysis.scala +++ /dev/null @@ -1,130 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.Domain -import org.opalj.ai.domain.RecordCFG -import org.opalj.ai.domain.l1.RecordAllThrownExceptions -import org.opalj.ai.domain.l1.ReferenceValues -import org.opalj.br.Method -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.ATHROW -import org.opalj.br.instructions.Instruction -import org.opalj.br.instructions.ReturnInstruction -import org.opalj.collection.immutable.Chain -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.LocalVariables -import org.opalj.issues.Operands -import org.opalj.issues.Relevance - -/** - * This analysis identifies those instructions (except of ATHROW) that always lead to an exception. - * - * @author Michael Eichberg - */ -object ThrowsExceptionAnalysis { - - type ThrowsExceptionAnalysisDomain = Domain with ReferenceValues with RecordCFG with RecordAllThrownExceptions - - def apply( - theProject: SomeProject, - method: Method, - result: AIResult { val domain: ThrowsExceptionAnalysisDomain } - ): Chain[Issue] = { - - val operandsArray = result.operandsArray - val domain = result.domain - val code = result.code - - // - // The analysis - // - - val exceptionThrowingInstructions = - code collectWithIndex { - case (pc, i: Instruction) - if operandsArray(pc) != null /* <=> i was executed */ && - i != ATHROW && !i.isInstanceOf[ReturnInstruction] /* <=> i may have regular successors */ && - domain.regularSuccessorsOf( - pc - ).isEmpty /* <=> but i actually does not have a regular successor */ && - ( - domain.exceptionHandlerSuccessorsOf(pc).nonEmpty || - domain.allThrownExceptions.get(pc).nonEmpty - ) => - (pc, i) - } - - // - // Post-Processing - // - - val exceptionIssues: Chain[Issue] = { - - for { (pc, instruction) <- exceptionThrowingInstructions } yield { - val operands = operandsArray(pc) - val exceptions = { - var allExceptions: Set[domain.DomainSingleOriginReferenceValue] = { - if (domain.allThrownExceptions.get(pc).nonEmpty) - Set.empty ++ domain.allThrownExceptions.get(pc).get - else - Set.empty - } - - domain.exceptionHandlerSuccessorsOf(pc).foreach { handlerPC => - operandsArray(handlerPC).head match { - case domain.DomainSingleOriginReferenceValue(sorv) => - allExceptions += sorv - case domain.DomainMultipleReferenceValues(morv) => - allExceptions ++= morv.values - } - } - allExceptions.map(_.upperTypeBound.head.toJava).mkString(", ") - } - - // If we have the case: - // "throw throwsException()", where throwsException always throws an - // exception then we don't want to report an issue. - val relevance = { - val code = method.body.get - val nextPC = code.pcOfNextInstruction(pc) - if (nextPC < code.instructions.size && code.instructions(nextPC) == ATHROW) - Relevance.CommonIdiom - else - Relevance.VeryHigh - } - Issue( - "ThrowsExceptionAnalysis", - relevance, - "evaluation will always lead to an exception", - Set(IssueCategory.Correctness), - Set(IssueKind.ThrowsException), - List(new InstructionLocation( - Some(s"evaluation of $instruction always throws: $exceptions"), - theProject, - method, - pc, - List( - new Operands( - code, - pc, - operands.take(instruction.numberOfPoppedOperands { x => ??? }), - result.localsArray(pc) - ), - new LocalVariables(code, pc, result.localsArray(pc)) - ) - )) - ) - } - } - - exceptionIssues - } - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedFields.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedFields.scala deleted file mode 100644 index 74d3b831c6..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedFields.scala +++ /dev/null @@ -1,119 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.br.ClassFile -import org.opalj.br.ClassType -import org.opalj.br.ConstantString -import org.opalj.br.analyses.FieldAccessInformation -import org.opalj.br.analyses.SomeProject -import org.opalj.br.analyses.StringConstantsInformation -import org.opalj.br.analyses.cg.TypeExtensibilityKey -import org.opalj.fpcf.PropertyStore -import org.opalj.issues.FieldLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Relevance -import org.opalj.log.GlobalLogContext -import org.opalj.log.OPALLogger - -/** - * Identifies fields (static or instance) that are not used and which are also not useable. - * - * @author Michael Eichberg - */ -object UnusedFields { - - def apply( - theProject: SomeProject, - propertyStore: PropertyStore, - fieldAccessInformation: FieldAccessInformation, - stringConstantsInformation: StringConstantsInformation, - classFile: ClassFile - ): Seq[Issue] = { - - val typeExtensibility = theProject.get(TypeExtensibilityKey) - - val candidateFields = classFile.fields.filterNot { field => - (field.isSynthetic) || - // These fields are inlined by compilers; hence, even if the field is not accessed - // it may be used in the source code. - (field.isFinal && (field.fieldType.isBaseType || field.fieldType == ClassType.String)) || - // The field is read at least once... - (fieldAccessInformation.readAccesses(field).nonEmpty) || - // We may have some users of the field in the future... - // IMPROVE use FutureFieldAccess property (TBD) to get the information if we may have future field accesses - (!field.isPrivate && AnalysisModes.isLibraryLike(theProject.analysisMode)) - } - - if (candidateFields.isEmpty) - return Nil; - - val unusedFields = candidateFields.filterNot { field => - // Test if the field defines a (probably inlined) constant string. - field.isFinal && (field.fieldType eq ClassType.String) && - { - field.constantFieldValue match { - case Some(ConstantString(value)) => - stringConstantsInformation.get(value).isDefined - case _ => - false - } - } - } - - val unusedAndNotReflectivelyAccessedFields = unusedFields.filterNot { field => - // Let's test if we can find: - // - the field's name, - // - or the simpleName followed by the field's name - // - or the fully qualified name followed by the field's name - // in the code; if so we assume that the field is reflectively accessed - // and we ignore it - val fieldName = field.name - stringConstantsInformation.get(fieldName).isDefined || { - val thisSimpleTypeName = classFile.thisType.simpleName.replace('$', '.') - val qualifiedFieldName = thisSimpleTypeName + '.' + fieldName - stringConstantsInformation.get(qualifiedFieldName).isDefined - } || { - val thisFullyQualifiedTypeName = classFile.thisType.toJava.replace('$', '.') - val fullyQualifiedFieldName = thisFullyQualifiedTypeName + '.' + fieldName - stringConstantsInformation.get(fullyQualifiedFieldName).isDefined - } - } - - val unusedAndUnusableFields = { - val analysisMode = theProject.analysisMode - if (AnalysisModes.isApplicationLike(analysisMode)) { - unusedAndNotReflectivelyAccessedFields - } else if (analysisMode == AnalysisModes.OPA) { - // Only private fields cannot be accessed by classes that access the currently - // analyzed library. - unusedAndNotReflectivelyAccessedFields.filter(_.isPrivate) - } else if (analysisMode == AnalysisModes.CPA) { - unusedAndNotReflectivelyAccessedFields.filter(f => - f.isPrivate || f.isPackagePrivate || { - f.isProtected && typeExtensibility(classFile.thisType).isNo - } - ) - } else { - val message = s"the analysis mode $analysisMode is unknown" - OPALLogger.error("unused fields analysis", message)(GlobalLogContext) - Nil - } - } - - for (unusedField <- unusedAndUnusableFields) yield { - Issue( - "UnusedField", - Relevance.DefaultRelevance, - s"the field ${unusedField.toJava} is unused", - Set(IssueCategory.Correctness, IssueCategory.Comprehensibility), - Set(IssueKind.UnusedField), - List(new FieldLocation(None, theProject, classFile, unusedField)) - ) - } - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedLocalVariables.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedLocalVariables.scala deleted file mode 100644 index 6083576ace..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedLocalVariables.scala +++ /dev/null @@ -1,288 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.Domain -import org.opalj.ai.analyses.cg.CallGraph -import org.opalj.ai.analyses.cg.CallGraphFactory -import org.opalj.ai.domain.RecordDefUse -import org.opalj.ai.domain.TheCode -import org.opalj.br.Method -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.ACONST_NULL -import org.opalj.br.instructions.BIPUSH -import org.opalj.br.instructions.DCONST_0 -import org.opalj.br.instructions.DCONST_1 -import org.opalj.br.instructions.FCONST_0 -import org.opalj.br.instructions.FCONST_1 -import org.opalj.br.instructions.FCONST_2 -import org.opalj.br.instructions.GETSTATIC -import org.opalj.br.instructions.ICONST_0 -import org.opalj.br.instructions.ICONST_1 -import org.opalj.br.instructions.ICONST_2 -import org.opalj.br.instructions.ICONST_3 -import org.opalj.br.instructions.ICONST_4 -import org.opalj.br.instructions.ICONST_5 -import org.opalj.br.instructions.ICONST_M1 -import org.opalj.br.instructions.IINC -import org.opalj.br.instructions.INVOKEINTERFACE -import org.opalj.br.instructions.INVOKESPECIAL -import org.opalj.br.instructions.INVOKESTATIC -import org.opalj.br.instructions.INVOKEVIRTUAL -import org.opalj.br.instructions.LCONST_0 -import org.opalj.br.instructions.LCONST_1 -import org.opalj.br.instructions.LDC -import org.opalj.br.instructions.LDC2_W -import org.opalj.br.instructions.LDC_W -import org.opalj.br.instructions.LoadConstantInstruction -import org.opalj.br.instructions.MethodInvocationInstruction -import org.opalj.br.instructions.SIPUSH -import org.opalj.br.instructions.StoreLocalVariableInstruction -import org.opalj.fpcf.EP -import org.opalj.fpcf.PropertyStore -import org.opalj.fpcf.properties.LBPure -import org.opalj.fpcf.properties.Purity -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.MethodLocation -import org.opalj.issues.Relevance -import org.opalj.log.OPALLogger - -/** - * Identifies unused local variables in non-synthetic methods. - * - * @author Michael Eichberg - */ -object UnusedLocalVariables { - - def apply( - theProject: SomeProject, - propertyStore: PropertyStore, - callGraph: CallGraph, - method: Method, - result: AIResult { val domain: Domain with TheCode with RecordDefUse } - ): Seq[Issue] = { - - if (method.isSynthetic) - return Nil; - - // - // - // IDENTIFYING RAW ISSUES; IN OTHER WORDS: "THE ANALYSIS" - // - // - - val operandsArray = result.operandsArray - val allUnused = result.domain.unused() - val unused = allUnused.withFilter { vo => - // IMPROVE Improve the identification of unused method parameters... check if future overridings are possible; if it already overrides a method where the parameter is used... - (vo < 0 && ( - ( - method.isPrivate && - !CallGraphFactory.isPotentiallySerializationRelated(method)(theProject.classHierarchy) - ) - ) || - method.isStatic) || - // filter unused local variables related to dead code... - // (we have another analysis for that) - (vo >= 0 && (operandsArray(vo) ne null)) - } - - if (unused.isEmpty) - return Nil; - - // - // - // POST PROCESSING ISSUES TO FILTER LIKELY FALSE POSITIVES - // - // - - val code = result.domain.code - val instructions = code.instructions - val implicitParameterOffset = if (!method.isStatic) 1 else 0 - - var issues = List.empty[Issue] - - // It may happen that a user defines a final local constant - // which is then used by the compiler whenever we have a - // reference in the code; in this case we actually have an unused - // local variable in the bytecode... - // E.g., given the following code: - // final int MAGIC = 12012; - // ... - // if (x == MAGIC) {...} - // then the value 12012 is then directly used in the comparison - // which makes the initial declaration (at the bytecode level) - // unused. - lazy val constantValues: Set[Any] = { - import code.collectInstructions - val allConstantsValues = collectInstructions { case LoadConstantInstruction(v) => v } - val constantValuesOnlyUsedOnces = allConstantsValues.groupBy(v => v).collect { - case (k, occurences) if occurences.tail.isEmpty => k - } - constantValuesOnlyUsedOnces.toSet - } - - unused foreach { vo => - var issue: String = null - var relevance: Relevance = Relevance.Undetermined - if (vo < 0) { - // we have to make sure that we do not create an issue report - // for instance methods that can be/are inherited - if (method.isStatic || - method.isPrivate || - // IMPROVE Check that in all other cases the method parameter is never used across all implementations of the method; only then report it. - method.name == "" - ) { - relevance = Relevance.High - if (vo == -1 && !method.isStatic) { - issue = "the self reference \"this\" is unused (the method could be static)" - } else { - val index = (-(vo + implicitParameterOffset)) - code.localVariable(0, index - 1) match { - case Some(lv) => issue = s"the parameter ${lv.name} is unused" - case None => issue = s"the $index. parameter is unused" - } - } - } - } else { - val instruction = instructions(vo) - - def defaultUnusedValueHandling(): Unit = { - val instructionDescription = instruction.toString(vo).replace("\n", "\\n") - issue = "the value of " + instructionDescription + " is not used" - relevance = Relevance.VeryHigh - } - - instruction.opcode match { - - case INVOKEVIRTUAL.opcode | INVOKEINTERFACE.opcode | - INVOKESTATIC.opcode | INVOKESPECIAL.opcode => - val invoke = instruction.asInstanceOf[MethodInvocationInstruction] - try { - val resolvedMethod: Iterable[Method] = callGraph.calls(method, vo) - // IMPROVE Use a more precise method to determine if a method has a side effect "pureness" is actually too strong. - if (resolvedMethod.exists(m => propertyStore(m, Purity.key) == EP(m, LBPure))) { - issue = "the return value of the call of " + invoke.declaringClass.toJava + - "{ " + - invoke.methodDescriptor.toJava(invoke.name) + - " } is not used" - relevance = Relevance.OfUtmostRelevance - } - } catch { - case b: Break[?] => throw b - case t: Throwable => - val message = "assessing analysis result failed; ignoring issue" - OPALLogger.error("error", message, t)(theProject.logContext) - } - - case ACONST_NULL.opcode | - ICONST_0.opcode | - ICONST_M1.opcode | - LCONST_0.opcode | - FCONST_0.opcode | - DCONST_0.opcode => - val nextPC = code.pcOfNextInstruction(vo) - instructions(nextPC) match { - case StoreLocalVariableInstruction((_, index)) => - // The typical pattern generated by a compiler if the - // value is used to set "some initial value" is that - // after pushing the constant value on the stack, the - // value is immediately stored in a register... - // - // final int i = 0 - // if (x == ...) i = j*1; else i = abc(); - // - - val lvOption = code.localVariable(nextPC, index) - if (lvOption.isDefined && lvOption.get.startPC < vo) { - issue = s"the constant value ${instruction.toString(vo)} is not used" - relevance = Relevance.Low - } - // else... we filter basically all issues unless we are sure that - // this is a real issue; i.e., - // - it is not a default value - // - it is not a final local variable - - case _ => - issue = "the constant value " + - instruction.toString(vo) + - "is (most likely) used to initialize a local variable" - relevance = Relevance.TechnicalArtifact - } - - case BIPUSH.opcode | SIPUSH.opcode | - ICONST_1.opcode | ICONST_2.opcode | ICONST_3.opcode | ICONST_4.opcode | ICONST_5.opcode | - LCONST_1.opcode | - DCONST_1.opcode | - FCONST_1.opcode | FCONST_2.opcode | - LDC.opcode | LDC_W.opcode | LDC2_W.opcode => - val LoadConstantInstruction(value) = instruction - if (constantValues.contains(value)) { - // => the value is only found once in the source code and - // the value is not used! - issue = "the constant " + - instruction.toString(vo).replace("\n", "\\n") + - " is not used" - relevance = Relevance.TechnicalArtifact - } - - case IINC.opcode => - issue = "the incremented value is not used" - relevance = Relevance.DefaultRelevance - - case GETSTATIC.opcode => - val GETSTATIC(_, _, fieldType) = instruction - if (fieldType.isClassType) { - val instr = instruction.toString(vo) - - theProject.classFile(fieldType.asClassType) match { - case Some(cf) => - if (cf.isEnumDeclaration) { - issue = s"the enum value $instr" + - "is (most likely) used to initialize a local variable" - relevance = Relevance.TechnicalArtifact - } else { - defaultUnusedValueHandling() - } - case None => - // we were not able to find the class - issue = s"the field value $instr is not used" - relevance = Relevance.DefaultRelevance - } - } else - defaultUnusedValueHandling() - - case _ => - defaultUnusedValueHandling() - } - - } - - if (issue ne null) { - issues ::= Issue( - "UnusedLocalVariables", - relevance, - issue, - Set(IssueCategory.Comprehensibility, IssueCategory.Correctness), - Set(IssueKind.UnusedLocalVariable), - List( - if (vo >= 0) - new InstructionLocation(None, theProject, method, vo) - else - new MethodLocation(None, theProject, method) - ) - ) - } - } - - issues - - } - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedMethodsAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedMethodsAnalysis.scala deleted file mode 100644 index f9ffdbfa91..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UnusedMethodsAnalysis.scala +++ /dev/null @@ -1,167 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.analyses.cg.ComputedCallGraph -import org.opalj.bi.VisibilityModifier -import org.opalj.br.Method -import org.opalj.br.MethodDescriptor -import org.opalj.br.VoidType -import org.opalj.br.analyses.SomeProject -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.MethodLocation -import org.opalj.issues.Relevance - -/** - * Identifies unused methods and constructors using the given call graph. - * - * @author Marco Jacobasch - * @author Michael Eichberg - */ -object UnusedMethodsAnalysis { - - /** - * Checks if the given method is used/is potentially useable. If the method is not used - * and is also not potentially useable by future clients, then an issue is created - * and returned. - * - * If any of the following conditions is true, the method is considered as being called. - * - The method is the target of a method call in the calculated call graph. - * - The method is a private (empty) default constructor in a final class. Such constructors - * are usually defined to avoid instantiations of the respective class. - * - The method is a private constructor in a final class that always throws an exception. - * Such constructors are usually defined to avoid instantiations of the - * respective class. E.g., - * `private XYZ(){throw new UnsupportedOperationException()` - * - The method is "the finalize" method. - */ - def apply( - theProject: SomeProject, - callgraph: ComputedCallGraph, - callgraphEntryPoints: Set[Method], - method: Method - ): Option[Issue] = { - - if (method.isSynthetic) - return None; - - if (method.name == "finalize" && (method.descriptor eq MethodDescriptor.NoArgsAndReturnVoid)) - return None; - - if (callgraphEntryPoints.contains(method)) - return None; - - def rateMethod(): Relevance = { - - val classFile = method.classFile - - import method.{isConstructor, isPrivate, actualArgumentsCount, descriptor, name} - import descriptor.returnType, parametersCount as declaredParametersCount - - // - // Let's handle some technical artifacts related methods... - // - if (name == "valueOf" && classFile.isEnumDeclaration) - return Relevance.Undetermined; - - // - // Let's handle the standard methods... - // - if ((name == "equals" && descriptor == ObjectEqualsMethodDescriptor) || - (name == "hashCode" && descriptor == ObjectHashCodeMethodDescriptor) - ) { - return Relevance.VeryLow; - } - - // - // Let's handle standard getter and setter methods... - // - if (name.length() > 3 && - ((name.startsWith("get") && returnType != VoidType && declaredParametersCount == 0) || - (name.startsWith("set") && returnType == VoidType && declaredParametersCount == 1)) && - { - val fieldNameCandidate = name.substring(3) - val fieldName = fieldNameCandidate.charAt(0).toLower + fieldNameCandidate.substring(1) - classFile.findField(fieldName).nonEmpty || - classFile.findField('_' + fieldName).nonEmpty || - classFile.findField('_' + fieldNameCandidate).nonEmpty - } - ) { - return Relevance.VeryLow; - } - - // - // IN THE FOLLOWING WE DEAL WITH CONSTRUCTORS - // - - // Let's check if it is a default constructor - // which was defined to avoid instantiations of the - // class (e.g., java.lang.Math) - val isPrivateDefaultConstructor = isConstructor && isPrivate && actualArgumentsCount == 1 /*this*/ - if (!isPrivateDefaultConstructor) - return Relevance.DefaultRelevance; - - val constructorsIterator = classFile.constructors - constructorsIterator.next // <= we always have at least one constructor in bytecode - if (constructorsIterator.hasNext) - // we have (among others) a default constructor that is not used - return Relevance.High; - - val body = method.body.get - val instructions = body.instructions - def justThrowsException: Boolean = { - !body.exists { (pc, i) => /* <= it just throws exceptions */ - i.isReturnInstruction - } - } - if (instructions.size == 5 /* <= default empty constructor */ ) - Relevance.TechnicalArtifact - else if (justThrowsException) - Relevance.CommonIdiom - else - Relevance.DefaultRelevance - } - - // - // - // THE ANALYSIS - // - // - - def unusedMethodOrConstructor: String = { - def access(flags: Int): String = - VisibilityModifier.get(flags) match { - case Some(visiblity) => visiblity.javaName.get - case _ => "/*default*/" - } - - val isConstructor = method.isConstructor - val accessFlags = access(method.accessFlags) - s"the $accessFlags ${if (isConstructor) "constructor" else "method"} is not used" - } - - val callers = callgraph.callGraph calledBy method - - if (callers.isEmpty) { - val relevance: Relevance = rateMethod() - if (relevance != Relevance.Undetermined) { - val issue = Issue( - "UnusedMethodsAnalysis", - relevance, - unusedMethodOrConstructor, - Set(IssueCategory.Comprehensibility), - Set(IssueKind.UnusedMethod), - List(new MethodLocation(None, theProject, method)) - ) - return Some(issue); - } - } - - None - } - -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessComputationsAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessComputationsAnalysis.scala deleted file mode 100644 index bcc6512ad1..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessComputationsAnalysis.scala +++ /dev/null @@ -1,174 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.Domain -import org.opalj.ai.collectPCWithOperands -import org.opalj.ai.domain.ConcreteIntegerValues -import org.opalj.ai.domain.ConcreteLongValues -import org.opalj.ai.domain.l1.ReferenceValues -import org.opalj.br.ComputationalTypeInt -import org.opalj.br.ComputationalTypeLong -import org.opalj.br.Method -import org.opalj.br.PC -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.IAND -import org.opalj.br.instructions.IINC -import org.opalj.br.instructions.INEG -import org.opalj.br.instructions.INSTANCEOF -import org.opalj.br.instructions.IOR -import org.opalj.br.instructions.LNEG -import org.opalj.br.instructions.ShiftInstruction -import org.opalj.br.instructions.StackBasedBinaryArithmeticInstruction -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Operands -import org.opalj.issues.Relevance - -/** - * Identifies computations that are useless (i.e., computations that could be done - * in the source code). - * - * @author Michael Eichberg - */ -object UselessComputationsAnalysis { - - type UselessComputationsAnalysisDomain = - Domain with ConcreteIntegerValues with ConcreteLongValues with ReferenceValues - - def apply( - theProject: SomeProject, - method: Method, - result: AIResult { val domain: UselessComputationsAnalysisDomain } - ): Seq[Issue] = { - - val defaultRelevance = Relevance.DefaultRelevance - val defaultIIncRelevance = Relevance(5) - - val code = result.code - - def createIssue(pc: PC, message: String, relevance: Relevance): Issue = { - val operands = result.operandsArray(pc) - val localVariables = result.localsArray(pc) - val details = new InstructionLocation( - None, - theProject, - method, - pc, - List(new Operands(code, pc, operands, localVariables)) - ) - Issue( - "UselessComputationsAnalysis", - relevance, - s"the expression ($message) always evaluates to the same value", - Set(IssueCategory.Comprehensibility, IssueCategory.Performance), - Set(IssueKind.ConstantComputation), - List(details) - ) - } - - import result.domain - import result.operandsArray - import domain.ConcreteIntegerValue - import domain.ConcreteLongValue - - collectPCWithOperands(domain)(code, operandsArray) { - - // IMPROVE Add support for identifying useless computations related to double and float values. - - // HANDLING INT VALUES - // - case ( - pc, - instr @ StackBasedBinaryArithmeticInstruction(ComputationalTypeInt), - Seq(ConcreteIntegerValue(a), ConcreteIntegerValue(b), _*) - ) => - // The java "~" operator has no direct representation in bytecode. - // Instead, compilers generate an "ixor" with "-1" as the - // second value. - if (instr.operator == "^" && a == -1) { - val message = s"constant computation: ~$b (<=> $b ${instr.operator} $a)." - createIssue(pc, message, defaultRelevance) - } else { - val message = s"constant computation: $b ${instr.operator} $a." - createIssue(pc, message, defaultRelevance) - } - - case (pc, IOR, Seq(ConcreteIntegerValue(0), _*)) => - createIssue(pc, "0 | x will always evaluate to x", Relevance.High) - case (pc, IOR, Seq(_, ConcreteIntegerValue(0), _*)) => - createIssue(pc, "x | 0 will always evaluate to x", Relevance.High) - case (pc, IOR, Seq(ConcreteIntegerValue(-1), _*)) => - createIssue(pc, "-1 | x will always evaluate to -1", Relevance.High) - case (pc, IOR, Seq(_, ConcreteIntegerValue(-1))) => - createIssue(pc, "x | -1 will always evaluate to -1", Relevance.High) - - case (pc, IAND, Seq(ConcreteIntegerValue(0), _*)) => - createIssue(pc, "0 & x will always evaluate to 0", Relevance.High) - case (pc, IAND, Seq(ConcreteIntegerValue(-1), _*)) => - createIssue(pc, "-1 & x will always evaluate to -1", Relevance.High) - case (pc, IAND, Seq(_, ConcreteIntegerValue(0), _*)) => - createIssue(pc, "x & 0 will always evaluate to 0", Relevance.High) - case (pc, IAND, Seq(_, ConcreteIntegerValue(-1), _*)) => - createIssue(pc, s"x & -1 will always evaluate to x", Relevance.High) - - case (pc, INEG, Seq(ConcreteIntegerValue(a), _*)) => - createIssue(pc, s"constant computation: -${a}", defaultRelevance) - - case ( - pc, - IINC(index, increment), - _ - ) if domain.intValueOption(result.localsArray(pc)(index)).isDefined => - val v = domain.intValueOption(result.localsArray(pc)(index)).get - val relevance = - if (increment == 1 || increment == -1) - defaultIIncRelevance - else - defaultRelevance - createIssue(pc, s"constant computation (inc): ${v} + $increment", relevance) - - // HANDLING LONG VALUES - // - case ( - pc, - instr @ StackBasedBinaryArithmeticInstruction(ComputationalTypeLong), - Seq(ConcreteLongValue(a), ConcreteLongValue(b), _*) - ) => - val message = s"constant computation: ${b}l ${instr.operator} ${a}l." - createIssue(pc, message, defaultRelevance) - case ( - pc, - instr @ ShiftInstruction(ComputationalTypeLong), - Seq(ConcreteLongValue(a), ConcreteIntegerValue(b), _*) - ) => - val message = s"constant computation: ${b}l ${instr.operator} ${a}l." - createIssue(pc, message, defaultRelevance) - - case (pc, LNEG, Seq(ConcreteLongValue(a), _*)) => - createIssue(pc, s"constant computation: -${a}l", defaultRelevance) - - // HANDLING REFERENCE VALUES - // - - case ( - pc, - INSTANCEOF(referenceType), - Seq(rv: domain.ReferenceValue, _*) - ) - if domain.intValueOption( - operandsArray(pc + INSTANCEOF.length).head - ).isDefined => - val utb = rv.upperTypeBound.map(_.toJava) - val targetType = " instanceof " + referenceType.toJava - val message = utb.mkString("useless type test: ", " with ", targetType) - createIssue(pc, message, defaultRelevance) - - } - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessReComputationsAnalysis.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessReComputationsAnalysis.scala deleted file mode 100644 index 2fbd3995a3..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/UselessReComputationsAnalysis.scala +++ /dev/null @@ -1,103 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core -package analyses - -import org.opalj.ai.AIResult -import org.opalj.ai.ValuesDomain -import org.opalj.ai.collectPCWithOperands -import org.opalj.ai.domain.ConcreteIntegerValues -import org.opalj.ai.domain.ConcreteLongValues -import org.opalj.ai.domain.TheCode -import org.opalj.br.Method -import org.opalj.br.analyses.SomeProject -import org.opalj.br.instructions.IStoreInstruction -import org.opalj.br.instructions.LStoreInstruction -import org.opalj.collection.immutable.:&: -import org.opalj.issues.InstructionLocation -import org.opalj.issues.Issue -import org.opalj.issues.IssueCategory -import org.opalj.issues.IssueKind -import org.opalj.issues.Operands -import org.opalj.issues.Relevance - -/** - * Identifies computations of primitive values that lead to the same result as a - * previous computation. Such computations (which could be a constant expression) - * are generally useless and hinder code comprehension. - * - * @author Michael Eichberg - */ -object UselessReComputationsAnalysis { - - def apply( - theProject: SomeProject, - method: Method, - result: AIResult { val domain: TheCode with ConcreteIntegerValues with ConcreteLongValues with ValuesDomain } - ): Seq[Issue] = { - - import result.domain.ConcreteIntegerValue - import result.domain.ConcreteLongValue - import result.domain - - if (!domain.code.localVariableTable.isDefined) - // This analysis requires debug information to increase the likelihood - // that we identify the correct local variable re-assignments. Otherwise - // we are not able to distinguish the reuse of a "register variable"/ - // local variable for a new/different purpose or the situation where - // the same variable is updated the second time using the same - // value. - return Seq.empty; - - val operandsArray = result.operandsArray - val localsArray = result.localsArray - val code = domain.code - - val methodsWithValueReassignment = - collectPCWithOperands(domain)(code, operandsArray) { - case ( - pc, - IStoreInstruction(index), - ConcreteIntegerValue(a) :&: _ - ) - if localsArray(pc) != null && - domain.intValueOption(localsArray(pc)(index)).map(_ == a).getOrElse(false) && - code.localVariable(pc, index).map(lv => lv.startPC < pc).getOrElse(false) => - (pc, index, a.toString) - - case ( - pc, - LStoreInstruction(index), - ConcreteLongValue(a) :&: _ - ) - if localsArray(pc) != null && - domain.longValueOption(localsArray(pc)(index)).map(_ == a).getOrElse(false) && - code.localVariable(pc, index).map(lv => lv.startPC < pc).getOrElse(false) => - (pc, index, a.toString) - } - - methodsWithValueReassignment.map { e => - val (pc, index, value) = e - val lv = code.localVariable(pc, index).get - val details = List(new Operands(code, pc, operandsArray(pc), localsArray(pc))) - val location = new InstructionLocation( - Some("useless (re-)assignment"), - theProject, - method, - pc, - details - ) - - Issue( - "UselessReevaluation", - Relevance.Low, - s"(re-)assigned the same value ($value) to the same variable (${lv.name})", - Set(IssueCategory.Comprehensibility), - Set(IssueKind.ConstantComputation), - List(location) - ) - - } - } -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/package.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/package.scala deleted file mode 100644 index ce53e57a1e..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/analyses/package.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker -package core - -import org.opalj.br.BooleanType -import org.opalj.br.ClassType -import org.opalj.br.IntegerType -import org.opalj.br.MethodDescriptor -import org.opalj.br.analyses.AnalysisException -import org.opalj.issues.Issue -import org.opalj.util.Nanoseconds - -/** - * Common constants and helper methods used by the BugPicker's analyses. - * - * @author Michael Eichberg - */ -package object analyses { - - type BugPickerResults = (Nanoseconds, Iterable[Issue], Iterable[AnalysisException]) - - final val AssertionError = ClassType.AssertionError - - final val ObjectEqualsMethodDescriptor = MethodDescriptor(ClassType.Object, BooleanType) - - final val ObjectHashCodeMethodDescriptor = MethodDescriptor.withNoArgs(IntegerType) -} diff --git a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/package.scala b/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/package.scala deleted file mode 100644 index d902da1b3b..0000000000 --- a/TOOLS/bp/src/main/scala/org/opalj/bugpicker/core/package.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package org.opalj -package bugpicker - -import scala.io.Source - -import org.opalj.io.process - -/** - * Common constants used by the BugPicker. - * - * @author Michael Eichberg - */ -package object core { - - def getAsset(path: String): String = { - process(getClass.getResourceAsStream(path)) { in => Source.fromInputStream(in).mkString } - } - - lazy val HTMLCSS: String = getAsset("html.css") - - lazy val HTMLJS: String = getAsset("html.js") - - lazy val SearchJS: String = getAsset("search.js") - - lazy val ReportCSS: String = getAsset("report.css") - - lazy val ReportJS: String = getAsset("report.js") - -} diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/AnonymousInnerClassShouldBeStatic.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/AnonymousInnerClassShouldBeStatic.jar deleted file mode 100644 index 6d675890a7..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/AnonymousInnerClassShouldBeStatic.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/BadlyOverriddenAdapter.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/BadlyOverriddenAdapter.jar deleted file mode 100644 index 32002ac21a..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/BadlyOverriddenAdapter.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/BitNops.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/BitNops.jar deleted file mode 100644 index 112806c02a..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/BitNops.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion.jar deleted file mode 100644 index 51a55b1e19..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/CatchesIllegalMonitorStateException.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/CatchesIllegalMonitorStateException.jar deleted file mode 100644 index b8ecbc5a67..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/CatchesIllegalMonitorStateException.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/CloneDoesNotCallSuperClone.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/CloneDoesNotCallSuperClone.jar deleted file mode 100644 index 027c304495..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/CloneDoesNotCallSuperClone.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/CnImplementsCloneButNotCloneable.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/CnImplementsCloneButNotCloneable.jar deleted file mode 100644 index 2dd60de8a0..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/CnImplementsCloneButNotCloneable.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantCompareTo.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantCompareTo.jar deleted file mode 100644 index 63cb916f1a..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantCompareTo.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantEquals.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantEquals.jar deleted file mode 100644 index 18027be961..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/CovariantEquals.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/DmRunFinalizersOnExit.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/DmRunFinalizersOnExit.jar deleted file mode 100644 index 93f34f0589..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/DmRunFinalizersOnExit.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/DoInsideDoPrivileged.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/DoInsideDoPrivileged.jar deleted file mode 100644 index 132d8bf206..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/DoInsideDoPrivileged.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/EqualsHashCodeContract.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/EqualsHashCodeContract.jar deleted file mode 100644 index 3f7876e8ce..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/EqualsHashCodeContract.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldIsntImmutableInImmutableClass.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/FieldIsntImmutableInImmutableClass.jar deleted file mode 100644 index d8aea804d7..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldIsntImmutableInImmutableClass.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBeFinal.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBeFinal.jar deleted file mode 100644 index d889ad8187..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBeFinal.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBePackageProtected.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBePackageProtected.jar deleted file mode 100644 index abc436ad31..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/FieldShouldBePackageProtected.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/FinalizeUseless.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/FinalizeUseless.jar deleted file mode 100644 index 0392c1b25d..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/FinalizeUseless.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/ImmutableClassInheritsMutableClass.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/ImmutableClassInheritsMutableClass.jar deleted file mode 100644 index c809257083..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/ImmutableClassInheritsMutableClass.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/ImplementsCloneableButNotClone.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/ImplementsCloneableButNotClone.jar deleted file mode 100644 index 78b4632a81..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/ImplementsCloneableButNotClone.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/InefficientToArray.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/InefficientToArray.jar deleted file mode 100644 index a66379e073..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/InefficientToArray.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations-license.txt b/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations-license.txt deleted file mode 100644 index 6cf3197fc5..0000000000 --- a/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations-license.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2013 Stephen Connolly. - * - * 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. - */ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations.jar deleted file mode 100644 index 1095b7b45d..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/JCIPAnnotations.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations-license.txt b/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations-license.txt deleted file mode 100644 index 043690f230..0000000000 --- a/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations-license.txt +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2005 Brian Goetz - * Released under the Creative Commons Attribution License - * (http://creativecommons.org/licenses/by/2.5) - * Official home: http://www.jcip.net - */ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations.jar deleted file mode 100644 index 8d65c3031b..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/JSR305Annotations.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/LongBitsToDoubleInvokedOnInt.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/LongBitsToDoubleInvokedOnInt.jar deleted file mode 100644 index 0feef9bd12..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/LongBitsToDoubleInvokedOnInt.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/ManualGarbageCollection.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/ManualGarbageCollection.jar deleted file mode 100644 index d92fb63a6a..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/ManualGarbageCollection.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/NativeMethodInImmutableClass.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/NativeMethodInImmutableClass.jar deleted file mode 100644 index 40d126863b..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/NativeMethodInImmutableClass.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/NonSerializableClassHasASerializableInnerClass.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/NonSerializableClassHasASerializableInnerClass.jar deleted file mode 100644 index f994516ba5..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/NonSerializableClassHasASerializableInnerClass.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/OwnAnnotations.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/OwnAnnotations.jar deleted file mode 100644 index 031cef548b..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/OwnAnnotations.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/ProtectedFieldInFinalClass.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/ProtectedFieldInFinalClass.jar deleted file mode 100644 index 1ed7e90866..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/ProtectedFieldInFinalClass.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/PublicFinalizeMethodShouldBeProtected.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/PublicFinalizeMethodShouldBeProtected.jar deleted file mode 100644 index 0263ec5496..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/PublicFinalizeMethodShouldBeProtected.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/Readme.txt b/TOOLS/bp/src/test/resources/classfiles/analyses/Readme.txt deleted file mode 100644 index 6eefcb8d05..0000000000 --- a/TOOLS/bp/src/test/resources/classfiles/analyses/Readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -JSR305Annotations implementation: -JSR 305: Annotations for Software Defect Detection in Java -http://code.google.com/p/jsr-305/ - -JCIPAnnotations implementation: - stephenc / jcip-annotations -https://github.com/stephenc/jcip-annotations diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/SerializableNoSuitableConstructor.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/SerializableNoSuitableConstructor.jar deleted file mode 100644 index ea117e7013..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/SerializableNoSuitableConstructor.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/SwingMethodInvokedInSwingThread.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/SwingMethodInvokedInSwingThread.jar deleted file mode 100644 index 3c9b82c7e9..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/SwingMethodInvokedInSwingThread.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/SyncSetUnsyncGet.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/SyncSetUnsyncGet.jar deleted file mode 100644 index aeecdb440b..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/SyncSetUnsyncGet.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/UninitializedFieldAccessDuringStaticInitialization.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/UninitializedFieldAccessDuringStaticInitialization.jar deleted file mode 100644 index 5ad6220233..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/UninitializedFieldAccessDuringStaticInitialization.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/UnusedPrivateFields.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/UnusedPrivateFields.jar deleted file mode 100644 index 7c45cafa6d..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/UnusedPrivateFields.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/UrUninitReadCalledFromSuperConstructor.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/UrUninitReadCalledFromSuperConstructor.jar deleted file mode 100644 index 42fe0a8fcb..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/UrUninitReadCalledFromSuperConstructor.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/classfiles/analyses/UselessIncrementInReturn.jar b/TOOLS/bp/src/test/resources/classfiles/analyses/UselessIncrementInReturn.jar deleted file mode 100644 index 52e2fafcbd..0000000000 Binary files a/TOOLS/bp/src/test/resources/classfiles/analyses/UselessIncrementInReturn.jar and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/empty.properties b/TOOLS/bp/src/test/resources/empty.properties deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/TOOLS/bp/src/test/resources/invalid-value-1.properties b/TOOLS/bp/src/test/resources/invalid-value-1.properties deleted file mode 100644 index 0063d56fa5..0000000000 --- a/TOOLS/bp/src/test/resources/invalid-value-1.properties +++ /dev/null @@ -1 +0,0 @@ -Analysis1 diff --git a/TOOLS/bp/src/test/resources/invalid-value-2.properties b/TOOLS/bp/src/test/resources/invalid-value-2.properties deleted file mode 100644 index d0448646c4..0000000000 --- a/TOOLS/bp/src/test/resources/invalid-value-2.properties +++ /dev/null @@ -1 +0,0 @@ -Analysis1=1 diff --git a/TOOLS/bp/src/test/resources/not-a-property-file.gif b/TOOLS/bp/src/test/resources/not-a-property-file.gif deleted file mode 100644 index 65c117ac79..0000000000 Binary files a/TOOLS/bp/src/test/resources/not-a-property-file.gif and /dev/null differ diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClass.java deleted file mode 100644 index 4769b52824..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClass.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package AnonymousInnerClassShouldBeStatic; - -/** - * Common example of how anonymous inner classes are used. The parent object is never - * referenced from the anonymous inner class, so it could have been made Static (and - * explicitly named instead of anonymous) to save memory. - * - * @author Daniel Klauer - */ -public class AnonymousInnerClass { - - void testAwtButton() { - java.awt.Button button = new java.awt.Button(); - button.addActionListener(new java.awt.event.ActionListener() { - - public void actionPerformed(java.awt.event.ActionEvent e) { - System.out.println("test"); - } - }); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClassAccessingOuterClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClassAccessingOuterClass.java deleted file mode 100644 index 62c0973ffd..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/AnonymousInnerClassAccessingOuterClass.java +++ /dev/null @@ -1,51 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package AnonymousInnerClassShouldBeStatic; - -/** - * Common examples of how anonymous inner classes are used. The parent object is - * referenced from the anonymous inner class, so it cannot be made `static`. - * - * @author Daniel Klauer - */ -public class AnonymousInnerClassAccessingOuterClass { - - private String message = "test"; - - void testCommonExample() { - java.awt.Button button = new java.awt.Button(); - button.addActionListener(new java.awt.event.ActionListener() { - - public void actionPerformed(java.awt.event.ActionEvent e) { - System.out.println(message); - } - }); - } - - class ReadOuterClassFieldInMethod { - - void test() { - System.out.println(message); - } - } - - class WriteOuterClassFieldInMethod { - - void test() { - message = "foo"; - } - } - - class ReadOuterClassFieldInConstructor { - - ReadOuterClassFieldInConstructor() { - System.out.println(message); - } - } - - class WriteOuterClassFieldInConstructor { - - WriteOuterClassFieldInConstructor() { - message = "foo"; - } - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/StaticInnerClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/StaticInnerClass.java deleted file mode 100644 index eb410e25e9..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/AnonymousInnerClassShouldBeStatic/StaticInnerClass.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package AnonymousInnerClassShouldBeStatic; - -/** - * "Fixed" version of AnonymousInnerClass. - * - * @author Daniel Klauer - */ -public class StaticInnerClass { - - static class MyEventHandler implements java.awt.event.ActionListener { - - public void actionPerformed(java.awt.event.ActionEvent e) { - System.out.println("test"); - } - } - - void testAwtButton() { - java.awt.Button button = new java.awt.Button(); - button.addActionListener(new MyEventHandler()); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapter.java deleted file mode 100644 index dc9445a054..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapter.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `KeyAdapter` but does not override its `keyTyped()` properly, - * because the signatures of the `keyTyped()` here is incompatible to that of - * `KeyAdapter`'s `keyTyped()`. This should be reported. - * - * @author Florian Brandherm - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class BadlyOverriddenKeyAdapter extends java.awt.event.KeyAdapter { - - public void keyTyped() { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapterWithOverload.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapterWithOverload.java deleted file mode 100644 index bfdbc123eb..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenKeyAdapterWithOverload.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `KeyAdapter` but does not override its `keyTyped()` properly, - * because the signatures of both `keyTyped()` overloads here are incompatible to that - * of `KeyAdapter`'s `keyTyped()`. This should be reported. - * - * @author Daniel Klauer - */ -public class BadlyOverriddenKeyAdapterWithOverload extends java.awt.event.KeyAdapter { - - public void keyTyped() { - } - - public void keyTyped(float arg0) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenMouseInputAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenMouseInputAdapter.java deleted file mode 100644 index 8cd6f0fca9..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/BadlyOverriddenMouseInputAdapter.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `MouseInputAdapter` but does not override `mouseClicked()` - * properly, because the signature of the `mouseClicked()` here is not compatible to that - * of `MouseInputAdapter`'s `mouseClicked()`. This should be reported. - * - * @author Florian Brandherm - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class BadlyOverriddenMouseInputAdapter extends javax.swing.event.MouseInputAdapter { - - public void mouseClicked(boolean arg0) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenKeyAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenKeyAdapter.java deleted file mode 100644 index 19803030fb..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenKeyAdapter.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `KeyAdapter` and properly overrides its `keyTyped()`. No - * report should be generated for this. - * - * @author Florian Brandherm - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class CorrectlyOverriddenKeyAdapter extends java.awt.event.KeyAdapter { - - @Override - public void keyTyped(java.awt.event.KeyEvent event) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenMouseInputAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenMouseInputAdapter.java deleted file mode 100644 index d5a9388a23..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/CorrectlyOverriddenMouseInputAdapter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `MouseInputAdapter` and correctly overrides its - * `mouseClicked()` method. No report should be generated for this. - * - * @author Florian Brandherm - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class CorrectlyOverriddenMouseInputAdapter extends - javax.swing.event.MouseInputAdapter { - - @Override - public void mouseClicked(java.awt.event.MouseEvent event) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/NotAnAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/NotAnAdapter.java deleted file mode 100644 index 3cfc6ef179..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/NotAnAdapter.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * Some class that is not related to any *Adapter classes at all. No problems should be - * detected here. - * - * @author Daniel Klauer - */ -public class NotAnAdapter { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload1CorrectlyOverridesKeyAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload1CorrectlyOverridesKeyAdapter.java deleted file mode 100644 index 9d399d751c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload1CorrectlyOverridesKeyAdapter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `KeyAdapter` and the 1st `keyTyped()` method here properly - * overrides `KeyAdapter`'s `keyTyped()`. No report should be generated for this. - * - * @author Daniel Klauer - */ -public class Overload1CorrectlyOverridesKeyAdapter extends java.awt.event.KeyAdapter { - - @Override - public void keyTyped(java.awt.event.KeyEvent event) { - } - - public void keyTyped(float arg0) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload2CorrectlyOverridesKeyAdapter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload2CorrectlyOverridesKeyAdapter.java deleted file mode 100644 index f1bbc7b111..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BadlyOverriddenAdapter/Overload2CorrectlyOverridesKeyAdapter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BadlyOverriddenAdapter; - -/** - * This class inherits from `KeyAdapter` and the 2nd `keyTyped()` method here properly - * overrides `KeyAdapter`'s `keyTyped()`. No report should be generated for this. - * - * @author Daniel Klauer - */ -public class Overload2CorrectlyOverridesKeyAdapter extends java.awt.event.KeyAdapter { - - public void keyTyped(float arg0) { - } - - @Override - public void keyTyped(java.awt.event.KeyEvent event) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/And.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/And.java deleted file mode 100644 index 3896ef946c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/And.java +++ /dev/null @@ -1,42 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * Various & (AND) no-ops, all of which should be reported by BitNops. - * - * @author Daniel Klauer - */ -public class And { - - int testZeroLhs(int r) { - int l = 0; - return l & r; - } - - int testZeroRhs(int l) { - int r = 0; - return l & r; - } - - int testZeroBoth() { - int l = 0; - int r = 0; - return l & r; - } - - int testMinusOneLhs(int r) { - int l = -1; - return l & r; - } - - int testMinusOneRhs(int l) { - int r = -1; - return l & r; - } - - int testMinusOneBoth() { - int l = -1; - int r = -1; - return l & r; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/FlagCollectionLoop.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/FlagCollectionLoop.java deleted file mode 100644 index 518ed65f6b..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/FlagCollectionLoop.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * A common construct for which BitNops should not produce false-positive reports: A loop - * that "collects" flags into a variable. During the first iteration, the OR operation - * will be a no-op, but in later iterations it won't be. - * - * @author Daniel Klauer - */ -public class FlagCollectionLoop { - - void test() { - int x = 0; - - for (int i = 0; i < 10; i++) { - x |= 1 << i; - } - - System.out.println(x); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPrivateField.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPrivateField.java deleted file mode 100644 index 01ce88c50b..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPrivateField.java +++ /dev/null @@ -1,19 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * Some AND/OR no-ops involving a `private` field as operand. Currently BitNops does not - * detect this case, but that may change in the future, if it can determine that the field - * is never written. - * - * @author Daniel Klauer - */ -public class InvolvingPrivateField { - - private int zero = 0; - - void test(int a) { - System.out.println(a | zero); - System.out.println(a & zero); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPublicField.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPublicField.java deleted file mode 100644 index 54926bc4df..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/InvolvingPublicField.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * Some AND/OR no-ops involving a `public` field as operand. The field may be altered at - * runtime, so our static analyses cannot detect any issues here. - * - * @author Daniel Klauer - */ -public class InvolvingPublicField { - - public int zero = 0; - - void test(int a) { - System.out.println(a | zero); - System.out.println(a & zero); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/Or.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/Or.java deleted file mode 100644 index 03bb8e5e63..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/Or.java +++ /dev/null @@ -1,42 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * Various | (OR) no-ops, all of which should be reported by BitNops. - * - * @author Daniel Klauer - */ -public class Or { - - int testZeroLhs(int r) { - int l = 0; - return l | r; - } - - int testZeroRhs(int l) { - int r = 0; - return l | r; - } - - int testZeroBoth() { - int l = 0; - int r = 0; - return l | r; - } - - int testMinusOneLhs(int r) { - int l = -1; - return l | r; - } - - int testMinusOneRhs(int l) { - int r = -1; - return l | r; - } - - int testMinusOneBoth() { - int l = -1; - int r = -1; - return l | r; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/UninterpretedInstructions.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/UninterpretedInstructions.java deleted file mode 100644 index 2cd2300763..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BitNops/UninterpretedInstructions.java +++ /dev/null @@ -1,21 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BitNops; - -/** - * A class with a method containing instructions that AI won't reach when using precise - * integer values. BitNops should not crash due to this. - * - * @author Daniel Klauer - */ -public class UninterpretedInstructions { - - public void test() { - int i = 0; - if (i == 0) { - } else { - // Unreachable code that won't be analyzed by AI - // (won't have operands information for these PCs) - i = i & 0; - } - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/NewIntegerToDoubleValue.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/NewIntegerToDoubleValue.java deleted file mode 100644 index 8dbc328cbc..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/NewIntegerToDoubleValue.java +++ /dev/null @@ -1,13 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BoxingImmediatelyUnboxedToPerformCoercion; - -/** - * @author Daniel Klauer - */ -public class NewIntegerToDoubleValue { - - void test() { - double d = new Integer(123).doubleValue(); - System.out.println(d); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/UnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/UnrelatedClass.java deleted file mode 100644 index 31c3f9b2bb..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/BoxingImmediatelyUnboxedToPerformCoercion/UnrelatedClass.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package BoxingImmediatelyUnboxedToPerformCoercion; - -/** - * Some class that does not do any boxing/unboxing and should not be reported. - * - * @author Daniel Klauer - */ -public class UnrelatedClass { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/MissingSynchronized.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/MissingSynchronized.java deleted file mode 100644 index c3f610a0d0..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/MissingSynchronized.java +++ /dev/null @@ -1,63 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CatchesIllegalMonitorStateException; - -/** - * This is an example class which attempts to communicate with a thread using `wait()` and - * `notifyAll()`, but without using `synchronized()` blocks. - * - * This causes `IllegalMonitorStateException`s to be thrown at runtime, which are handled - * in try/catch blocks here to prevent the program from terminating which is what someone - * who does not know about this issue might do. Instead of doing this, the code that leads - * to this exception being thrown should be fixed. - * - * @author Daniel Klauer - */ -public class MissingSynchronized { - - private String lock = "some object used as lock"; - - Thread thread = new Thread(new Runnable() { - - public void run() { - System.out.println("hello from thread! waking up parent..."); - try { - // Without the proper synchronized(lock) block, this will throw a - // IllegalMonitorStateException. - lock.notifyAll(); - } catch (IllegalMonitorStateException e) { - // Wrongly catch the IllegalMonitorStateException, and potentially even - // ignore it, instead of fixing the bug above. - System.out.println("IllegalMonitorStateException caught..."); - } - } - }); - - void test() { - System.out.println("starting thread..."); - thread.start(); - - System.out.println("waiting for thread to start..."); - try { - // Without the proper synchronized(lock) block, this will throw a - // IllegalMonitorStateException. - lock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (IllegalMonitorStateException e) { - // Wrongly catch the IllegalMonitorStateException, and potentially even - // ignore it, instead of fixing the bug above. - System.out.println("IllegalMonitorStateException caught..."); - } - - System.out.println("waiting for thread to exit..."); - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) { - new MissingSynchronized().test(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/ProperSynchronized.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/ProperSynchronized.java deleted file mode 100644 index e0d8c0a74a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/ProperSynchronized.java +++ /dev/null @@ -1,51 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CatchesIllegalMonitorStateException; - -/** - * Fixed version of MissingSynchronized. The `wait()` and `notifyAll()` calls are done - * from inside `synchronized()` blocks on the proper object. No reports should be - * generated here. - * - * @author Daniel Klauer - */ -public class ProperSynchronized { - - private String lock = "some object used as lock"; - - Thread thread = new Thread(new Runnable() { - - public void run() { - synchronized (lock) { - System.out.println("hello from thread! waking up parent..."); - lock.notifyAll(); - } - } - }); - - void test() { - synchronized (lock) { - System.out.println("starting thread..."); - thread.start(); - - System.out.println("waiting for thread to start..."); - try { - // Without the proper synchronized(lock) block, this will throw a - // IllegalMonitorStateException. - lock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - System.out.println("waiting for thread to exit..."); - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) { - new ProperSynchronized().test(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/UnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/UnrelatedClass.java deleted file mode 100644 index 8a3bceaedc..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CatchesIllegalMonitorStateException/UnrelatedClass.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CatchesIllegalMonitorStateException; - -/** - * Some class that has nothing to do with `IllegalMonitorStateException`s: It neither - * catches them nor has any `wait()` or `notifyAll()` calls that might trigger them. - * - * @author Daniel Klauer - */ -public class UnrelatedClass { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CloneWithoutCallToSuperClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CloneWithoutCallToSuperClone.java deleted file mode 100644 index cd26d5230c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CloneWithoutCallToSuperClone.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CloneDoesNotCallSuperClone; - -/** - * A class with a `clone()` method that does not have a call to `super.clone()`. This - * indicates a faulty `clone()` implementation. - * - * @author Daniel Klauer - */ -public class CloneWithoutCallToSuperClone implements Cloneable { - - @Override - protected Object clone() { - return new CloneWithoutCallToSuperClone(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CorrectlyImplementedClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CorrectlyImplementedClone.java deleted file mode 100644 index bf16feff76..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/CorrectlyImplementedClone.java +++ /dev/null @@ -1,24 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CloneDoesNotCallSuperClone; - -/** - * A class with a correctly implemented `clone()` method, including the call to - * `super.clone()`. This should not be reported. - * - * @author Daniel Klauer - */ -public class CorrectlyImplementedClone implements Cloneable { - - java.util.ArrayList mutableData = new java.util.ArrayList(); - - @Override - public Object clone() throws CloneNotSupportedException { - // Call super.clone() and down-cast result - CorrectlyImplementedClone copy = (CorrectlyImplementedClone) super.clone(); - - // Duplicate fields of this class as needed - copy.mutableData = new java.util.ArrayList(); - - return copy; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/SomeClassWithoutClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/SomeClassWithoutClone.java deleted file mode 100644 index a442306034..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CloneDoesNotCallSuperClone/SomeClassWithoutClone.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CloneDoesNotCallSuperClone; - -/** - * Some class without clone() method shouldn't be an issue for the analysis. - * - * @author Daniel Klauer - */ -public class SomeClassWithoutClone { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneAndCloneable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneAndCloneable.java deleted file mode 100644 index 2c178a9770..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneAndCloneable.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CnImplementsCloneButNotCloneable; - -/** - * A class that implements clone() and Cloneable. Implementing Cloneable isn't enforced by - * the compiler, but it's required by the Object.clone() contract. - * - * @author Daniel Klauer - */ -public class ImplementsCloneAndCloneable implements Cloneable { - - @Override - public Object clone() { - return new ImplementsCloneAndCloneable(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneButNotCloneable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneButNotCloneable.java deleted file mode 100644 index 35e6503dbe..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/ImplementsCloneButNotCloneable.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CnImplementsCloneButNotCloneable; - -/** - * A class that has a clone() method but does not implement Cloneable. This violates the - * Object.clone() contract. - * - * @author Daniel Klauer - */ -public class ImplementsCloneButNotCloneable { - - @Override - public Object clone() { - return new ImplementsCloneButNotCloneable(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/SomeClassWithoutClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/SomeClassWithoutClone.java deleted file mode 100644 index 04329970f1..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CnImplementsCloneButNotCloneable/SomeClassWithoutClone.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CnImplementsCloneButNotCloneable; - -/** - * Some class without clone() method shouldn't be an issue for the analysis. - * - * @author Daniel Klauer - */ -public class SomeClassWithoutClone { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithCovariantCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithCovariantCompareTo.java deleted file mode 100644 index d7de5394e3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithCovariantCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * A Comparable abstract class that does not implement the proper compareTo(Object) - * method, but rather a covariant one. - * - * This is bad practice: There should be a proper compareTo() which subclasses can - * override, rather than an incorrect one which may end up unused in practice: Subclasses - * are forced to implement the proper compareTo() by the compiler, but then they will - * override Comparable's compareTo(), instead of that of this abstract class. - * - * @author Daniel Klauer - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractComparableWithCovariantCompareTo implements Comparable { - - // Does not override Comparable.compareTo(Object) - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithMultipleCompareTo.java deleted file mode 100644 index 70746b8f70..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CovariantCompareTo; - -/** - * Abstract Comparable with multiple compareTo() methods, one of which is the correct one. - * Since the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractComparableWithMultipleCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(Object) - @Override - public int compareTo(Object o) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithProperCompareTo.java deleted file mode 100644 index 7fd0bda122..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractComparableWithProperCompareTo.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CovariantCompareTo; - -/** - * Comparable abstract class with proper compareTo() method: should not be reported. - * - * @author Daniel Klauer - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractComparableWithProperCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(Object) - @Override - public int compareTo(Object o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithCovariantCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithCovariantCompareTo.java deleted file mode 100644 index 3d0c46c1f5..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithCovariantCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * A generic Comparable abstract class that does not implement the proper compareTo(T) - * method, but rather a covariant one. - * - * This is bad practice: There should be a proper compareTo() which subclasses can - * override, rather than an incorrect one which may end up unused in practice: Subclasses - * are forced to implement the proper compareTo() by the compiler, but then they will - * override Comparable's compareTo(), instead of that of this abstract class. - * - * @author Daniel Klauer - */ -public abstract class AbstractGenericComparableWithCovariantCompareTo implements - Comparable { - - // Does not override Comparable.compareTo(T) - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithMultipleCompareTo.java deleted file mode 100644 index 919ef6e87a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,24 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Abstract Comparable with multiple compareTo() methods, one of which is the correct one. - * Since the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -public abstract class AbstractGenericComparableWithMultipleCompareTo implements - Comparable { - - // Properly overrides Comparable.compareTo(T) - @Override - public int compareTo(T o) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithProperCompareTo.java deleted file mode 100644 index 3c2e57e9f0..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractGenericComparableWithProperCompareTo.java +++ /dev/null @@ -1,19 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Generic Comparable abstract class with proper compareTo() method: should not be - * reported. - * - * @author Daniel Klauer - */ -public abstract class AbstractGenericComparableWithProperCompareTo implements - Comparable { - - // Properly overrides Comparable.compareTo(T) - @Override - public int compareTo(T o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithCovariantCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithCovariantCompareTo.java deleted file mode 100644 index aa24a10138..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithCovariantCompareTo.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CovariantCompareTo; - -/** - * An abstract class Comparable to itself, without implementing the proper compareTo() - * method. This is bad practice because now the derived classes must implement it. It - * would be better to have the implementation residing in this class, instead of spread - * out in one or multiple subclasses. - * - * Since there is a covariant compareTo() implemented here, we can assume the author did - * not want to run into the problem mentioned above. - * - * @author Daniel Klauer - */ -public abstract class AbstractSelfComparableWithCovariantCompareTo implements - Comparable { - - // Does not override compareTo(AbstractSelfCovariant) - public int compareTo(String v) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithMultipleCompareTo.java deleted file mode 100644 index afb88b9605..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Abstract self-Comparable with multiple compareTo() methods, one of which is the correct - * one. Since the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -public abstract class AbstractSelfComparableWithMultipleCompareTo implements - Comparable { - - @Override - public int compareTo(AbstractSelfComparableWithMultipleCompareTo v) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithProperCompareTo.java deleted file mode 100644 index 084e2f107f..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/AbstractSelfComparableWithProperCompareTo.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Self-Comparable abstract class with proper compareTo() method: should not be reported. - * - * @author Daniel Klauer - */ -public abstract class AbstractSelfComparableWithProperCompareTo implements - Comparable { - - @Override - public int compareTo(AbstractSelfComparableWithProperCompareTo v) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithMultipleCompareTo.java deleted file mode 100644 index 3a6437ab2f..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,24 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Comparable with multiple compareTo() methods, one of which is the correct one. Since - * the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -@SuppressWarnings("rawtypes") -public class ComparableWithMultipleCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(Object) - @Override - public int compareTo(Object o) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithProperCompareTo.java deleted file mode 100644 index 8bd36386ff..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ComparableWithProperCompareTo.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Comparable class with proper compareTo() method: should not be reported. - * - * @author Daniel Klauer - */ -@SuppressWarnings("rawtypes") -public class ComparableWithProperCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(Object) - @Override - public int compareTo(Object o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableAndOverrides.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableAndOverrides.java deleted file mode 100644 index e663b76e96..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableAndOverrides.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * This is a subclass of a proper Comparable class, and it properly overrides the parent's - * compareTo(). This should not be reported. - * - * @author Daniel Klauer - */ -public class ExtendsProperComparableAndOverrides extends ComparableWithProperCompareTo { - - @Override - public int compareTo(Object other) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithCovariantCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithCovariantCompareTo.java deleted file mode 100644 index 861622b997..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithCovariantCompareTo.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package CovariantCompareTo; - -/** - * This is a subclass of a proper Comparable class, but does not override the parent - * class' compareTo(). Instead there is a suspicious covariant compareTo() method. This - * case should be reported, because we can assume that the programmer intended to override - * the parent's compareTo() but just used the wrong parameter types accidentally. - * - * @author Daniel Klauer - */ -public class ExtendsProperComparableWithCovariantCompareTo extends - ComparableWithProperCompareTo { - - // Does not implement Comparable.compareTo(Object), - // but this could be intentional, so no report. - int compareTo(String other) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithoutOverriding.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithoutOverriding.java deleted file mode 100644 index 3404053a66..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/ExtendsProperComparableWithoutOverriding.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * This is a subclass of a proper Comparable class, but does not override the parent's - * compareTo(). We do not generate a report for this case because there are no suspicious - * covariant compareTo() methods. - * - * @author Daniel Klauer - */ -public class ExtendsProperComparableWithoutOverriding extends - ComparableWithProperCompareTo { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithMultipleCompareTo.java deleted file mode 100644 index e2f773b619..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Generic Comparable class with multiple compareTo() methods, one of which is the correct - * one. Since the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -public class GenericComparableWithMultipleCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(T) - @Override - public int compareTo(T o) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithProperCompareTo.java deleted file mode 100644 index 45dea32f91..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/GenericComparableWithProperCompareTo.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Generic Comparable class with proper compareTo() method: should not be reported. - * - * @author Daniel Klauer - */ -public class GenericComparableWithProperCompareTo implements Comparable { - - // Properly overrides Comparable.compareTo(T) - @Override - public int compareTo(T o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithMultipleCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithMultipleCompareTo.java deleted file mode 100644 index bf4b500e68..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithMultipleCompareTo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Self-Comparable with multiple compareTo() methods, one of which is the correct one. - * Since the correct compareTo() is not missing, we should not generate a report. - * - * @author Daniel Klauer - */ -public class SelfComparableWithMultipleCompareTo implements - Comparable { - - @Override - public int compareTo(SelfComparableWithMultipleCompareTo v) { - return 1; - } - - // This 2nd compareTo() should not cause a report - public int compareTo(String o) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithProperCompareTo.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithProperCompareTo.java deleted file mode 100644 index 49af247df8..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantCompareTo/SelfComparableWithProperCompareTo.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantCompareTo; - -/** - * Self-Comparable class with proper compareTo() method: should not be reported. - * - * @author Daniel Klauer - */ -public class SelfComparableWithProperCompareTo implements - Comparable { - - @Override - public int compareTo(SelfComparableWithProperCompareTo v) { - return 1; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenAndCovariantEqualsMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenAndCovariantEqualsMethod.java deleted file mode 100644 index 193afdd072..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenAndCovariantEqualsMethod.java +++ /dev/null @@ -1,21 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantEquals; - -/** - * A class with a proper `equals(Object)`, and also a covariant one. Since there's a - * correct `equals()`, we do not report the covariant one. - * - * @author Daniel Klauer - */ -public class CorrectlyOverriddenAndCovariantEqualsMethod { - - @Override - public boolean equals(Object other) { - return true; - } - - public boolean equals(String other) { - return true; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenEqualsMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenEqualsMethod.java deleted file mode 100644 index cdf74a8122..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CorrectlyOverriddenEqualsMethod.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantEquals; - -/** - * A class with a properly overridden `equals(Object)` and no other. This should not be - * reported. - * - * @author Daniel Klauer - */ -public class CorrectlyOverriddenEqualsMethod { - - @Override - public boolean equals(Object other) { - return true; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CovariantEqualsMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CovariantEqualsMethod.java deleted file mode 100644 index 6bbc171114..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/CovariantEqualsMethod.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantEquals; - -/** - * A class without proper `equals(Object)` but instead a covariant one. This should be - * reported. - * - * @author Daniel Klauer - */ -public class CovariantEqualsMethod { - - public boolean equals(String other) { - return true; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/NoEqualsMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/NoEqualsMethod.java deleted file mode 100644 index 5e63566d8f..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/CovariantEquals/NoEqualsMethod.java +++ /dev/null @@ -1,12 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package CovariantEquals; - -/** - * A class without any `equals()` method. This should neiter be reported nor cause trouble - * for the analysis. - * - * @author Daniel Klauer - */ -public class NoEqualsMethod { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/CallsRunFinalizersOnExit.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/CallsRunFinalizersOnExit.java deleted file mode 100644 index e144595d75..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/CallsRunFinalizersOnExit.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DmRunFinalizersOnExit; - -/** - * Invokes System.runFinalizersOnExit, an extremely dangerous method. - * - * @author Roberts Kolosovs - */ -public class CallsRunFinalizersOnExit { - - @SuppressWarnings("deprecation") - public void doStuff() { - System.runFinalizersOnExit(true); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/SomeUnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/SomeUnrelatedClass.java deleted file mode 100644 index 72eda1efc0..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DmRunFinalizersOnExit/SomeUnrelatedClass.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DmRunFinalizersOnExit; - -/** - * Some class that does not call System.runFinalizersOnExit() and shouldn't be an issue - * for the analysis. - * - * @author Daniel Klauer - */ -public class SomeUnrelatedClass { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleInsideDoPrivileged.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleInsideDoPrivileged.java deleted file mode 100644 index a9f36708a7..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleInsideDoPrivileged.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DoInsideDoPrivileged; - -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * Invokes setAccessible inside of doPrivileged. - * - * @author Florian Brandherm - */ -public class CallsSetAccessibleInsideDoPrivileged { - - ClassWithAField t = new ClassWithAField(); - - public void method() { - AccessController.doPrivileged(new PrivilegedAction() { - - public Void run() { - java.lang.reflect.Field[] fs = t.getClass().getDeclaredFields(); - for (java.lang.reflect.Field f : fs) { - f.setAccessible(true); - } - return null; - } - }); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleOutsideDoPrivileged.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleOutsideDoPrivileged.java deleted file mode 100644 index a7a5dd062a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/CallsSetAccessibleOutsideDoPrivileged.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DoInsideDoPrivileged; - -/** - * Invokes setAccessible outside of doPriviledged. - * - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class CallsSetAccessibleOutsideDoPrivileged { - - ClassWithAField t = new ClassWithAField(); - - public void method() { - java.lang.reflect.Field[] fs = t.getClass().getDeclaredFields(); - for (java.lang.reflect.Field f : fs) { - f.setAccessible(true); - } - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/ClassWithAField.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/ClassWithAField.java deleted file mode 100644 index 3e944c0f25..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/ClassWithAField.java +++ /dev/null @@ -1,13 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DoInsideDoPrivileged; - -/** - * Some class with a field for CallsSetAccessibleOutsideDoPrivileged to call - * setAccessible() on. - * - * @author Daniel Klauer - */ -public class ClassWithAField { - - public int field; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/UnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/UnrelatedClass.java deleted file mode 100644 index 091855b143..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/DoInsideDoPrivileged/UnrelatedClass.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package DoInsideDoPrivileged; - -/** - * A class without setAccessible() calls. It should not be reported. - * - * @author Daniel Klauer - */ -public class UnrelatedClass { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/ClassWithNeitherEqualsNorHashCode.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/ClassWithNeitherEqualsNorHashCode.java deleted file mode 100644 index b02c896841..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/ClassWithNeitherEqualsNorHashCode.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package EqualsHashCodeContract; - -/** - * A class with neither equals() nor hashCode(). It should not be reported. - * - * @author Daniel Klauer - */ -public class ClassWithNeitherEqualsNorHashCode { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/EqualsWithoutHashCode.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/EqualsWithoutHashCode.java deleted file mode 100644 index 13c6482de4..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/EqualsWithoutHashCode.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package EqualsHashCodeContract; - -/** - * Class with an equals() method but no hashCode() method. This breaks the equals/hashCode - * contract. - * - * @author Daniel Klauer - */ -public class EqualsWithoutHashCode { - - @Override - public boolean equals(Object other) { - return false; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/HashCodeWithoutEquals.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/HashCodeWithoutEquals.java deleted file mode 100644 index f8fbd64c01..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/EqualsHashCodeContract/HashCodeWithoutEquals.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package EqualsHashCodeContract; - -/** - * Class with a hashCode() method but no equals() method. This breaks the equals/hashCode - * contract. - * - * @author Daniel Klauer - */ -public class HashCodeWithoutEquals { - - @Override - public int hashCode() { - return 0; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/CustomAnnotatedWithTrivialMutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/CustomAnnotatedWithTrivialMutable.java deleted file mode 100644 index 2ecc32a87a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/CustomAnnotatedWithTrivialMutable.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import OwnAnnotations.Immutable; - -/** - * Some class annotated with a custom Immutable annotation and a trivial mutable field. - * This should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class CustomAnnotatedWithTrivialMutable { - - public int whatever; // trivial mutable -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithCyclicFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithCyclicFields.java deleted file mode 100644 index 47b997ab9b..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithCyclicFields.java +++ /dev/null @@ -1,21 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * This immutable class has classes with cyclic dependences as fields. This can cause the - * analysis to execute an infinite recursion and crash with a stack overflow error. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithCyclicFields { - - // The field classes contain each other as fields. - // This cycle can crash the analysis if not handled properly. - @SuppressWarnings("unused") - private MutableClassWithCyclicFieldsA foo = new MutableClassWithCyclicFieldsA(); - @SuppressWarnings("unused") - private MutableClassWithCyclicFieldsB bar = new MutableClassWithCyclicFieldsB(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDefensiveCopyOfUnknownClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDefensiveCopyOfUnknownClass.java deleted file mode 100644 index 3892fbb67c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDefensiveCopyOfUnknownClass.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Class defensively copying a class with fields of a type unknown to the analysis. As the - * analysis does not have enough information for an evaluation the unknown class is - * considered to be mutable and the defensive copy to be too shallow. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithDefensiveCopyOfUnknownClass { - - @SuppressWarnings("unused") - private MutableClassWithUnknownField foo; - - public JCIPAnnotatedWithDefensiveCopyOfUnknownClass(MutableClassWithUnknownField arg0) { - foo = new MutableClassWithUnknownField(arg0.foo); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDirectPublicSetter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDirectPublicSetter.java deleted file mode 100644 index 97fcf061d3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithDirectPublicSetter.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and an direct public setter for a - * private variable. This should get reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithDirectPublicSetter { - - @SuppressWarnings("unused") - private int x; - - // This method violates the immutability of the class. - public void setX(int y) { - x = y; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithIndirectPublicSetter.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithIndirectPublicSetter.java deleted file mode 100644 index ebffa9592c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithIndirectPublicSetter.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and an indirect public setter. This - * should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithIndirectPublicSetter { - - @SuppressWarnings("unused") - private int x; - - private void setX(int y) { - x = y; - } - - // Public method that indirectly sets x. - public void indirect(int a, int b) { - // With this x really isn't that immutable any more. - setX(a + b); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalArray.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalArray.java deleted file mode 100644 index 3966e04df1..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalArray.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some Class annotated with Immutable and a public final array. This should get reported, - * as Arrays are always mutable. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithMutablePublicFinalArray { - - // The ELements of the Array can still be changed, even if the Array is final. - public final int[] foo = { 1, 2, 3 }; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalField.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalField.java deleted file mode 100644 index ff56e0fc04..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithMutablePublicFinalField.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some Class annotated with Immutable and a mutable public final field. This should get - * reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithMutablePublicFinalField { - - // Field is a reference to a mutable type. final isn't enough to ensure immutability. - public final NotImmutableWithPublicFields mutable = new NotImmutableWithPublicFields(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTooShallowDefensiveCopy.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTooShallowDefensiveCopy.java deleted file mode 100644 index 3b3e1293a9..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTooShallowDefensiveCopy.java +++ /dev/null @@ -1,37 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and a defensive copy that is not - * deep enough. This should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithTooShallowDefensiveCopy { - - private final NotImmutableWithPublicFields foo = new NotImmutableWithPublicFields(1, - new int[] { 1, 2, 3 }); - private NotImmutableWithPublicFields[] bar = { - new NotImmutableWithPublicFields(1, new int[] { 1, 2, 3 }), - new NotImmutableWithPublicFields(2, new int[] { 1, 2, 3 }) }; - - public NotImmutableWithPublicFields getFoo() { - // No defensive copy for foo.foo, which it should have. - NotImmutableWithPublicFields v = new NotImmutableWithPublicFields(foo.x, foo.foo); - return v; - } - - public NotImmutableWithPublicFields[] getBar() { - NotImmutableWithPublicFields[] result = new NotImmutableWithPublicFields[bar.length]; - // The elements of the array are mutable. They should be defensively copied - // instead of being passed right through. - for (int i = 0; i < bar.length; i++) { - result[i] = bar[i]; - } - return result; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTrivialMutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTrivialMutable.java deleted file mode 100644 index 3d2c7b8518..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithTrivialMutable.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and a trivial mutable. This should - * get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithTrivialMutable { - - public int whatever; // trivial mutable -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopy.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopy.java deleted file mode 100644 index 77fea69504..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopy.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and without a defensive copy during - * output. This should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithoutDefensiveCopy { - - private final int[] foo = { 4, 2 }; - - // Here a defensive copy should be made. - public int[] getFoo() { - return foo; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopyAtInput.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopyAtInput.java deleted file mode 100644 index d99c1aa67b..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPAnnotatedWithoutDefensiveCopyAtInput.java +++ /dev/null @@ -1,26 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation and without a defensive copy during - * input. This should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPAnnotatedWithoutDefensiveCopyAtInput { - - // Final applies only to the array, and not to its elements. - @SuppressWarnings("unused") - private final int[] foo; - - // Here a defensive copy should be made, since the source of arg0 still has a - // reference to the array and can change its elements. - public JCIPAnnotatedWithoutDefensiveCopyAtInput(int[] args) { - // This is an error. - foo = args; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectlyImplementedImmutableClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectlyImplementedImmutableClass.java deleted file mode 100644 index c1bb1a6b22..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectlyImplementedImmutableClass.java +++ /dev/null @@ -1,95 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Some class annotated with JCIP Immutable annotation. Everything is implemented - * correctly. This should not be reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPCorrectlyImplementedImmutableClass { - - public final int foo = 0; - private NotImmutableWithPublicFields bar; - private String bum; - private int[] baz = { 1, 3, 3, 7 }; - private String[] werWohntHier = { "Das ", "ist ", "das ", "Haus ", "vom ", "Nikolaus" }; - - // Constructor calls the private setters. - public JCIPCorrectlyImplementedImmutableClass(NotImmutableWithPublicFields arg0, - int[] arg1, String arg2) { - setBum(arg2); - setBar(arg0); - setBaz(arg1); - setBazWithClone(arg1); - } - - // Setter for bar, only used by the constructor. No defensive copy needed, as strings - // are immutable. - private void setBum(String arg0) { - bum = arg0; - } - - // Getter for Bum. No defensive copy needed, as strings are immutable. - public String getBum() { - return bum; - } - - // Private setter for Bar with deep defensive copy by cloning. - private void setBar(NotImmutableWithPublicFields arg0) { - bar = new NotImmutableWithPublicFields(arg0.x, arg0.foo.clone()); - } - - // Public getter for bar, with deep defensive copy by cloning. - public NotImmutableWithPublicFields getBar() { - int[] arr = new int[bar.foo.length]; - for (int i = 0; i < arr.length; i++) { - arr[i] = bar.foo[i]; - } - NotImmutableWithPublicFields temp = new NotImmutableWithPublicFields(bar.x, arr); - return temp; - } - - // Setter for baz, only used by the constructor. Implemented with defensive copy. - private void setBaz(int[] arg0) { - int[] blub = new int[arg0.length]; - for (int i = 0; i < arg0.length; i++) { - blub[i] = arg0[i]; - } - baz = blub; - } - - // Setter for baz, with defensive copy by cloning. - private void setBazWithClone(int[] arg0) { - baz = arg0.clone(); - } - - // Public getter for WerWohntHier, with defensive copy by cloning. - public String[] getWerWohntHier() { - String[] out = werWohntHier.clone(); - return out; - } - - // Public getter for baz, implemented with defensive copy. - public int[] getBaz() { - int[] v = new int[baz.length]; - for (int i = 0; i < baz.length; i++) { - v[i] = baz[i]; - } - return v; - } - - // No member of the class is returned. No defensive copy is needed. - public NotImmutableWithPublicFields getParity() { - int[] retArray = { 1, 2 }; - if (bar.x % 2 == 0) { - return new NotImmutableWithPublicFields(1, retArray); - } else { - return new NotImmutableWithPublicFields(0, retArray); - } - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectyImplementationWithFactoryMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectyImplementationWithFactoryMethod.java deleted file mode 100644 index b44180a62e..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JCIPCorrectyImplementationWithFactoryMethod.java +++ /dev/null @@ -1,37 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Implements immutable class correctly with private constructors, and a factory method. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JCIPCorrectyImplementationWithFactoryMethod { - - private String foo; - - private JCIPCorrectyImplementationWithFactoryMethod() { - // Implemented to override the default construcor, so that this class cann now - // only be build with the factory method. - } - - private JCIPCorrectyImplementationWithFactoryMethod(String arg0) { - foo = arg0; - } - - public String getFoo() { - return foo; - } - - // This is the factory method to call the private construcor. - // The only way to get an instance of this class. - public static JCIPCorrectyImplementationWithFactoryMethod makeJCIPCorrectyImplementationWithFactoryMethod( - String arg0) { - return new JCIPCorrectyImplementationWithFactoryMethod(arg0); - } - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JSR305AnnotatedWithTrivialMutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JSR305AnnotatedWithTrivialMutable.java deleted file mode 100644 index af578eba5c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/JSR305AnnotatedWithTrivialMutable.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import javax.annotation.concurrent.Immutable; - -/** - * Some class annotated with JSR305 and a trivial mutable field. This should get reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Immutable -public class JSR305AnnotatedWithTrivialMutable { - - public int whatever; // trivial mutable -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsA.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsA.java deleted file mode 100644 index 480f4a365a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsA.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -/** - * First mutable class used to form a cyclic dependence. - * - * @author Roberts Kolosovs - */ -public class MutableClassWithCyclicFieldsA { - - // MutableClassWithCyclicFieldsB contains this class as field. - @SuppressWarnings("unused") - private MutableClassWithCyclicFieldsB bar = new MutableClassWithCyclicFieldsB(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsB.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsB.java deleted file mode 100644 index bd4b682d0a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithCyclicFieldsB.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -/** - * Second mutable class used to form a cyclic dependence. - * - * @author Roberts Kolosovs - */ -public class MutableClassWithCyclicFieldsB { - - // MutableClassWithCyclicFieldsA contains this class as field. - @SuppressWarnings("unused") - private MutableClassWithCyclicFieldsA foo = new MutableClassWithCyclicFieldsA(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithUnknownField.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithUnknownField.java deleted file mode 100644 index 2ee825bf1f..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/MutableClassWithUnknownField.java +++ /dev/null @@ -1,19 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -import FinalizeUseless.ClassWithoutExplicitFinalize; - -/** - * Class for testing handling of classes with missing class file in immutability analysis. - * - * @author Roberts Kolosovs - */ -public class MutableClassWithUnknownField { - - // The .jar containing this class is not loaded during testing. - public final ClassWithoutExplicitFinalize foo; - - public MutableClassWithUnknownField(ClassWithoutExplicitFinalize arg0) { - foo = arg0; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/NotImmutableWithPublicFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/NotImmutableWithPublicFields.java deleted file mode 100644 index cc41d15abc..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldIsntImmutableInImmutableClass/NotImmutableWithPublicFields.java +++ /dev/null @@ -1,26 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldIsntImmutableInImmutableClass; - -/** - * Some class with public Fields, but without an immutable annotation. This should not be - * reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -public class NotImmutableWithPublicFields { - - public int x; - public int[] foo; - - public NotImmutableWithPublicFields(int arg0, int[] arg1) { - x = arg0; - foo = arg1; - } - - public NotImmutableWithPublicFields() { - x = 5; - int[] temp = { 1, 2, 3, 4 }; - foo = temp; - }; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/SomeClassWithoutFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/SomeClassWithoutFields.java deleted file mode 100644 index e5d36f7ec5..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/SomeClassWithoutFields.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldShouldBeFinal; - -/** - * Some class without fields shouldn't be an issue for the analysis. - * - * @author Daniel Klauer - */ -public class SomeClassWithoutFields { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/VariousFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/VariousFields.java deleted file mode 100644 index 4630c4a067..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBeFinal/VariousFields.java +++ /dev/null @@ -1,39 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldShouldBeFinal; - -import java.util.Hashtable; - -/** - * @author Daniel Klauer - */ -public class VariousFields { - - /** - * These fields are final already, and they are just int/String, so they are - * definitely immutable, and should not be reported. - */ - public static final int int1 = 123; - public static final String s1 = "abc"; - - /** - * Both fields are non-final, and could be modified. They should be reported. - */ - public static int int2 = 123; - public static String s2 = "abc"; - - /** - * These fields are mutable despite being final, because they are not primitives. Only - * the reference is final, not the array content, etc. The analysis does not report - * these though. - */ - public static final int[] array1 = new int[10]; - public static final Hashtable hashtb1 = new Hashtable(); - - /** - * These fields are non-final, but should not be reported because they are not - * primitives. The analysis explicitly ignores arrays and hashtables to avoid - * detecting too many false-positives. - */ - public static int[] array2 = new int[10]; - public static Hashtable hashtb2 = new Hashtable(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/SomeClassWithoutFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/SomeClassWithoutFields.java deleted file mode 100644 index 353b952bd3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/SomeClassWithoutFields.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldShouldBePackageProtected; - -/** - * Some class without fields shouldn't be an issue for the analysis. - * - * @author Daniel Klauer - */ -public class SomeClassWithoutFields { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/VariousFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/VariousFields.java deleted file mode 100644 index d021a24df4..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FieldShouldBePackageProtected/VariousFields.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FieldShouldBePackageProtected; - -import java.util.Hashtable; - -/** - * @author Daniel Klauer - */ -public class VariousFields { - - /** - * Both fields already are package-protected, no report. - */ - static final int[] array1 = new int[10]; - static final Hashtable hashtb1 = new Hashtable(); - - /** - * Both fields are public, so they should be reported. - */ - public static final int[] array2 = new int[10]; - public static final Hashtable hashtb2 = new Hashtable(); - - /** - * Both fields have primitive types that the analysis does not check, so no report. - */ - public static int int1 = 123; - public static String s1 = "abc"; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/ClassWithoutExplicitFinalize.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/ClassWithoutExplicitFinalize.java deleted file mode 100644 index f1c661e558..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/ClassWithoutExplicitFinalize.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FinalizeUseless; - -/** - * A class without explicit `finalize()` method. This should not be reported. - * - * @author Roberts Kolosovs - */ -public class ClassWithoutExplicitFinalize { - - private String s1 = "You may not see it but it is here."; - private String s2 = "The finalize. It can't be avoided."; - - public void foo() { - System.out.println(s1); - System.out.println(s2); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UsefulFinalize.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UsefulFinalize.java deleted file mode 100644 index 072b7cdba3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UsefulFinalize.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FinalizeUseless; - -/** - * A class with a `finalize()` that does more than just call `super.finalize()`. This - * should not be reported. - * - * @author Roberts Kolosovs - */ -public class UsefulFinalize { - - @Override - protected void finalize() throws Throwable { - System.out.println("So I will be running finalize now."); - System.out.println("Just so you are informed."); - System.out.println("Ok, finalize is about to run."); - System.out.println("I don't want to die..."); - super.finalize(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UselessFinalize.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UselessFinalize.java deleted file mode 100644 index 75f163ac07..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/FinalizeUseless/UselessFinalize.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package FinalizeUseless; - -/** - * A class with a useless finalize() method. Since it just calls super.finalize(), it may - * aswell have been omitted, which would have caused super.finalize() to be called - * directly. - * - * @author Daniel Klauer - */ -public class UselessFinalize { - - @Override - protected void finalize() throws Throwable { - super.finalize(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedImmutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedImmutable.java deleted file mode 100644 index cf05a0aace..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedImmutable.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImmutableClassInheritsMutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Immutable class. Should not be reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedImmutable { - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritingFromMutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritingFromMutable.java deleted file mode 100644 index b7d2101328..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritingFromMutable.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImmutableClassInheritsMutableClass; - -import ImmutableClassInheritsMutableClass.MutableClass; -import net.jcip.annotations.Immutable; - -/** - * In and off itself immutable class inherits from a mutable class. Thus it should be - * reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedInheritingFromMutable extends MutableClass { - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritsFromDirectImmutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritsFromDirectImmutable.java deleted file mode 100644 index e7dbeef634..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedInheritsFromDirectImmutable.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImmutableClassInheritsMutableClass; - -import net.jcip.annotations.Immutable; - -/** - * Immutable class inheriting from an immutable class. Should not be reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedInheritsFromDirectImmutable extends JCIPAnnotatedImmutable { - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedWithoutInheritance.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedWithoutInheritance.java deleted file mode 100644 index 9e96e45bb5..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/JCIPAnnotatedWithoutInheritance.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImmutableClassInheritsMutableClass; - -import ImmutableClassInheritsMutableClass.JCIPAnnotatedInheritingFromMutable; -import net.jcip.annotations.Immutable; - -/** - * Immutable class inherits from another immutable class. Should not be reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithoutInheritance extends JCIPAnnotatedInheritingFromMutable { - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/MutableClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/MutableClass.java deleted file mode 100644 index 811dba2635..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImmutableClassInheritsMutableClass/MutableClass.java +++ /dev/null @@ -1,26 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImmutableClassInheritsMutableClass; - -/** - * Some class with public Fields, but without an immutable annotation. This should not be - * reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -public class MutableClass { - - public int x; - public int[] foo; - - public MutableClass(int arg0, int[] arg1) { - x = arg0; - foo = arg1; - } - - public MutableClass() { - x = 5; - int[] temp = { 1, 2, 3, 4 }; - foo = temp; - }; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneAndCloneable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneAndCloneable.java deleted file mode 100644 index 4a1c09ddd3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneAndCloneable.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImplementsCloneableButNotClone; - -/** - * A class that implements Cloneable and overrides the clone() method. - * - * @author Daniel Klauer - */ -public class ImplementsCloneAndCloneable implements Cloneable { - - @Override - public Object clone() { - return new ImplementsCloneAndCloneable(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneableButNotClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneableButNotClone.java deleted file mode 100644 index 12202d9401..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/ImplementsCloneableButNotClone.java +++ /dev/null @@ -1,10 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImplementsCloneableButNotClone; - -/** - * A class that implements Cloneable but does not override the clone() method. - * - * @author Daniel Klauer - */ -public class ImplementsCloneableButNotClone implements Cloneable { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/SomeClassWithoutClone.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/SomeClassWithoutClone.java deleted file mode 100644 index 34978e7916..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ImplementsCloneableButNotClone/SomeClassWithoutClone.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ImplementsCloneableButNotClone; - -/** - * Some class without clone() method shouldn't be an issue for the analysis. - * - * @author Daniel Klauer - */ -public class SomeClassWithoutClone { - - void test() { - System.out.println("test\n"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/EfficientToArray.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/EfficientToArray.java deleted file mode 100644 index 6a97a80695..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/EfficientToArray.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package InefficientToArray; - -import java.util.ArrayList; - -/** - * Fixed version of InefficientToArray, should not be reported by the analysis. - * - * @author Daniel Klauer - */ -public class EfficientToArray { - - void test() { - ArrayList list = new ArrayList(); - - // Passing "new Integer[...]" to get the correct result type - // (Integer[]), - // because toArray() alone would return Object[]. - // - // Doing new Integer[list.size()] instead of new Integer[0] to allow - // toArray() to - // re-use - // that array to return the result, instead of having to allocate a new - // one. - @SuppressWarnings("unused") - Integer[] array = list.toArray(new Integer[list.size()]); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/InefficientToArray.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/InefficientToArray.java deleted file mode 100644 index feacf31895..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/InefficientToArray/InefficientToArray.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package InefficientToArray; - -import java.util.ArrayList; - -/** - * A class with a method using toArray() in an inefficient way. Should be reported by the - * analysis. - * - * @author Daniel Klauer - */ -public class InefficientToArray { - - void test() { - ArrayList list = new ArrayList(); - - // Passing "new Integer[0]" to get the correct result type (Integer[]), - // because toArray() alone would return Object[]. - @SuppressWarnings("unused") - Integer[] array = list.toArray(new Integer[0]); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/IntBitsToDouble.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/IntBitsToDouble.java deleted file mode 100644 index a3efbf8687..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/IntBitsToDouble.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package LongBitsToDoubleInvokedOnInt; - -/** - * A call to `Double.longBitsToDouble()` with `int` argument. This is dangerous; normally - * `Double.longBitsToDouble()` takes a `long` argument, as a `long` is needed to hold a - * `double`, while an `int` is too small. This should be reported. - * - * @author Daniel Klauer - */ -public class IntBitsToDouble { - - void test() { - int i = 0xAABBCCDD; - double d = Double.longBitsToDouble(i); - System.out.println(d); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/LongBitsToDouble.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/LongBitsToDouble.java deleted file mode 100644 index 1d3bf02ce3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/LongBitsToDoubleInvokedOnInt/LongBitsToDouble.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package LongBitsToDoubleInvokedOnInt; - -/** - * A call to Double.longBitsToDouble() with long argument. This is the correct usage and - * should not be reported. - * - * @author Daniel Klauer - */ -public class LongBitsToDouble { - - void test() { - long l = 0xAAAABBBBCCCCDDDDl; - double d = Double.longBitsToDouble(l); - System.out.println(d); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGc.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGc.java deleted file mode 100644 index 558f55da3b..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGc.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ManualGarbageCollection; - -/** - * A class that invokes Runtime.gc() from the main() method. This should be reported. - * - * @author Daniel Klauer - */ -public final class RuntimeGc { - - public static void main() { - java.lang.Runtime.getRuntime().gc(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGcIntentional.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGcIntentional.java deleted file mode 100644 index a924baabf7..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/RuntimeGcIntentional.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ManualGarbageCollection; - -/** - * A class that invokes Runtime.gc() in a method named gc(). The heuristic of the analysis - * should ignore this case because it seems intentional. - * - * @author Daniel Klauer - */ -public final class RuntimeGcIntentional { - - public static void gc() { - java.lang.Runtime.getRuntime().gc(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGc.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGc.java deleted file mode 100644 index 2b66ff96ee..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGc.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ManualGarbageCollection; - -/** - * A class that invokes System.gc() from the main() method. This should be reported. - * - * @author Daniel Klauer - */ -public final class SystemGc { - - public static void main() { - java.lang.System.gc(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGcIntentional.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGcIntentional.java deleted file mode 100644 index 426d8d36e4..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ManualGarbageCollection/SystemGcIntentional.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ManualGarbageCollection; - -/** - * A class that invokes System.gc() in a method named gc(). The heuristic of the analysis - * should ignore this case because it seems intentional. - * - * @author Daniel Klauer - */ -public final class SystemGcIntentional { - - public static void gc() { - java.lang.System.gc(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithNativeMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithNativeMethod.java deleted file mode 100644 index d6cf4137d7..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithNativeMethod.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package NativeMethodInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * This class is annotated as immutable and contains native code. This is a problem, as - * the native code may change the classes fields in unexpected ways. This should be - * reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithNativeMethod { - - // Field is immutable because of lack of setter - private int foo = 42; - - // Returning foo is allowed as it is a java primitive and thus passed by value. - public int getFoo() { - return foo; - } - - // This method may do anything. There is no easy way to know. We assume immutability - // to be violated. - public native void changeFoo(int v); - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithoutNativeMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithoutNativeMethod.java deleted file mode 100644 index 188a79556a..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/JCIPAnnotatedWithoutNativeMethod.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package NativeMethodInImmutableClass; - -import net.jcip.annotations.Immutable; - -/** - * This class in annotated as immutable and does not contain native methods. It should not - * be reported. - * - * @author Roberts Kolosovs - */ -@Immutable -public class JCIPAnnotatedWithoutNativeMethod { - - public final int foo = 42; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/NotImmutableWithPublicFields.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/NotImmutableWithPublicFields.java deleted file mode 100644 index acb3bb5f6e..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NativeMethodInImmutableClass/NotImmutableWithPublicFields.java +++ /dev/null @@ -1,26 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package NativeMethodInImmutableClass; - -/** - * Some class with public fields, but without an immutable annotation. This should not be - * reported. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -public class NotImmutableWithPublicFields { - - public int x; - public int[] foo; - - public NotImmutableWithPublicFields(int arg0, int[] arg1) { - x = arg0; - foo = arg1; - } - - public NotImmutableWithPublicFields() { - x = 5; - int[] temp = { 1, 2, 3, 4 }; - foo = temp; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/NonSerializableOuterClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/NonSerializableOuterClass.java deleted file mode 100644 index b5e3132746..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/NonSerializableOuterClass.java +++ /dev/null @@ -1,26 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package NonSerializableClassHasASerializableInnerClass; - -/** - * A non-Serializable outer class with various inner classes, some Serializable, some not. - * - * @author Daniel Klauer - */ -public class NonSerializableOuterClass { - - class SerializableInnerClass implements java.io.Serializable { - - private static final long serialVersionUID = 1l; - } - - class NonSerializableInnerClass { - } - - static class SerializableStaticInnerClass implements java.io.Serializable { - - private static final long serialVersionUID = 3l; - } - - static class NonSerializableStaticInnerClass { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/SerializableOuterClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/SerializableOuterClass.java deleted file mode 100644 index 1f66fd08c5..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/NonSerializableClassHasASerializableInnerClass/SerializableOuterClass.java +++ /dev/null @@ -1,24 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package NonSerializableClassHasASerializableInnerClass; - -/** - * A Serializable outer class with a non-Serializable inner class which has various inner - * classes itself, some Serializable, some not. - * - * @author Daniel Klauer - */ -public class SerializableOuterClass implements java.io.Serializable { - - private static final long serialVersionUID = 1l; - - class NonSerializableInnerClass { - - class SerializableInnerInnerClass implements java.io.Serializable { - - private static final long serialVersionUID = 1l; - } - - class NonSerializableInnerInnerClass { - } - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/OwnAnnotations/Immutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/OwnAnnotations/Immutable.java deleted file mode 100644 index f5fd8d8c0e..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/OwnAnnotations/Immutable.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package OwnAnnotations; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Our own Immutable annotation for test purposes. - * - * @author Roberts Kolosovs - * @author Peter Spieler - */ -@Target(TYPE) -@Retention(RUNTIME) -public @interface Immutable { - -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/PrivateInFinal.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/PrivateInFinal.java deleted file mode 100644 index 43a9a657cc..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/PrivateInFinal.java +++ /dev/null @@ -1,11 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ProtectedFieldInFinalClass; - -/** - * @author Daniel Klauer - */ -public final class PrivateInFinal { - - @SuppressWarnings("unused") - private int i = 1; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInFinal.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInFinal.java deleted file mode 100644 index 12c66020bc..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInFinal.java +++ /dev/null @@ -1,11 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ProtectedFieldInFinalClass; - -/** - * @author Daniel Klauer - */ -public final class ProtectedInFinal { - - // this could also be private since the class can not be inherited from - protected int i = 1; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInNonFinal.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInNonFinal.java deleted file mode 100644 index 6bb6091a35..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/ProtectedFieldInFinalClass/ProtectedInNonFinal.java +++ /dev/null @@ -1,10 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package ProtectedFieldInFinalClass; - -/** - * @author Daniel Klauer - */ -public class ProtectedInNonFinal { - - protected int i = 1; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/ProtectedFinalizeMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/ProtectedFinalizeMethod.java deleted file mode 100644 index 07d9240548..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/ProtectedFinalizeMethod.java +++ /dev/null @@ -1,16 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package PublicFinalizeMethodShouldBeProtected; - -/** - * This class contains a `protected` `finalize()` method. This is ok and should not be - * reported. - * - * @author Daniel Klauer - */ -public class ProtectedFinalizeMethod { - - @Override - protected void finalize() throws Throwable { - super.finalize(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/PublicFinalizeMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/PublicFinalizeMethod.java deleted file mode 100644 index d7e1c48d75..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/PublicFinalizeMethodShouldBeProtected/PublicFinalizeMethod.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package PublicFinalizeMethodShouldBeProtected; - -/** - * This class contains a `public` `finalize()` method. Because it is `public`, it can be - * called from the outside, at any time, which is not the intention of `finalize()`. This - * should be reported. - * - * @author Daniel Klauer - */ -public class PublicFinalizeMethod { - - @Override - public void finalize() throws Throwable { - super.finalize(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableInheritsFromNoSuitableConstructor.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableInheritsFromNoSuitableConstructor.java deleted file mode 100644 index e67ce1e9be..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableInheritsFromNoSuitableConstructor.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SerializableNoSuitableConstructor; - -/** - * This class implements java.io.Serializable and inherits from - * SerializableNoSuitableConstructor which does not have a zero-argument constructor, - * which however is required for Serializable. The superclass is supposed to be reported, - * but not this subclass. - * - * @author Roberts Kolosovs - */ -class SerializableInheritsFromNoSuitableConstructor extends - SerializableNoSuitableConstructor implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - public SerializableInheritsFromNoSuitableConstructor(int[] args) { - super(args); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableNoSuitableConstructor.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableNoSuitableConstructor.java deleted file mode 100644 index 8ced6a78d7..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SerializableNoSuitableConstructor/SerializableNoSuitableConstructor.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SerializableNoSuitableConstructor; - -/** - * This is a superclass of SerializableInheritsFromNoSuitableConstructor, which implements - * Serializable, but this superclass does not have a constructor with no arguments. Thus - * it should be reported. - * - * @author Roberts Kolosovs - */ -public class SerializableNoSuitableConstructor { - - public SerializableNoSuitableConstructor(int[] args) { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/BadSwingImplementation.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/BadSwingImplementation.java deleted file mode 100644 index b7e819c758..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/BadSwingImplementation.java +++ /dev/null @@ -1,31 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SwingMethodInvokedInSwingThread; - -import java.awt.BorderLayout; -import javax.swing.JButton; -import javax.swing.JFrame; - -/** - * Incorrectly implemented javax/swing functionality. The setVisible() function should be - * called in the event dispatching thread. Further information: - * http://en.wikipedia.org/wiki/Event_dispatching_thread Source code: - * http://web.archive.org/web/20090526170426/http://java.sun.com/developer - * /JDCTechTips/2003/tt1208.html#1 - * - * @author Daniel Klauer - * @author Roberts Kolosovs - */ -public class BadSwingImplementation { - - public static int main() { - JFrame frame = new JFrame(); - frame.setTitle("Title"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JButton button = new JButton(); - button.setText("Hello, World!"); - frame.getContentPane().add(button, BorderLayout.CENTER); - frame.setSize(200, 100); - frame.setVisible(true); // This should be called via EventQueue. - return 0; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/GoodSwingImplementation.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/GoodSwingImplementation.java deleted file mode 100644 index 71f467683c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/GoodSwingImplementation.java +++ /dev/null @@ -1,43 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SwingMethodInvokedInSwingThread; - -import java.awt.BorderLayout; -import java.awt.EventQueue; -import javax.swing.JButton; -import javax.swing.JFrame; - -/** - * Correctly implemented javax/swing functionality. The setVisible() function is called - * through invokeLater() function of the EventQueue. Source code: - * http://web.archive.org/web/20090526170426/http://java.sun.com/developer - * /JDCTechTips/2003/tt1208.html#1 - * - * @author Roberts Kolosovs - */ -public class GoodSwingImplementation { - - private static class FrameShower implements Runnable { - - final JFrame frame; - - public FrameShower(JFrame frame) { - this.frame = frame; - } - - public void run() { - frame.setVisible(true); - } - } - - public static void main(String args[]) { - JFrame frame = new JFrame(); - frame.setTitle("Title"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JButton button = new JButton(); - button.setText("Hello, World!"); - frame.getContentPane().add(button, BorderLayout.CENTER); - frame.setSize(200, 100); - Runnable runner = new FrameShower(frame); - EventQueue.invokeLater(runner); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/NoSwingUsed.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/NoSwingUsed.java deleted file mode 100644 index 046d7a4d6c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SwingMethodInvokedInSwingThread/NoSwingUsed.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SwingMethodInvokedInSwingThread; - -/** - * A class that does not use javax/swing functionality at all should not cause any issues - * for the analysis. - * - * @author Roberts Kolosovs - */ -public class NoSwingUsed { - - public int randomInt; - - private String randomString; - - public void setRandomString(String v) { - randomString = v; - } - - public String getRandomString() { - return randomString; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SyncSetUnsyncGet/VariousSettersAndGetters.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/SyncSetUnsyncGet/VariousSettersAndGetters.java deleted file mode 100644 index 3a078c8533..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/SyncSetUnsyncGet/VariousSettersAndGetters.java +++ /dev/null @@ -1,80 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package SyncSetUnsyncGet; - -/** - * A class with several setter/getter pairs. Some don't use synchronized at all, some use - * synchronized on both setter & getter, and some use synchronized only on the setter, but - * not the getter. - * - * @author Daniel Klauer - */ -public class VariousSettersAndGetters { - - /** - * s1 with synchronized setter, but unsynchronized getter (dangerous, this is an issue - * that FindRealBugs should report) - */ - private String a = ""; - - public synchronized void setA(String a) { - this.a = a; - } - - public String getA() { - return a; - } - - /** - * Same as above, but with different data type. - */ - private int b; - - public synchronized void setB(int b) { - this.b = b; - } - - public int getB() { - return b; - } - - /** - * Here, both setter and getter are synchronized, so there's no issue. - */ - private int c; - - public synchronized void setC(int c) { - this.c = c; - } - - public synchronized int getC() { - return c; - } - - /** - * Here, neither the setter nor the getter is synchronized. This should not be - * reported. - */ - private int d; - - public void setD(int d) { - this.d = d; - } - - public int getD() { - return d; - } - - /** - * Setter/getter pair where only the getter is synchronized. Currently this won't be - * reported. - */ - private int e; - - public void setE(int e) { - this.e = e; - } - - public synchronized int getE() { - return e; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/A.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/A.java deleted file mode 100644 index aabe12bba3..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/A.java +++ /dev/null @@ -1,155 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * Superclass in the A->B->C class hierarchy. All tests are based on the static - * initializer here in the superclass. - * - * @author Daniel Klauer - */ -public class A { - - // Direct access to subclass'es static field, should be reported. In the source code, - // this access appears in static initialization outside the `static { }` block, but - // when compiled it will also appear in ``, which is what the analysis - // analyzes. - static int A1 = B.B1; // uninitialized - static int A2 = C.C2; // uninitialized - - static int A20 = 42; - - static int A_getA20() { - return A20; - } - - static int A_getB21() { - return B.B21; - } - - static int A_getC22() { - return C.C22; - } - - static int A23 = 42; - static int A26 = 42; - static int A30 = 42; - - static int A_getA30() { - return A30; - } - - static int A_getA30_viaA() { - return A_getA30(); - } - - static int A_getB31() { - return B.B31; - } - - static int A_getB31_viaA() { - return A_getB31(); - } - - static int A32 = 42; - - static int A_getA32_viaB() { - return B.B_getA32(); - } - - static int A_getB33_viaB() { - return B.B_getB33(); - } - - static int A34 = 42; - - static int A_getA34() { - return A34; - } - - static int A_getB35() { - return B.B35; - } - - static int A36 = 42; - - // Static fields in the class and its subclasses may have the same name. That should - // not confuse the analysis though - it has to reference fields not only by name, but - // also by their declaring class. - static int samename1 = 42; - static int samename2 = 42; - - static int A50 = 42; - - static { - // Direct access - System.out.println(B.B3); // uninitialized - System.out.println(C.C4); // uninitialized - - // Various indirect accesses (1 level of indirection) - System.out.println(A_getA20()); // ok - System.out.println(A_getB21()); // uninitialized - System.out.println(A_getC22()); // uninitialized - System.out.println(B.B_getA23()); // ok - System.out.println(B.B_getB24()); // uninitialized - System.out.println(B.B_getC25()); // uninitialized - System.out.println(C.C_getA26()); // ok - System.out.println(C.C_getB27()); // uninitialized - System.out.println(C.C_getC28()); // uninitialized - - // Access to uninitialized field through 2 levels of indirection - System.out.println(A_getA30_viaA()); // ok - System.out.println(A_getB31_viaA()); // uninitialized - System.out.println(A_getA32_viaB()); // ok - System.out.println(A_getB33_viaB()); // uninitialized - System.out.println(B.B_getA34_viaA()); // ok - System.out.println(B.B_getB35_viaA()); // uninitialized - System.out.println(B.B_getA36_viaB()); // ok - System.out.println(B.B_getB37_viaB()); // uninitialized - - // Accessing this class'es static field first, it's initialized already. - // The following access to the subclass'es static field should still be detected - // as uninitialized access (but would not be if the analysis only checked fields - // based on their name). - System.out.println(samename1); // ok - System.out.println(B.samename1); // uninitialized - - // Accessing the subclass'es static field first, this is an uninitialized access. - // The following access to this class'es static field should not be mis-detected - // as uninitialized access (but would be if the analysis only checked fields - // based on their name). - System.out.println(B.samename2); // uninitialized - System.out.println(samename2); // ok - - // Direct access but through context other than the field's declaringClass, - // shouldn't confuse the analysis - System.out.println(B.A50); // ok - System.out.println(C.A50); // ok - System.out.println(C.B50); // uninitialized - - // Second access to an uninitialized field. Only the first access should be - // reported. - System.out.println(B.B60); // uninitialized - System.out.println(B.B60); // uninitialized, but ignored - - // Initializing a field manually prevents the uninitialized access - B.B70 = 42; - System.out.println(B.B70); // ok - A_initB71(); - System.out.println(B.B71); // ok - B.B_initB72(); - System.out.println(B.B72); // ok - } - - // Inner class that also is a subclass - static class InnerB extends A { - - static int InnerB40 = 42; - } - - static int A40 = InnerB.InnerB40; // uninitialized - - static void A_initB71() { - B.B71 = 42; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/B.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/B.java deleted file mode 100644 index 5d6bc6e8df..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/B.java +++ /dev/null @@ -1,82 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * Subclass in the A->B->C class hierarchy. - * - * @author Daniel Klauer - */ -public class B extends A { - - static int B1 = 42; - static int B3 = 42; - static int B21 = 42; - - static int B_getA23() { - return A23; - } - - static int B24 = 42; - - static int B_getB24() { - return B24; - } - - static int B_getC25() { - return C.C25; - } - - static int B27 = 42; - static int B31 = 42; - - static int B_getA32() { - return A32; - } - - static int B33 = 42; - - static int B_getB33() { - return B33; - } - - static int B_getA34_viaA() { - return A_getA34(); - } - - static int B35 = 42; - - static int B_getB35_viaA() { - return A_getB35(); - } - - static int B_getA36() { - return A36; - } - - static int B_getA36_viaB() { - return B_getA36(); - } - - static int B37 = 42; - - static int B_getB37() { - return B37; - } - - static int B_getB37_viaB() { - return B_getB37(); - } - - static int samename1 = 42; - static int samename2 = 42; - - static int B50 = 42; - static int B60 = 42; - static int B70 = 42; - static int B71 = 42; - static int B72 = 42; - - static void B_initB72() { - B72 = 42; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/C.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/C.java deleted file mode 100644 index f73de80460..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/C.java +++ /dev/null @@ -1,31 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * Subsubclass in the A->B->C class hierarchy. - * - * @author Daniel Klauer - */ -public class C extends B { - - static int C2 = 42; - static int C4 = 42; - static int C22 = 42; - static int C25 = 42; - - static int C_getA26() { - return A26; - } - - static int C_getB27() { - return B27; - } - - static int C28 = 42; - - static int C_getC28() { - return C28; - } - - static int C50 = 42; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/ClassUsesItself.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/ClassUsesItself.java deleted file mode 100644 index a2362dfe9c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/ClassUsesItself.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * A class that references itself during , and should not trigger reports. - * - * @author Daniel Klauer - */ -public class ClassUsesItself { - - public final static String text = "hello"; - - static { - // A GETSTATIC instruction during the static initializer. - System.out.println(text); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/CodePaths.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/CodePaths.java deleted file mode 100644 index f2ed664424..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/CodePaths.java +++ /dev/null @@ -1,106 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * This test covers the analysis' ability to track the code-path-specific initialization - * status of static fields. - * - * @author Daniel Klauer - */ -public class CodePaths { - - public static int condition10 = 0; - public static int condition11 = 0; - public static int condition12 = 0; - public static int condition20 = 0; - public static int condition21 = 0; - public static int condition22 = 0; - public static int condition30 = 0; - public static int condition31 = 0; - public static int condition40 = 0; - - static void test11() { - if (condition11 != 0) { - } else { - System.out.println(CodePathsSubclass.i11); // uninitialized - } - } - - static void test40() { - if (condition40 != 0) { - System.out.println(CodePathsSubclass.i40); // uninitialized - return; - } - - System.out.println(CodePathsSubclass.i40); // uninitialized - } - - static { - // Uninitialized access on only 1 of 2 code paths - if (condition10 != 0) { - System.out.println(CodePathsSubclass.i10); // uninitialized - } else { - } - - // same but in a subroutine - test11(); - - // Uninitialized accesses on both code paths - if (condition12 != 0) { - System.out.println(CodePathsSubclass.i12); // uninitialized - } else { - System.out.println(CodePathsSubclass.i12); // uninitialized - } - - // Field initialized manually, but only on 1 of 2 code paths, - // potentially causing an uninitialized access later - if (condition20 != 0) { - CodePathsSubclass.i20 = 1; - } - System.out.println(CodePathsSubclass.i20); // maybe uninitialized - - if (condition21 != 0) { - CodePathsSubclass.i21 = 1; - } else { - CodePathsSubclass.i21 = 2; - } - System.out.println(CodePathsSubclass.i21); // ok - - if (condition22 != 0) { - CodePathsSubclass.i22 = 1; - System.out.println(CodePathsSubclass.i22); // ok - } - - // Field initialized manually on one code path, - // and accessed uninitialized on the other. - if (condition30 != 0) { - CodePathsSubclass.i30 = 1; - } else { - System.out.println(CodePathsSubclass.i30); // uninitialized - // (if the analysis didn't track code paths, but just looked through - // instructions one by one, this would probably not be detected as an - // uninitialized access. - } - - if (condition31 != 0) { - System.out.println(CodePathsSubclass.i31); // uninitialized - } else { - CodePathsSubclass.i31 = 1; - } - - test40(); - } -} - -class CodePathsSubclass extends CodePaths { - - static int i10 = 42; - static int i11 = 42; - static int i12 = 42; - static int i20 = 42; - static int i21 = 42; - static int i22 = 42; - static int i30 = 42; - static int i31 = 42; - static int i40 = 42; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EmptyStaticInitializer.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EmptyStaticInitializer.java deleted file mode 100644 index cc5dc4c2d6..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EmptyStaticInitializer.java +++ /dev/null @@ -1,12 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * @author Daniel Klauer - */ -public class EmptyStaticInitializer { - - static { - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EnumUsesItself.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EnumUsesItself.java deleted file mode 100644 index 1670d8fb06..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/EnumUsesItself.java +++ /dev/null @@ -1,22 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * An enum that references itself during (due to the implicit code generated - * by Java, such as the values field), and should not trigger reports. - * - * @author Daniel Klauer - */ -public enum EnumUsesItself { - A("a"), B("b"), C("c"); - - private String text; - - private EnumUsesItself(String text) { - this.text = text; - } - - public String getText() { - return text; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/Recursion.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/Recursion.java deleted file mode 100644 index f6a578e0a6..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/Recursion.java +++ /dev/null @@ -1,34 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * The analysis must be able to deal with recursive calls when analyzing called methods, - * to avoid infinite recursion. - * - * @author Daniel Klauer - */ -public class Recursion { - - static void limitedRecursion(int i) { - if (i < 10) { - limitedRecursion(i + 1); - } - System.out.println(RecursionSubclass.i1); - } - - static void infiniteRecursion() { - infiniteRecursion(); - System.out.println(RecursionSubclass.i2); - } - - static { - limitedRecursion(0); - infiniteRecursion(); - } -} - -class RecursionSubclass extends Recursion { - - public static int i1 = 123; - public static int i2 = 123; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/StaticNativeMethod.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/StaticNativeMethod.java deleted file mode 100644 index c18ce0d4a4..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/StaticNativeMethod.java +++ /dev/null @@ -1,28 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * A class that calls a `static native` method during ``. This is special because - * references to `native` methods can be resolved, but they can still not be analyzed - * because they don't have known bodies. - * - * This test class must have a subclass with a static field, or else the analysis would - * simply skip it immediately. - * - * @author Daniel Klauer - */ -public class StaticNativeMethod { - - public static native int f(); - - static { - System.out.println(f()); - System.out.println(StaticNativeMethodSubclass.i); - } -} - -class StaticNativeMethodSubclass extends StaticNativeMethod { - - static int i = 123; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassA.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassA.java deleted file mode 100644 index fedc1a9fd8..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassA.java +++ /dev/null @@ -1,18 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ - -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * Invokes System.runFinalizersOnExit, an extremely dangerous method. - * - * @author Roberts Kolosovs - */ -public class UnrelatedControlClassA { - - @SuppressWarnings("deprecation") - public void doStuff() { - System.runFinalizersOnExit(true); - } - - static int bla = UnrelatedControlClassB.blubb; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassB.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassB.java deleted file mode 100644 index 5c023d6fae..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UninitializedFieldAccessDuringStaticInitialization/UnrelatedControlClassB.java +++ /dev/null @@ -1,20 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UninitializedFieldAccessDuringStaticInitialization; - -/** - * This class deliberately contains "useless" code to test checkers that search for it. - * - * It contains: - a finalize method that just calls super.finalize(); - * - * @author Michael Eichberg - */ -@SuppressWarnings("all") -public class UnrelatedControlClassB { - - @Override - protected void finalize() throws Throwable { - super.finalize(); - } - - static int blubb = 5; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Unused.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Unused.java deleted file mode 100644 index b05d1361ab..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Unused.java +++ /dev/null @@ -1,23 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UnusedPrivateFields; - -/** - * A class containing various unused private fields. - * - * @author Daniel Klauer - */ -@SuppressWarnings("unused") -public class Unused { - - // Normal field without initializer - private int a; - - // Normal field with a constant initializer - private int b = 111; - - // Final field with non-constant initializer - private final Unused c = new Unused(); - - // Final field with another constant initializer - private final int d = 222; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UnusedSerialVersionUID.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UnusedSerialVersionUID.java deleted file mode 100644 index a67a6f24ad..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UnusedSerialVersionUID.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UnusedPrivateFields; - -/** - * Class with an unused private serialVersionUID field. serialVersionUID is not special - * here, because this class is not Serializable, thus it should be reported. - * - * @author Daniel Klauer - */ -public class UnusedSerialVersionUID { - - @SuppressWarnings("unused") - private static final long serialVersionUID = 1L; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Used.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Used.java deleted file mode 100644 index 9e2632c357..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/Used.java +++ /dev/null @@ -1,102 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UnusedPrivateFields; - -/** - * A class containing various used private fields, testing that the analysis detects field - * accesses to normal instructions and handles the many special cases for final constant - * fields. - * - * @author Daniel Klauer - */ -public class Used { - - private int normali = 0; - - private final int im1 = -1; - private final int i0 = 0; - private final int i1 = 1; - private final int i2 = 2; - private final int i3 = 3; - private final int i4 = 4; - private final int i5 = 5; - private final int i6 = 6; - private final int i123 = 123; - - private final long lm1 = -1; - private final long l0 = 0; - private final long l1 = 1; - private final long l2 = 2; - private final long l3 = 3; - private final long l4 = 4; - private final long l5 = 5; - private final long l6 = 6; - private final long l123 = 123; - - private final float fm1 = -1; - private final float f0 = 0; - private final float f1 = 1; - private final float f2 = 2; - private final float f3 = 3; - private final float f4 = 4; - private final float f5 = 5; - private final float f6 = 6; - private final float f123 = 123; - - private final double dm1 = -1; - private final double d0 = 0; - private final double d1 = 1; - private final double d2 = 2; - private final double d3 = 3; - private final double d4 = 4; - private final double d5 = 5; - private final double d6 = 6; - private final double d123 = 123; - - private final String s = "abc"; - - void test() { - System.out.println(normali); - - System.out.println(im1); - System.out.println(i0); - System.out.println(i1); - System.out.println(i2); - System.out.println(i3); - System.out.println(i4); - System.out.println(i5); - System.out.println(i6); - System.out.println(i123); - - System.out.println(lm1); - System.out.println(l0); - System.out.println(l1); - System.out.println(l2); - System.out.println(l3); - System.out.println(l4); - System.out.println(l5); - System.out.println(l6); - System.out.println(l123); - - System.out.println(fm1); - System.out.println(f0); - System.out.println(f1); - System.out.println(f2); - System.out.println(f3); - System.out.println(f4); - System.out.println(f5); - System.out.println(f6); - System.out.println(f123); - - System.out.println(dm1); - System.out.println(d0); - System.out.println(d1); - System.out.println(d2); - System.out.println(d3); - System.out.println(d4); - System.out.println(d5); - System.out.println(d6); - System.out.println(d123); - - System.out.println(s); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedInInnerClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedInInnerClass.java deleted file mode 100644 index 0ea7d38770..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedInInnerClass.java +++ /dev/null @@ -1,35 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UnusedPrivateFields; - -/** - * Private fields unused in their own class, but used in an inner class. The analysis has - * to analyze inner classes too in order to detect this. - * - * @author Daniel Klauer - */ -public class UsedInInnerClass { - - // This field really is unused, it should be reported. - @SuppressWarnings("unused") - private final String reallyUnused = "reallyUnused"; - - // These fields however aren't unused -- they're used in inner classes, and should not - // be reported. - private final String usedByInner = "usedByInner"; - private final String usedByInnerInner = "usedByInnerInner"; - - class InnerClass { - - void test() { - System.out.println(usedByInner); - } - - class InnerInnerClass { - - void test() { - System.out.println(usedByInnerInner); - } - } - - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedSerialVersionUID.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedSerialVersionUID.java deleted file mode 100644 index 62b02ea5aa..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UnusedPrivateFields/UsedSerialVersionUID.java +++ /dev/null @@ -1,13 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UnusedPrivateFields; - -/** - * A Serializable class with a private serialVersionUID field. The serialVersionUID field - * is used by Serializable, and thus it should not be reported. - * - * @author Daniel Klauer - */ -class UsedSerialVersionUID implements java.io.Serializable { - - private static final long serialVersionUID = 1L; -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SubclassAccessedBySuperclassBeforeInit.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SubclassAccessedBySuperclassBeforeInit.java deleted file mode 100644 index 07b2b304a5..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SubclassAccessedBySuperclassBeforeInit.java +++ /dev/null @@ -1,25 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UrUninitReadCalledFromSuperConstructor; - -/** - * A subclass that is accessed by its superclass before it (the subclass) has been - * initialized. This can happen if the superclass accesses the subclass during its own - * initialization, because subclasses are initialized after superclasses. - * - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public class SubclassAccessedBySuperclassBeforeInit extends - SuperclassWithAccessToSubclassDuringInit { - - int i = 123; - - /** - * This method is called from the parent's constructor, but at that point, this child - * class' i field hasn't been initialized yet. - */ - @Override - void f() { - System.out.println(i); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SuperclassWithAccessToSubclassDuringInit.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SuperclassWithAccessToSubclassDuringInit.java deleted file mode 100644 index f402e43c99..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/SuperclassWithAccessToSubclassDuringInit.java +++ /dev/null @@ -1,17 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UrUninitReadCalledFromSuperConstructor; - -/** - * Abstract superclass for UrUninitReadCallFromSuperConstructor test - * - * @author Roberts Kolosovs - * @author Daniel Klauer - */ -public abstract class SuperclassWithAccessToSubclassDuringInit { - - abstract void f(); - - SuperclassWithAccessToSubclassDuringInit() { - f(); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/UnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/UnrelatedClass.java deleted file mode 100644 index d2a8536a06..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UrUninitReadCalledFromSuperConstructor/UnrelatedClass.java +++ /dev/null @@ -1,15 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UrUninitReadCalledFromSuperConstructor; - -/** - * Some class that neither accesses a subclass nor is accessed by its superclass during - * initialization. - * - * @author Daniel Klauer - */ -public class UnrelatedClass { - - public UnrelatedClass() { - System.out.println("test"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntFieldIncrementInReturn.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntFieldIncrementInReturn.java deleted file mode 100644 index 0ad286c23e..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntFieldIncrementInReturn.java +++ /dev/null @@ -1,37 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UselessIncrementInReturn; - -/** - * Various methods incrementing the int field during return instructions. - * - * In this case the increment is not useless, even though it happens as part of a return - * statement, because the resulting value is stored into the field, instead of being - * thrown away. Thus, none of these cases should trigger reports. - * - * @author Daniel Klauer - */ -public class IntFieldIncrementInReturn { - - int i = 0; - - int standaloneIncrement() { - i++; - return i; - } - - int intToIreturn() { - return i++; - } - - long intToLreturn() { - return i++; - } - - float intToFreturn() { - return i++; - } - - double intToDreturn() { - return i++; - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntParameterIncrementInReturn.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntParameterIncrementInReturn.java deleted file mode 100644 index 53ac896149..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/IntParameterIncrementInReturn.java +++ /dev/null @@ -1,33 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UselessIncrementInReturn; - -/** - * Various methods containing int increment and return instructions. The analysis should - * only report those cases where the increment appears in the return and thus is dead - * code. - * - * @author Daniel Klauer - */ -public class IntParameterIncrementInReturn { - - int standaloneIncrement(int i) { - i++; // should not be reported - return i; - } - - int intToIreturn(int i) { - return i++; // should be reported - } - - long intToLreturn(int i) { - return i++; // should be reported - } - - float intToFreturn(int i) { - return i++; // should be reported - } - - double intToDreturn(int i) { - return i++; // should be reported - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/UnrelatedClass.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/UnrelatedClass.java deleted file mode 100644 index d56ff38231..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/UselessIncrementInReturn/UnrelatedClass.java +++ /dev/null @@ -1,14 +0,0 @@ -/* BSD 2-Clause License - see OPAL/LICENSE for details. */ -package UselessIncrementInReturn; - -/** - * Some class that doesn't have any increment instruction. - * - * @author Daniel Klauer - */ -public class UnrelatedClass { - - public UnrelatedClass() { - System.out.println("test"); - } -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/GuardedBy.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/GuardedBy.java deleted file mode 100644 index 52500549eb..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/GuardedBy.java +++ /dev/null @@ -1,38 +0,0 @@ -package javax.annotation.concurrent; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* - * Copyright (c) 2005 Brian Goetz - * Released under the Creative Commons Attribution License - * (http://creativecommons.org/licenses/by/2.5) - * Official home: http://www.jcip.net - */ - -/** - * GuardedBy - * - * The field or method to which this annotation is applied can only be accessed when - * holding a particular lock, which may be a built-in (synchronization) lock, or may be an - * explicit java.util.concurrent.Lock. - * - * The argument determines which lock guards the annotated field or method: this : The - * string literal "this" means that this field is guarded by the class in which it is - * defined. class-name.this : For inner classes, it may be necessary to disambiguate - * 'this'; the class-name.this designation allows you to specify which 'this' reference is - * intended itself : For reference fields only; the object to which the field refers. - * field-name : The lock object is referenced by the (instance or static) field specified - * by field-name. class-name.field-name : The lock object is reference by the static field - * specified by class-name.field-name. method-name() : The lock object is returned by - * calling the named nil-ary method. class-name.class : The Class object for the specified - * class should be used as the lock object. - */ -@Target({ ElementType.FIELD, ElementType.METHOD }) -@Retention(RetentionPolicy.CLASS) -public @interface GuardedBy { - - String value(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/Immutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/Immutable.java deleted file mode 100644 index 6c4e170b0e..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/Immutable.java +++ /dev/null @@ -1,35 +0,0 @@ -package javax.annotation.concurrent; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* - * Copyright (c) 2005 Brian Goetz - * Released under the Creative Commons Attribution License - * (http://creativecommons.org/licenses/by/2.5) - * Official home: http://www.jcip.net - */ - -/** - * Immutable - * - * The class to which this annotation is applied is immutable. This means that its state - * cannot be seen to change by callers. Of necessity this means that all public fields are - * final, and that all public final reference fields refer to other immutable objects, and - * that methods do not publish references to any internal state which is mutable by - * implementation even if not by design. Immutable objects may still have internal mutable - * state for purposes of performance optimization; some state variables may be lazily - * computed, so long as they are computed from immutable state and that callers cannot - * tell the difference. - * - * Immutable objects are inherently thread-safe; they may be passed between threads or - * published without synchronization. - */ -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface Immutable { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/NotThreadSafe.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/NotThreadSafe.java deleted file mode 100644 index 764f951f02..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/NotThreadSafe.java +++ /dev/null @@ -1,30 +0,0 @@ -package javax.annotation.concurrent; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* - * Copyright (c) 2005 Brian Goetz - * Released under the Creative Commons Attribution License - * (http://creativecommons.org/licenses/by/2.5) - * Official home: http://www.jcip.net - */ - -/** - * NotThreadSafe - * - * The class to which this annotation is applied is not thread-safe. This annotation - * primarily exists for clarifying the non-thread-safety of a class that might otherwise - * be assumed to be thread-safe, despite the fact that it is a bad idea to assume a class - * is thread-safe without good reason. - * - * @see ThreadSafe - */ -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface NotThreadSafe { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/ThreadSafe.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/ThreadSafe.java deleted file mode 100644 index 06aed5aa61..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/javax/annotation/concurrent/ThreadSafe.java +++ /dev/null @@ -1,22 +0,0 @@ -package javax.annotation.concurrent; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * ThreadSafe - * - * The class to which this annotation is applied is thread-safe. This means that no - * sequences of accesses (reads and writes to public fields, calls to public methods) may - * put the object into an invalid state, regardless of the interleaving of those actions - * by the runtime, and without requiring any additional synchronization or coordination on - * the part of the caller. - */ -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface ThreadSafe { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/GuardedBy.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/GuardedBy.java deleted file mode 100644 index 1bd301e313..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/GuardedBy.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013 Stephen Connolly. - * - * 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 net.jcip.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * The presence of this annotation indicates that the field or method must only be - * accessed when holding the specified lock. - */ -@Documented -@Target(value = { FIELD, METHOD }) -@Retention(RUNTIME) -public @interface GuardedBy { - - /** - * The specified lock that guards the annotated field or method. Valid values are: - *
    - *
  • {@code this} indicates the intrinsic lock of the instance containing the field - * or method.
  • - *
  • class-name.this which allows for disambiguation of which - * {@code this} when dealing with inner classes
  • - *
  • {@code itself} which is valid for reference fields only, and indicates that the - * referenced instance's own intrinsic lock should be used as the guard
  • - *
  • field-name indicates the named instance or static field is - * to be used as the guard. If the field type is not a sub-type of - * {@link java.util.concurrent.locks.Lock} then the intrinsic lock of the referenced - * instance is to be used
  • - *
  • class-name.field-name indicates the named static - * field is to be used as the guard. If the field type is not a sub-type of - * {@link java.util.concurrent.locks.Lock} then the intrinsic lock of the referenced - * instance is to be used
  • - *
  • method-name() indicates that the zero-argument method - * should be called to obtain the lock object. If the return type is not a sub-type of - * {@link java.util.concurrent.locks.Lock} then the intrinsic lock of the returned - * instance is to be used
  • - *
  • class-name.class indicates that the intrinsic lock of the - * specified class should be used as the guard
  • - *
- * - * @return The specified lock that guards the annotated field or method - */ - String value(); -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/Immutable.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/Immutable.java deleted file mode 100644 index 5f027667b0..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/Immutable.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013 Stephen Connolly. - * - * 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 net.jcip.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * The presence of this annotation indicates that the author believes the class to be - * immutable and hence inherently thread-safe. An immutable class is one where the state - * of an instance cannot be seen to change. As a result - *
    - *
  • All public fields must be {@code final}
  • - *
  • All public final reference fields are either {@code null} or refer to other - * immutable objects
  • - *
  • Constructors and methods do not publish references to any potentially mutable - * internal state.
  • - *
- * Performance optimization may mean that instances of an immutable class may have mutable - * internal state. The critical point is that callers cannot tell the difference. For - * example {@link String} is an immutable class, despite having an internal int that is - * non-final but used as a cache for {@link String#hashCode()}. - *

- * Immutable objects are inherently thread-safe; they may be passed between threads or - * published without synchronization. - */ -@Documented -@Target(TYPE) -@Retention(RUNTIME) -public @interface Immutable { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/NotThreadSafe.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/NotThreadSafe.java deleted file mode 100644 index 9c35168c8f..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/NotThreadSafe.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 Stephen Connolly. - * - * 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 net.jcip.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * The presence of this annotation indicates that the author believes the class is not - * thread-safe. The absence of this annotation does not indicate that the class is - * thread-safe, instead this annotation is for cases where a naïve assumption could be - * easily made that the class is thread-safe. In general, it is a bad plan to assume a - * class is thread safe without good reason. - */ -@Documented -@Target(TYPE) -@Retention(RUNTIME) -public @interface NotThreadSafe { -} diff --git a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/ThreadSafe.java b/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/ThreadSafe.java deleted file mode 100644 index 3309a18e1c..0000000000 --- a/TOOLS/bp/src/test/resources/sourcefiles/analyses/net/jcip/annotations/ThreadSafe.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 Stephen Connolly. - * - * 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 net.jcip.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * The presence of this annotation indicates that the author believes the class to be - * thread-safe. As such, there should be no sequence of accessing the public methods or - * fields that could put an instance of this class into an invalid state, irrespective of - * any rearrangement of those operations by the Java Runtime and without introducing any - * requirements for synchronization or coordination by the caller/accessor. - */ -@Documented -@Target(TYPE) -@Retention(RUNTIME) -public @interface ThreadSafe { -} diff --git a/TOOLS/bp/src/test/resources/valid.properties b/TOOLS/bp/src/test/resources/valid.properties deleted file mode 100644 index 4a92f61f53..0000000000 --- a/TOOLS/bp/src/test/resources/valid.properties +++ /dev/null @@ -1,4 +0,0 @@ -Analysis1=yes -Analysis2=yes -Analysis3=no -Analysis4=yes diff --git a/build.sbt b/build.sbt index f620123fc1..9267a2ab21 100644 --- a/build.sbt +++ b/build.sbt @@ -177,7 +177,6 @@ lazy val `OPAL` = (project in file(".")) av, apk, framework, - // bp, (just temporarily...) tools, hermes, ce, @@ -414,19 +413,6 @@ lazy val `Framework` = (project in file("OPAL/framework")) ) .configs(IntegrationTest) -/* TEMPORARILY DISABLED THE BUGPICKER UNTIL WE HAVE A CG ANALYSIS AGAIN! -lazy val bp = `BugPicker` -lazy val `BugPicker` = (project in file("TOOLS/bp")) - .settings(buildSettings *) - .settings( - name := "BugPicker", - scalacOptions in(Compile, doc) ++= Opts.doc.title("OPAL - BugPicker"), - fork := true - ) - .dependsOn(framework % "it->it;it->test;test->test;compile->compile") - .configs(IntegrationTest) - */ - lazy val hermes = `Hermes` lazy val `Hermes` = (project in file("TOOLS/hermes")) @@ -519,7 +505,6 @@ lazy val `ConfigurationExplorer` = (project in file("TOOLS/ce")) br % "compile->compile", apk % "runtime->compile", demos % "runtime->compile", - // bp % "runtime->compile", hermes % "runtime->compile" ) .configs(IntegrationTest) diff --git a/src/site/UsingOPAL.md b/src/site/UsingOPAL.md index 5bd1d2e031..b6e6bb0d61 100644 --- a/src/site/UsingOPAL.md +++ b/src/site/UsingOPAL.md @@ -71,8 +71,3 @@ The architecture validation framework facilitates the development of tools for s Provides support for the analyis of APKs, with automatic conversion from dalvik to java byte code. libraryDependencies += "de.opal-project" % "apk_2.13" % "6.0.0" - - -[comment]: # "Exploring the Abstract Interpretation Framework" - -[comment]: # "To get a good, first idea what the abstract interpretation framework can do, you can use the *BugPicker*. It enables you to perform some local abstract interpretations. To get good results it is usually necessary to load the JDK and all related libraries." diff --git a/src/site/index.md b/src/site/index.md index 60a5b52c66..39f8263b1d 100644 --- a/src/site/index.md +++ b/src/site/index.md @@ -15,12 +15,6 @@ In-depth tutorials on developing static analyses with OPAL can be found in the n Publications about OPAL's core concepts and about uses of OPAL in scientific research, and information on **citing OPAL in scientific works** can be found [here](/Publications.html). -[comment]: ## "OPAL based Tools" - -[comment]: # "### BugPicker" - -[comment]: # "Find bugs in your Java project using [BugPicker](tools/bugpicker/index.php)." - ### OPAL Java Bytecode Disassembler OPAL's [Java Bytecode Disassembler](DeveloperTools.html) disassembles your Java bytecode.