All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.checker.index.Subsequence Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.44.0
Show newest version
package org.checkerframework.checker.index;

import com.sun.source.tree.Tree;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import org.checkerframework.checker.index.qual.HasSubsequence;
import org.checkerframework.dataflow.expression.FieldAccess;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.util.JavaExpressionParseUtil;
import org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException;
import org.checkerframework.framework.util.StringToJavaExpression;
import org.checkerframework.javacutil.TreeUtils;

/** Holds information from {@link HasSubsequence} annotations. */
public class Subsequence {

  /** Name of the Subsequence. */
  public final String array;
  /** First index of the subsequence in the backing sequence. */
  public final String from;
  /** Last index of the subsequence in the backing sequence. */
  public final String to;

  private Subsequence(String array, String from, String to) {
    this.array = array;
    this.from = from;
    this.to = to;
  }

  /**
   * Returns a Subsequence representing the {@link HasSubsequence} annotation on the declaration of
   * {@code varTree} or null if there is not such annotation.
   *
   * 

Note that this method does not standardize or viewpoint adapt the arguments to the * annotation, unlike getSubsequenceFromReceiver. * * @param varTree some tree * @param factory an AnnotatedTypeFactory * @return null or a new Subsequence from the declaration of {@code varTree} */ public static Subsequence getSubsequenceFromTree( Tree varTree, BaseAnnotatedTypeFactoryForIndexChecker factory) { if (!(varTree.getKind() == Tree.Kind.IDENTIFIER || varTree.getKind() == Tree.Kind.MEMBER_SELECT || varTree.getKind() == Tree.Kind.VARIABLE)) { return null; } Element element = TreeUtils.elementFromTree(varTree); AnnotationMirror hasSub = factory.getDeclAnnotation(element, HasSubsequence.class); return createSubsequence(hasSub, factory); } /** * Factory method to create a representation of a subsequence. * * @param hasSub {@link HasSubsequence} annotation or null * @param factory the type factory * @return a new Subsequence object representing {@code hasSub} or null */ private static Subsequence createSubsequence( AnnotationMirror hasSub, BaseAnnotatedTypeFactoryForIndexChecker factory) { if (hasSub == null) { return null; } String from = factory.hasSubsequenceFromValue(hasSub); String to = factory.hasSubsequenceToValue(hasSub); String array = factory.hasSubsequenceSubsequenceValue(hasSub); return new Subsequence(array, from, to); } /** * Returns a Subsequence representing the {@link HasSubsequence} annotation on the declaration of * {@code rec} or null if there is not such annotation. * * @param expr some tree * @param factory an AnnotatedTypeFactory * @return null or a new Subsequence from the declaration of {@code varTree} */ public static Subsequence getSubsequenceFromReceiver( JavaExpression expr, BaseAnnotatedTypeFactoryForIndexChecker factory) { if (!(expr instanceof FieldAccess)) { return null; } FieldAccess fa = (FieldAccess) expr; VariableElement element = fa.getField(); AnnotationMirror hasSub = factory.getDeclAnnotation(element, HasSubsequence.class); if (hasSub == null) { return null; } String array = standardizeAndViewpointAdapt( factory.hasSubsequenceSubsequenceValue(hasSub), fa, factory.getChecker()); String from = standardizeAndViewpointAdapt( factory.hasSubsequenceFromValue(hasSub), fa, factory.getChecker()); String to = standardizeAndViewpointAdapt( factory.hasSubsequenceToValue(hasSub), fa, factory.getChecker()); return new Subsequence(array, from, to); } /** * Helper function to standardize and viewpoint-adapt a string at a given field access. Wraps * {@link JavaExpressionParseUtil#parse}. If a parse exception is encountered, this returns its * argument. * * @param s a Java expression string * @param fieldAccess the field access * @param checker used to parse the expression * @return the argument, standardized and viewpoint-adapted */ private static String standardizeAndViewpointAdapt( String s, FieldAccess fieldAccess, SourceChecker checker) { JavaExpression parseResult; try { parseResult = StringToJavaExpression.atFieldDecl(s, fieldAccess.getField(), checker); } catch (JavaExpressionParseException e) { return s; } return parseResult.atFieldAccess(fieldAccess.getReceiver()).toString(); } /** * Returns the additive inverse of the given String. That is, if the result of this method is some * String s', then s + s' == 0 will evaluate to true. Note that this relies on the fact that the * JavaExpression parser cannot parse multiplication, so it naively just changes '-' to '+' and * vice-versa. * * @param s a Java expression string * @return the negated string */ public static String negateString(String s) { String original = s; String result = ""; if (!original.startsWith("-")) { result += '-'; } for (int i = 0; i < original.length(); i++) { char c = original.charAt(i); if (c == '-') { result += '+'; } else if (c == '+') { result += '-'; } else { result += c; } } return result; } @Override public String toString() { return "Subsequence(array=" + this.array + ", from=" + this.from + ", to=" + this.to + ")"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy