Merge pull request #10628 from michaelnebel/java/typebasedmodels

Java: Type based summary models.
This commit is contained in:
Michael Nebel
2022-11-10 16:34:52 +01:00
committed by GitHub
54 changed files with 814 additions and 22 deletions

View File

@@ -6,8 +6,8 @@
import java
/**
* The type `t` is a parameterization of `g`, where the `i`-th type parameter of
* `g` is instantiated to `a`?
* Holds if the type `t` is a parameterization of `g`, where the `i`-th type parameter of
* `g` is instantiated to `arg`.
*
* For example, `List<Integer>` parameterizes `List<T>`, instantiating its `0`-th
* type parameter to `Integer`, while the raw type `List` also parameterizes

View File

@@ -195,6 +195,9 @@ class TypeVariable extends BoundedType, Modifiable, @typevariable {
result = this.getASuppliedType().(TypeVariable).getAnUltimatelySuppliedType()
}
/** Gets the index of `this` type variable. */
int getIndex() { typeVars(this, _, result, _, _) }
override string getAPrimaryQlClass() { result = "TypeVariable" }
}

View File

@@ -6,8 +6,8 @@
* @tags model-generator
*/
import internal.CaptureModels
import internal.CaptureSummaryFlow
import utils.modelgenerator.internal.CaptureModels
import utils.modelgenerator.internal.CaptureSummaryFlow
from DataFlowTargetApi api, string noflow
where noflow = captureNoFlow(api)

View File

