use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class FlowExpressionParseUtil method parseMemberSelect.
/**
* Matches a field access. First of returned pair is object and second is field.
*
* @param s expression string
* @return pair of object and field
*/
private static Pair<String, String> parseMemberSelect(String s) {
Pair<Pair<String, String>, String> method = parseMethod(s);
if (method != null && method.second.startsWith(".")) {
return Pair.of(method.first.first + "(" + method.first.second + ")", method.second.substring(1));
}
Pair<Pair<String, String>, String> array = parseArray(s);
if (array != null && array.second.startsWith(".")) {
return Pair.of(array.first.first + "[" + array.first.second + "]", array.second.substring(1));
}
Pattern memberSelectOfStringPattern = anchored("(" + stringRegex + ")" + "\\.(.*)");
Matcher m = memberSelectOfStringPattern.matcher(s);
if (m.matches()) {
return Pair.of(m.group(1), m.group(2));
}
int nextRParenPos = matchingCloseParen(s, 0, '(', ')');
if (nextRParenPos != -1) {
if (nextRParenPos + 1 < s.length() && s.charAt(nextRParenPos + 1) == '.') {
String reciever = s.substring(0, nextRParenPos + 1);
String remaining = s.substring(nextRParenPos + 2);
return Pair.of(reciever, remaining);
} else {
return null;
}
}
int i = s.indexOf(".");
if (i == -1) {
return null;
}
String reciever = s.substring(0, i);
String remaining = s.substring(i + 1);
return Pair.of(reciever, remaining);
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class Analysis method getReturnStatementStores.
public List<Pair<ReturnNode, TransferResult<A, S>>> getReturnStatementStores() {
List<Pair<ReturnNode, TransferResult<A, S>>> result = new ArrayList<>();
for (ReturnNode returnNode : cfg.getReturnNodes()) {
TransferResult<A, S> store = storesAtReturnStatements.get(returnNode);
result.add(Pair.of(returnNode, store));
}
return result;
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class KeyForPropagator method propagate.
/**
* Propagate annotations from the type arguments of one type to another. Which type is the source
* and destination of the annotations depends on the direction parameter. Only @KeyFor annotations
* are propagated and only if the type to which it would be propagated contains an @UnknownKeyFor
* or contains no key for annotations of any kind. If any of the type arguments are wildcards than
* they are ignored.
*
* <p>Note the primary annotations of subtype/supertype are not used.
*
* <p>Simple Example:
*
* <pre>{@code
* typeOf(subtype) = ArrayList<@KeyFor("a") String>
* typeOf(supertype) = List<@UnknownKeyFor String>
* direction = TO_SUPERTYPE
* }</pre>
*
* The type of supertype after propagate would be: {@code List<@KeyFor("a") String>}
*
* <p>A more complex example would be:
*
* <pre>{@code
* typeOf(subtype) = HashMap<@UnknownKeyFor String, @KeyFor("b") List<@KeyFor("c") String>>
* typeOf(supertype) = Map<@KeyFor("a") String, @KeyFor("b") List<@KeyFor("c") String>>
* direction = TO_SUBTYPE
* }</pre>
*
* The type of subtype after propagate would be: {@code HashMap<@KeyFor("a") String, @KeyFor("b")
* List<@KeyFor("c") String>>}
*/
public void propagate(final AnnotatedDeclaredType subtype, final AnnotatedDeclaredType supertype, PropagationDirection direction, final AnnotatedTypeFactory typeFactory) {
final TypeElement subtypeElement = (TypeElement) subtype.getUnderlyingType().asElement();
final TypeElement supertypeElement = (TypeElement) supertype.getUnderlyingType().asElement();
final Types types = typeFactory.getProcessingEnv().getTypeUtils();
// Note: The right hand side of this or expression will cover raw types
if (subtype.getTypeArguments().isEmpty()) {
return;
}
// In either case, there is no reason to propagate
if (supertype.getTypeArguments().isEmpty()) {
return;
}
Set<Pair<Integer, Integer>> typeParamMappings = TypeArgumentMapper.mapTypeArgumentIndices(subtypeElement, supertypeElement, types);
final List<AnnotatedTypeMirror> subtypeArgs = subtype.getTypeArguments();
final List<AnnotatedTypeMirror> supertypeArgs = supertype.getTypeArguments();
for (final Pair<Integer, Integer> path : typeParamMappings) {
final AnnotatedTypeMirror subtypeArg = subtypeArgs.get(path.first);
final AnnotatedTypeMirror supertypeArg = supertypeArgs.get(path.second);
if (subtypeArg.getKind() == TypeKind.WILDCARD || supertypeArg.getKind() == TypeKind.WILDCARD) {
continue;
}
switch(direction) {
case TO_SUBTYPE:
replacer.visit(supertypeArg, subtypeArg);
break;
case TO_SUPERTYPE:
replacer.visit(subtypeArg, supertypeArg);
break;
case BOTH:
// note if they both have an annotation nothing will happen
replacer.visit(subtypeArg, supertypeArg);
replacer.visit(supertypeArg, subtypeArg);
break;
}
}
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class ContractsFromMethod method getContracts.
// / Helper methods
/**
* Returns the contracts (of a particular kind) on method or constructor {@code
* executableElement}.
*
* @param <T> the type of {@link Contract} to return
* @param executableElement the method whose contracts to return
* @param kind the kind of contracts to retrieve
* @param clazz the class to determine the return type
* @return the contracts on {@code executableElement}
*/
private <T extends Contract> Set<T> getContracts(ExecutableElement executableElement, Kind kind, Class<T> clazz) {
Set<T> result = new LinkedHashSet<>();
// Check for a single framework-defined contract annotation.
AnnotationMirror frameworkContractAnno = factory.getDeclAnnotation(executableElement, kind.frameworkContractClass);
result.addAll(getContract(kind, frameworkContractAnno, clazz));
// Check for a framework-defined wrapper around contract annotations.
// The result is RequiresQualifier.List, EnsuresQualifier.List, or EnsuresQualifierIf.List.
AnnotationMirror frameworkContractListAnno = factory.getDeclAnnotation(executableElement, kind.frameworkContractListClass);
if (frameworkContractListAnno != null) {
List<AnnotationMirror> frameworkContractAnnoList = factory.getContractListValues(frameworkContractListAnno);
for (AnnotationMirror a : frameworkContractAnnoList) {
result.addAll(getContract(kind, a, clazz));
}
}
// Check for type-system specific annotations.
List<Pair<AnnotationMirror, AnnotationMirror>> declAnnotations = factory.getDeclAnnotationWithMetaAnnotation(executableElement, kind.metaAnnotation);
for (Pair<AnnotationMirror, AnnotationMirror> r : declAnnotations) {
AnnotationMirror anno = r.first;
// contractAnno is the meta-annotation on anno.
AnnotationMirror contractAnno = r.second;
AnnotationMirror enforcedQualifier = getQualifierEnforcedByContractAnnotation(contractAnno, anno);
if (enforcedQualifier == null) {
continue;
}
List<String> expressions = factory.getContractExpressions(kind, anno);
Collections.sort(expressions);
Boolean ensuresQualifierIfResult = factory.getEnsuresQualifierIfResult(kind, anno);
for (String expr : expressions) {
T contract = clazz.cast(Contract.create(kind, expr, enforcedQualifier, anno, ensuresQualifierIfResult));
result.add(contract);
}
}
return result;
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class BaseTypeVisitor method parseAndLocalizeContracts.
/**
* Localizes some contracts -- that is, viewpoint-adapts them to some method body, according to
* the value of {@link #methodTree}.
*
* <p>The input is a set of {@link Contract}s, each of which contains an expression string and an
* annotation. In a {@link Contract}, Java expressions are exactly as written in source code, not
* standardized or viewpoint-adapted.
*
* <p>The output is a set of pairs of {@link JavaExpression} (parsed expression string) and
* standardized annotation (with respect to the path of {@link #methodTree}. This method discards
* any contract whose expression cannot be parsed into a JavaExpression.
*
* @param contractSet a set of contracts
* @param methodType the type of the method that the contracts are for
* @return pairs of (expression, AnnotationMirror), which are localized contracts
*/
private Set<Pair<JavaExpression, AnnotationMirror>> parseAndLocalizeContracts(Set<? extends Contract> contractSet, AnnotatedExecutableType methodType) {
if (contractSet.isEmpty()) {
return Collections.emptySet();
}
// This is the path to a place where the contract is being used, which might or might not be
// where the contract was defined. For example, methodTree might be an overriding
// definition, and the contract might be for a superclass.
MethodTree methodTree = this.methodTree;
StringToJavaExpression stringToJavaExpr = expression -> {
JavaExpression javaExpr = StringToJavaExpression.atMethodDecl(expression, methodType.getElement(), checker);
// viewpoint-adapt it to methodTree.
return javaExpr.atMethodBody(methodTree);
};
Set<Pair<JavaExpression, AnnotationMirror>> result = new HashSet<>(contractSet.size());
for (Contract p : contractSet) {
String expressionString = p.expressionString;
AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(atypeFactory, stringToJavaExpr, methodTree);
JavaExpression exprJe;
try {
// TODO: currently, these expressions are parsed many times.
// This could be optimized to store the result the first time.
// (same for other annotations)
exprJe = stringToJavaExpr.toJavaExpression(expressionString);
} catch (JavaExpressionParseException e) {
// report errors here
checker.report(methodTree, e.getDiagMessage());
continue;
}
result.add(Pair.of(exprJe, annotation));
}
return result;
}
Aggregations