001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2003-2007 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba.jsr305;
021:
022: import javax.annotation.meta.When;
023:
024: /**
025: * Flow value type for type qualifier dataflow analysis.
026: *
027: * @author David Hovemeyer
028: */
029: public enum FlowValue {
030:
031: TOP(0), ALWAYS(Bits.YES), NEVER(Bits.NO), UNKNOWN(Bits.YES
032: | Bits.NO | Bits.UNCERTAIN);
033:
034: private interface Bits {
035: public static final int YES = 1;
036: public static final int UNCERTAIN = 2;
037: public static final int NO = 4;
038: }
039:
040: private final int bits;
041:
042: private FlowValue(int bits) {
043: this .bits = bits;
044: }
045:
046: public boolean isYes() {
047: return (bits & Bits.YES) != 0;
048: }
049:
050: public boolean isUncertain() {
051: return (bits & Bits.UNCERTAIN) != 0;
052: }
053:
054: public boolean isNo() {
055: return (bits & Bits.NO) != 0;
056: }
057:
058: // Dataflow lattice:
059: //
060: // Top
061: // / \
062: // Always Never
063: // \ /
064: // Unknown
065: //
066: private static final FlowValue[][] mergeMatrix = {
067: // TOP ALWAYS NEVER UNKNOWN
068: /* TOP */{ TOP, },
069: /* ALWAYS */{ ALWAYS, ALWAYS, },
070: /* NEVER */{ NEVER, UNKNOWN, NEVER, },
071: /* UNKNOWN */{ UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN }, };
072:
073: public static final FlowValue meet(FlowValue a, FlowValue b) {
074: int aIndex = a.ordinal();
075: int bIndex = b.ordinal();
076:
077: if (aIndex < bIndex) {
078: int tmp = aIndex;
079: aIndex = bIndex;
080: bIndex = tmp;
081: }
082:
083: return mergeMatrix[aIndex][bIndex];
084: }
085:
086: /**
087: * Determine whether given flow values conflict.
088: *
089: * @param forward a forwards flow value
090: * @param backward a backwards flow value
091: * @param isStrictQualifier true if the type qualifier being checked is strict
092: * @return true if values conflict, false otherwise
093: */
094: public static boolean valuesConflict(FlowValue forward,
095: FlowValue backward) {
096: if (forward == TOP || backward == TOP) {
097: return false;
098: }
099: return (forward == ALWAYS && backward == NEVER)
100: || (forward == NEVER && backward == ALWAYS);
101: }
102:
103: /**
104: * Convert a When value to a FlowValue value.
105: *
106: * @param when a When value
107: * @return the corresponding FlowValue
108: */
109: public static FlowValue flowValueFromWhen(When when) {
110: switch (when) {
111: case ALWAYS:
112: return FlowValue.ALWAYS;
113: case MAYBE:
114: return FlowValue.UNKNOWN;
115: case NEVER:
116: return FlowValue.NEVER;
117: case UNKNOWN:
118: return FlowValue.UNKNOWN;
119: default:
120: throw new IllegalStateException();
121: }
122: }
123:
124: /**
125: * Determine whether given backwards FlowValue
126: * conflicts with given source.
127: *
128: * @param backwardsFlowValue a backwards FlowValue
129: * @param source SourceSinkInfo object representing a source
130: * reached by the backwards flow value
131: * @param typeQualifierValue TypeQualifierValue being checked
132: * @return true if backwards value conflicts with source, false if not
133: */
134: public static boolean backwardsValueConflictsWithSource(
135: FlowValue backwardsFlowValue, SourceSinkInfo source,
136: TypeQualifierValue typeQualifierValue) {
137:
138: When sourceWhen = source.getWhen();
139:
140: if (typeQualifierValue.isStrictQualifier()) {
141: // strict checking
142: return (backwardsFlowValue == ALWAYS && sourceWhen != When.ALWAYS)
143: || (backwardsFlowValue == NEVER && sourceWhen != When.NEVER);
144: } else {
145: // NOT strict checking
146: return (backwardsFlowValue == ALWAYS && (sourceWhen == When.NEVER || sourceWhen == When.MAYBE))
147: || (backwardsFlowValue == NEVER && (sourceWhen == When.ALWAYS || sourceWhen == When.MAYBE));
148: }
149: }
150:
151: }
|