@@ -6,7 +6,7 @@
* @tags model-generator
*/
import internal.CaptureModels
import utils.modelgenerator.internal.CaptureModels
class Activate extends ActiveConfiguration {
override predicate activateToSinkConfig() { any() }

View File

@@ -6,7 +6,7 @@
* @tags model-generator
*/
import internal.CaptureModels
import utils.modelgenerator.internal.CaptureModels
class Activate extends ActiveConfiguration {
override predicate activateFromSourceConfig() { any() }

View File

@@ -6,8 +6,8 @@
* @tags model-generator
*/
import internal.CaptureModels
import internal.CaptureSummaryFlow
import utils.modelgenerator.internal.CaptureModels
import utils.modelgenerator.internal.CaptureSummaryFlow
from DataFlowTargetApi api, string flow
where flow = captureFlow(api)

View File

@@ -0,0 +1,13 @@
/**
* @name Capture typed based summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id java/utils/model-generator/summary-models-typed-based
* @tags model-generator
*/
import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels
from TypeBasedFlowTargetApi api, string flow
where flow = captureFlow(api)
select flow order by flow

View File

@@ -67,6 +67,8 @@ private predicate isRelevantForModels(J::Callable api) {
*/
predicate isRelevantForDataFlowModels = isRelevantForModels/1;
predicate isRelevantForTypeBasedFlowModels = isRelevantForModels/1;
/**
* A class of Callables that are relevant for generating summary, source and sinks models for.
*
@@ -141,7 +143,7 @@ string asPartialNegativeModel(TargetApiSpecific api) {
)
}
private predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
t.hasName(["byte", "char", "Byte", "Character"])
}

View File

@@ -0,0 +1,330 @@
private import java
private import semmle.code.java.Collections
private import semmle.code.java.dataflow.internal.ContainerFlow
private import CaptureModelsSpecific as Specific
private import CaptureModels
/**
* A type representing instantiations of class types
* that has a method which returns an iterator.
*/
private class IterableClass extends Class {
private Type elementType;
IterableClass() {
elementType =
unique(Type et |
exists(Method m, RefType return, GenericType t, int position | m.getDeclaringType() = t |
return = m.getReturnType() and
return.getSourceDeclaration().hasQualifiedName("java.util", "Iterator") and
t.getTypeParameter(position) = return.(ParameterizedType).getTypeArgument(0) and
instantiates(this, t, position, et)
)
)
}
/**
* Returns the iterator element type of `this`.
*/
Type getElementType() { result = elementType }
}
/**
* Holds if type `bound` is an upper bound for type `t` or equal to `t`.
*/
private predicate isEffectivelyUpperBound(Type t, Type bound) {
t = bound or
t.(Wildcard).getUpperBound().getType() = bound
}
/**
* Holds if type `bound` is a lower bound for type `t` or equal to `t`.
*/
private predicate isEffectivelyLowerBound(Type t, Type bound) {
t = bound or
t.(Wildcard).getLowerBound().getType() = bound
}
/**
* Holds if `t` is a container like type of `tv` (eg. `List<T>`).
*/
private predicate genericContainerType(RefType t, TypeVariable tv) {
exists(Type et |
et =
[
t.(ContainerType).getElementType(), t.(IterableClass).getElementType(),
t.(Array).getElementType()
]
|
isEffectivelyUpperBound(et, tv)
)
}
/**
* Holds if `tv` is a type variable of the immediate type declaring `callable`.
*/
private predicate classTypeParameter(Callable callable, TypeVariable tv) {
callable.getDeclaringType().(GenericType).getATypeParameter() = tv
}
/**
* Holds if `tv` is type variable of `callable` or the type declaring `callable`.
*/
private predicate localTypeParameter(Callable callable, TypeVariable tv) {
classTypeParameter(callable, tv) or
callable.(GenericCallable).getATypeParameter() = tv
}
/**
* Gets the access path postfix for `t`.
*/
private string getAccessPath(Type t) {
if
t instanceof Array and
not Specific::isPrimitiveTypeUsedForBulkData(t.(Array).getElementType())
then result = ".ArrayElement"
else
if t instanceof ContainerType or t instanceof IterableClass
then result = ".Element"
else result = ""
}
/**
* Gets the access path for parameter `p`.
*/
private string parameterAccess(Parameter p) {
result = "Argument[" + p.getPosition() + "]" + getAccessPath(p.getType())
}
/**
* Holds if `callable` has a type parameter `tv` or container parameterized over type `tv`.
*/
private predicate parameter(Callable callable, string input, TypeVariable tv) {
exists(Parameter p, Type pt |
input = parameterAccess(p) and
p = callable.getAParameter() and
pt = p.getType() and
(
// Parameter of type tv
isEffectivelyUpperBound(pt, tv)
or
// Parameter is a container of type tv
genericContainerType(pt, tv)
)
)
}
/**
* Gets the string representation of a synthetic field corresponding to `tv`.
*/
private string getSyntheticField(TypeVariable tv) {
result = ".SyntheticField[ArgType" + tv.getIndex() + "]"
}
/**
* Gets a models as data string representation of, how a value of type `tv`
* can be read or stored implicitly in relation to `callable`.
*/
private string implicit(Callable callable, TypeVariable tv) {
classTypeParameter(callable, tv) and
not callable.isStatic() and
exists(string access, Type decl |
decl = callable.getDeclaringType() and
if genericContainerType(decl, tv)
then access = getAccessPath(decl)
else access = getSyntheticField(tv)
|
result = Specific::qualifierString() + access
)
}
private class GenericFunctionalInterface extends FunctionalInterface, GenericType {
override string getAPrimaryQlClass() { result = "GenericFunctionalInterface" }
}
/**
* A class of types that represents functions.
*/
private class Function extends ParameterizedType {
private GenericFunctionalInterface fi;
Function() { fi = this.getGenericType() }
/**
* Gets the typevariable that is the placeholder for the type `t`
* used in the instantiation of `this`.
*/
private TypeVariable getTypeReplacement(Type t) {
exists(int position |
instantiates(this, fi, position, t) and
result = fi.getTypeParameter(position)
)
}
/**
* Gets the parameter type of `this` function at position `position`.
* Note that functions are often contravariant in their parameter types.
*/
Type getParameterType(int position) {
exists(Type t |
fi.getRunMethod().getParameterType(position) = this.getTypeReplacement(t) and
isEffectivelyLowerBound(t, result)
)
}
/**
* Gets the return type of `this` function.
* Note that functions are often covariant in their return type.
*/
Type getReturnType() {
exists(Type t |
fi.getRunMethod().getReturnType() = this.getTypeReplacement(t) and
isEffectivelyUpperBound(t, result)
)
}
}
/**
* Holds if `callable` has a function parameter `f` at parameter position `position`.
*/
private predicate functional(Callable callable, Function f, int position) {
callable.getParameterType(position) = f
}
/**
* Gets models as data input/output access relative to the type parameter `tv` in the
* type `t` in the scope of `callable`.
*
* Note: This predicate has to be inlined as `callable` is not related to `return` or `tv`
* in every disjunction.
*/
bindingset[callable]
private string getAccess(Callable callable, Type return, TypeVariable tv) {
return = tv and result = ""
or
genericContainerType(return, tv) and result = getAccessPath(return)
or
not genericContainerType(return, tv) and
(
return.(ParameterizedType).getATypeArgument() = tv
or
callable.getDeclaringType() = return and return.(GenericType).getATypeParameter() = tv
) and
result = getSyntheticField(tv)
}
/**
* Holds if `input` is a models as data string representation of, how a value of type `tv`
* (or a generic parameterized over `tv`) can be generated by a function parameter of `callable`.
*/
private predicate functionalSource(Callable callable, string input, TypeVariable tv) {
exists(Function f, int position, Type return, string access |
functional(callable, f, position) and
return = f.getReturnType() and
access = getAccess(callable, return, tv) and
input = "Argument[" + position + "].ReturnValue" + access
)
}
/**
* Holds if `input` is a models as data string representation of, how a
* value of type `tv` (or a generic parameterized over `tv`)
* can be provided as input to `callable`.
* This includes
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
* (2) The parameters of `callable`.
* (3) Any function parameters of `callable`.
*/
private predicate input(Callable callable, string input, TypeVariable tv) {
input = implicit(callable, tv)
or
parameter(callable, input, tv)
or
functionalSource(callable, input, tv)
}
/**
* Holds if `callable` returns a value of type `tv` (or a generic parameterized over `tv`) and `output`
* is a models as data string representation of, how data is routed to the return.
*/
private predicate returns(Callable callable, TypeVariable tv, string output) {
exists(Type return, string access | return = callable.getReturnType() |
access = getAccess(callable, return, tv) and
output = "ReturnValue" + access
)
}
/**
* Holds if `callable` has a function parameter that accepts a value of type `tv`
* and `output` is the models as data string representation of, how data is routed to
* the function parameter.
*/
private predicate functionalSink(Callable callable, TypeVariable tv, string output) {
exists(Function f, int p1, int p2 |
functional(callable, f, p1) and
tv = f.getParameterType(p2) and
output = "Argument[" + p1 + "]" + ".Parameter[" + p2 + "]"
)
}
/**
* Holds if `output` is a models as data string representation of, how values of type `tv`
* (or generics parameterized over `tv`) can be routed.
* This includes
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
* (2) The return of `callable`.
* (3) Any function parameters of `callable`.
*/
private predicate output(Callable callable, TypeVariable tv, string output) {
output = implicit(callable, tv)
or
returns(callable, tv, output)
or
functionalSink(callable, tv, output)
}
/**
* A class of callables that are relevant generating summaries for based
* on the Theorems for Free approach.
*/
class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific {
TypeBasedFlowTargetApi() { Specific::isRelevantForTypeBasedFlowModels(this) }
/**
* Gets the string representation of all type based summaries for `this`
* inspired by the Theorems for Free approach.
*
* Examples could be (see Java pseudo code below)
* (1) `get` returns a value of type `T`. We assume that the returned
* value was fetched from a (synthetic) field.
* (2) `set` consumes a value of type `T`. We assume that the value is stored in
* a (synthetic) field.
* (3) `apply<S>` is assumed to apply the provided function to a value stored in
* a (synthetic) field and return the result.
* (4) `apply<S1,S2>` is assumed to apply the provided function to provided value
* and return the result.
* ```java
* public class MyGeneric<T> {
* public void set(T x) { ... }
* public T get() { ... }
* public <S> S apply<S>(Function<T, S> f) { ... }
* public <S1,S2> S2 apply<S1, S2>(S1 x, Function<S1, S2> f) { ... }
* }
* ```
*/
string getSummaries() {
exists(TypeVariable tv, string input, string output |
localTypeParameter(this, tv) and
input(this, input, tv) and
output(this, tv, output) and
input != output
|
result = asValueModel(this, input, output)
)
}
}
/**
* Returns the Theorems for Free inspired typed based summaries for `api`.
*/
string captureFlow(TypeBasedFlowTargetApi api) { result = api.getSummaries() }

View File

@@ -0,0 +1,2 @@
unexpectedSummary
expectedSummary

View File

@@ -0,0 +1,26 @@
import java
import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels
private string expects() {
exists(Javadoc doc |
doc.getChild(0).toString().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result
)
}
private string flows() { exists(TypeBasedFlowTargetApi api | result = captureFlow(api)) }
query predicate unexpectedSummary(string msg) {
exists(string flow |
flow = flows() and
not flow = expects() and
msg = "Unexpected summary found: " + flow
)
}
query predicate expectedSummary(string msg) {
exists(string e |
e = expects() and
not e = flows() and
msg = "Expected summary missing: " + e
)
}

View File

@@ -0,0 +1,10 @@
package p;
@FunctionalInterface
public interface MyFunction<T1, T2, T3> {
// MaD=p;MyFunction;true;apply;(Object,Object);;Argument[-1].SyntheticField[ArgType2];ReturnValue;value;generated
// MaD=p;MyFunction;true;apply;(Object,Object);;Argument[0];Argument[-1].SyntheticField[ArgType0];value;generated
// MaD=p;MyFunction;true;apply;(Object,Object);;Argument[1];Argument[-1].SyntheticField[ArgType1];value;generated
T3 apply(T1 x, T2 y);
}

View File

@@ -0,0 +1,247 @@
package p;
import java.util.*;
import java.util.function.*;
import java.util.stream.LongStream;
import java.util.stream.IntStream;
import java.util.stream.DoubleStream;
import java.util.stream.Collector;
/**
* This is a stub implementation of the Java Stream API.
*/
public class Stream<T> {
// MaD=p;Stream;true;iterator;();;Argument[-1].Element;ReturnValue.Element;value;generated
public Iterator<T> iterator() {
return null;
}
// MaD=p;Stream;true;allMatch;(Predicate);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public boolean allMatch(Predicate<? super T> predicate) {
return false;
}
// MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[-1].Element;Argument[1].Parameter[1];value;generated
// MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[0];value;generated
// MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[1];value;generated
// MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;ReturnValue;value;generated
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
return null;
}
// Collector is not a functional interface, so this is not supported
public <R, A> R collect(Collector<? super T, A, R> collector) {
return null;
}
// MaD=p;Stream;true;concat;(Stream,Stream);;Argument[0].Element;ReturnValue.Element;value;generated
// MaD=p;Stream;true;concat;(Stream,Stream);;Argument[1].Element;ReturnValue.Element;value;generated
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
return null;
}
// MaD=p;Stream;true;distinct;();;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> distinct() {
return null;
}
public static <T> Stream<T> empty() {
return null;
}
// MaD=p;Stream;true;filter;(Predicate);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;filter;(Predicate);;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> filter(Predicate<? super T> predicate) {
return null;
}
// MaD=p;Stream;true;findAny;();;Argument[-1].Element;ReturnValue.SyntheticField[ArgType0];value;generated
public Optional<T> findAny() {
return null;
}
// MaD=p;Stream;true;findFirst;();;Argument[-1].Element;ReturnValue.SyntheticField[ArgType0];value;generated
public Optional<T> findFirst() {
return null;
}
// MaD=p;Stream;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.Element;value;generated
// MaD=p;Stream;true;flatMap;(Function);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
return null;
}
// MaD=p;Stream;true;flatMapToDouble;(Function);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
return null;
}
// MaD=p;Stream;true;flatMapToInt;(Function);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
return null;
}
// MaD=p;Stream;true;flatMapToLong;(Function);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
return null;
}
// MaD=p;Stream;true;forEach;(Consumer);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public void forEach(Consumer<? super T> action) {
}
// MaD=p;Stream;true;forEachOrdered;(Consumer);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public void forEachOrdered(Consumer<? super T> action) {
}
// MaD=p;Stream;true;generate;(Supplier);;Argument[0].ReturnValue;ReturnValue.Element;value;generated
public static <T> Stream<T> generate(Supplier<T> s) {
return null;
}
// MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];ReturnValue.Element;value;generated
// MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;ReturnValue.Element;value;generated
public static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) {
return null;
}
// MaD=p;Stream;true;limit;(long);;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> limit(long maxSize) {
return null;
}
// MaD=p;Stream;true;map;(Function);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;map;(Function);;Argument[0].ReturnValue;ReturnValue.Element;value;generated
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
return null;
}
// MaD=p;Stream;true;mapToDouble;(ToDoubleFunction);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
return null;
}
// MaD=p;Stream;true;mapToInt;(ToIntFunction);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public IntStream mapToInt(ToIntFunction<? super T> mapper) {
return null;
}
// MaD=p;Stream;true;mapToLong;(ToLongFunction);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public LongStream mapToLong(ToLongFunction<? super T> mapper) {
return null;
}
// MaD=p;Stream;true;max;(Comparator);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;max;(Comparator);;Argument[-1].Element;Argument[0].Parameter[1];value;generated
// MaD=p;Stream;true;max;(Comparator);;Argument[-1].Element;ReturnValue.SyntheticField[ArgType0];value;generated
public Optional<T> max(Comparator<? super T> comparator) {
return null;
}
// MaD=p;Stream;true;min;(Comparator);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;min;(Comparator);;Argument[-1].Element;Argument[0].Parameter[1];value;generated
// MaD=p;Stream;true;min;(Comparator);;Argument[-1].Element;ReturnValue.SyntheticField[ArgType0];value;generated
public Optional<T> min(Comparator<? super T> comparator) {
return null;
}
// MaD=p;Stream;true;noneMatch;(Predicate);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
public boolean noneMatch(Predicate<? super T> predicate) {
return false;
}
// MaD=p;Stream;true;of;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;generated
public static <T> Stream<T> of(T... t) {
return null;
}
// MaD=p;Stream;true;of;(Object);;Argument[0];ReturnValue.Element;value;generated
public static <T> Stream<T> of(T t) {
return null;
}
// MaD=p;Stream;true;peek;(Consumer);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;peek;(Consumer);;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> peek(Consumer<? super T> action) {
return null;
}
// The generated models are only partially correct.
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[-1].Element;Argument[0].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[-1].Element;ReturnValue.SyntheticField[ArgType0];value;generated
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;generated
// SPURIOUS-MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[-1].Element;value;generated
public Optional<T> reduce(BinaryOperator<T> accumulator) {
return null;
}
// The generated models are only partially correct.
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[-1].Element;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[-1].Element;Argument[1].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;generated
// SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[-1].Element;ReturnValue;value;generated
// SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[-1].Element;value;generated
// SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[-1].Element;value;generated
public T reduce(T identity, BinaryOperator<T> accumulator) {
return null;
}
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[-1].Element;Argument[1].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[1].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[1];value;generated
// MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;ReturnValue;value;generated
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
return null;
}
// MaD=p;Stream;true;skip;(long);;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> skip(long n) {
return null;
}
// MaD=p;Stream;true;sorted;();;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> sorted() {
return null;
}
// MaD=p;Stream;true;sorted;(Comparator);;Argument[-1].Element;Argument[0].Parameter[0];value;generated
// MaD=p;Stream;true;sorted;(Comparator);;Argument[-1].Element;Argument[0].Parameter[1];value;generated
// MaD=p;Stream;true;sorted;(Comparator);;Argument[-1].Element;ReturnValue.Element;value;generated
public Stream<T> sorted(Comparator<? super T> comparator) {
return null;
}
// Models can never be generated correctly based on the type information
// as it involves downcasting.
public Object[] toArray() {
return null;
}
// The generated result is only partially correct as there is no mentioning of
// the type T in the method definition.
// MaD=p;Stream;true;toArray;(IntFunction);;Argument[0].ReturnValue.ArrayElement;ReturnValue.ArrayElement;value;generated
public <A> A[] toArray(IntFunction<A[]> generator) {
return null;
}
}

