if ("append".equals(getNameConstantOperand()) &&	"(Ljava/lang/String;)Ljava/lang/StringBuffer;".equals(getSigConstantOperand())) { appendPC = getPC(); } else if ("Ljava/lang/StringBuffer;".equals(getClassConstantOperand()) &&	"toString".equals(getNameConstantOperand()) &&	"()Ljava/lang/String;".equals(getSigConstantOperand())) {    reset(); } } else if ((seen == NEW) && "java/lang/StringBuffer".equals(getClassConstantOperand())) { reset(); state = SEEN_NEW; }  break;  default: reset(); break; } }
case SEEN_NEW: if ( DEBUG && seen == INVOKEVIRTUAL ) { System.out.println("Invoke virtual"); System.out.println("   " + getNameConstantOperand()); System.out.println("   " + getClassConstantOperand()); System.out.println("   " + getSigConstantOperand()); } if ( seen == INVOKEVIRTUAL &&  "append".equals(getNameConstantOperand()) && getClassConstantOperand().startsWith("java/lang/StringBu") && getSigConstantOperand() .startsWith("(Ljava/lang/String;)") ){ if (DEBUG) System.out.println("Saw string being appended from register " + registerOnStack); if ( registerOnStack >= 0 ) { if (DEBUG) System.out.println("Saw string being appended, source = " + registerOnStack); state = SEEN_APPEND1; stringSource = registerOnStack; } else reset(); } break; case SEEN_APPEND1: if ( seen == INVOKEVIRTUAL &&  "append".equals(getNameConstantOperand()) && getClassConstantOperand().startsWith("java/lang/StringBu")) { state = SEEN_APPEND2; } break;  case SEEN_APPEND2: if ( seen == INVOKEVIRTUAL &&  "toString".equals(getNameConstantOperand()) && getClassConstantOperand().startsWith("java/lang/StringBu")) { state = CONSTRUCTED_STRING_ON_STACK; } break;  case CONSTRUCTED_STRING_ON_STACK: boolean match = false; switch (seen) { case ASTORE_0: match = stringSource == 0; break; case ASTORE_1: match = stringSource == 1; break; case ASTORE_2: match = stringSource == 2; break; case ASTORE_3: match = stringSource == 3; break; case ASTORE: match = stringSource == getRegisterOperand(); break; } if (match) state = POSSIBLE_CASE; else reset(); break;  case POSSIBLE_CASE: if (seen == GOTO && getBranchTarget() < createPC ) { bugReporter.reportBug(new BugInstance("SBSC_USE_STRINGBUFFER_CONCATENATION", NORMAL_PRIORITY) .addClassAndMethod(this) .addSourceLine(this, createPC)); reset(); reportedThisMethod = true; } else if ((seen == NEW) && getClassConstantOperand().startsWith("java/lang/StringBu")) { state = SEEN_NEW; createPC = getPC(); } break; } registerOnStack = -1; switch(seen) { case ALOAD_0: registerOnStack = 0; break; case ALOAD_1: registerOnStack = 1; break; case ALOAD_2: registerOnStack = 2; break; case ALOAD_3: registerOnStack = 3; break; case ALOAD: registerOnStack = getRegisterOperand(); break; } if (DEBUG && state != oldState) System.out.println("At PC " + getPC() + " changing from state " + oldState + " to state " + state + ", regOnStack = " + registerOnStack); }
	public void sawOpcode(int seen) {		switch (state)		{		case SEEN_NOTHING:			if ((seen == NEW) && "java/lang/StringBuffer".equals(getClassConstantOperand())) {				state = SEEN_NEW;				createPC = getPC();			}			break;				case SEEN_NEW:			if (seen == DUP)				state = SEEN_DUP;			else				reset();			break;				case SEEN_DUP:			if ((seen == INVOKESPECIAL) 			&&  ("<init>".equals(getNameConstantOperand()))			&&	("java/lang/StringBuffer".equals(getClassConstantOperand()))) {				// A StringBuffer is being constructed				if ("()V".equals(getSigConstantOperand())) {					state = SEEN_INVOKESPECIAL;				} else if ("(Ljava/lang/String;)V".equals(getSigConstantOperand())) {					// The StringBuffer constructor can start with the					// value of an existing string.					state = SEEN_INVOKESPECIAL;					appendPC = getPC();				} else {					reset();				}			} else				reset();			break;				case SEEN_INVOKESPECIAL:			if ((seen == ASTORE_0)			||  (seen == ASTORE_1)			||  (seen == ASTORE_2)			||  (seen == ASTORE_3)			||  (seen == ASTORE)) {				reset();				break;			} else				state = POSSIBLE_CASE;			// FALL THROUGH						case POSSIBLE_CASE:			if ((seen == GOTO) && (appendPC >= 0)) {				if (getBranchTarget() < getPC()				&&	getBranchTarget() < createPC				&&	getBranchTarget() < appendPC) {					bugReporter.reportBug(new BugInstance("SBSC_USE_STRINGBUFFER_CONCATENATION", NORMAL_PRIORITY)						.addClassAndMethod(this)						.addSourceLine(this, appendPC));				}				reset();			}			else if (seen == INVOKEVIRTUAL) {				if ("append".equals(getNameConstantOperand())				&&	"(Ljava/lang/String;)Ljava/lang/StringBuffer;".equals(getSigConstantOperand())) {					appendPC = getPC();				} else if ("Ljava/lang/StringBuffer;".equals(getClassConstantOperand())				&&	"toString".equals(getNameConstantOperand())				&&	"()Ljava/lang/String;".equals(getSigConstantOperand())) {					// The StringBuffer appears to be consumed in the loop.					// In the pattern we're looking for, the StringBuffer					// is consumed AFTER the exit from the loop.					reset();				}			} else if ((seen == NEW) && "java/lang/StringBuffer".equals(getClassConstantOperand())) {				reset();				state = SEEN_NEW;			}							break;							default:			reset();			break;		}	}