View File

@@ -0,0 +1,25 @@
package p;
import java.util.List;
import java.util.ArrayList;
public class TypeBasedCollection<T> extends ArrayList<T> {
// MaD=p;TypeBasedCollection;true;addT;(Object);;Argument[0];Argument[-1].Element;value;generated
public void addT(T x) {
}
// MaD=p;TypeBasedCollection;true;addManyT;(List);;Argument[0].Element;Argument[-1].Element;value;generated
public void addManyT(List<T> xs) {
}
// MaD=p;TypeBasedCollection;true;firstT;();;Argument[-1].Element;ReturnValue;value;generated
public T firstT() {
return null;
}
// MaD=p;TypeBasedCollection;true;getManyT;();;Argument[-1].Element;ReturnValue.Element;value;generated
public List<T> getManyT() {
return null;
}
}

View File

@@ -0,0 +1,91 @@
package p;
import java.util.List;
import java.util.function.Function;
public class TypeBasedComplex<T> {
// MaD=p;TypeBasedComplex;true;addMany;(List);;Argument[0].Element;Argument[-1].SyntheticField[ArgType0];value;generated
public void addMany(List<T> xs) {
}
// MaD=p;TypeBasedComplex;true;getMany;();;Argument[-1].SyntheticField[ArgType0];ReturnValue.Element;value;generated
public List<T> getMany() {
return null;
}
// MaD=p;TypeBasedComplex;true;apply;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
public Integer apply(Function<T, Integer> f) {
return null;
}
// A method that doesn't mention `T` in its type signature.
// This is for testing that we don't generate a summary that involves the
// implicit field for `T`.
// MaD=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[0];Argument[1].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[1].ReturnValue;ReturnValue;value;generated
public <T1, T2> T2 apply2(T1 x, Function<T1, T2> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[-1].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[-1].SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated
public TypeBasedComplex<T> flatMap(Function<T, List<T>> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated
public <S> TypeBasedComplex<S> flatMap2(Function<T, List<S>> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;map;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;map;(Function);;Argument[0].ReturnValue;ReturnValue;value;generated
public <S> S map(Function<T, S> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;generated
public <S> TypeBasedComplex<S> mapComplex(Function<T, S> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[-1].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[-1].SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated
public TypeBasedComplex<T> returnComplex(Function<T, TypeBasedComplex<T>> f) {
return null;
}
// MaD=p;TypeBasedComplex;true;set;(Integer,Function);;Argument[1].ReturnValue;Argument[-1].SyntheticField[ArgType0];value;generated
public void set(Integer x, Function<Integer, T> f) {
}
// MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[-1].SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;generated
public Integer applyMyFunction(MyFunction<T, Integer, T> f, Integer x) {
return null;
}
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[-1].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[0].ReturnValue;ReturnValue;value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[1];Argument[0].Parameter[1];value;generated
public <S1, S2> S2 applyMyFunctionGeneric(MyFunction<T, S1, S2> f, S1 x) {
return null;
}
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[0].ReturnValue;ReturnValue;value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[1];Argument[0].Parameter[0];value;generated
// MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[2];Argument[0].Parameter[1];value;generated
public <S1, S2, S3> S3 applyMyFunctionGeneric(MyFunction<S1, S2, S3> f, S1 x, S2 y) {
return null;
}
}

View File

@@ -0,0 +1,42 @@
package p;
public class TypeBasedSimple<T> {
// MaD=p;TypeBasedSimple;true;TypeBasedSimple;(Object);;Argument[0];Argument[-1].SyntheticField[ArgType0];value;generated
public TypeBasedSimple(T t) {
}
// MaD=p;TypeBasedSimple;true;get;();;Argument[-1].SyntheticField[ArgType0];ReturnValue;value;generated
public T get() {
return null;
}
// MaD=p;TypeBasedSimple;true;get;(Object);;Argument[-1].SyntheticField[ArgType0];ReturnValue;value;generated
public T get(Object o) {
return null;
}
// MaD=p;TypeBasedSimple;true;id;(Object);;Argument[-1].SyntheticField[ArgType0];ReturnValue;value;generated
// MaD=p;TypeBasedSimple;true;id;(Object);;Argument[0];Argument[-1].SyntheticField[ArgType0];value;generated
// MaD=p;TypeBasedSimple;true;id;(Object);;Argument[0];ReturnValue;value;generated
public T id(T x) {
return null;
}
// MaD=p;TypeBasedSimple;true;id2;(Object);;Argument[0];ReturnValue;value;generated
public <S> S id2(S x) {
return null;
}
// MaD=p;TypeBasedSimple;true;set;(Object);;Argument[0];Argument[-1].SyntheticField[ArgType0];value;generated
public void set(T x) {
}
// MaD=p;TypeBasedSimple;true;set;(int,Object);;Argument[1];Argument[-1].SyntheticField[ArgType0];value;generated
public void set(int x, T y) {
}
// No summary as S is unrelated to T
public <S> void set2(S x) {
}
}