public void replaceWithElementType() { if (this.constantPoolName[1] == 'L') { this.constantPoolName = CharOperation.subarray(this.constantPoolName, 2, this.constantPoolName.length - 1); } else { this.constantPoolName = CharOperation.subarray(this.constantPoolName, 1, this.constantPoolName.length); if (this.constantPoolName.length == 1) { switch (this.constantPoolName[0]) { case 'I': this.id = TypeIds.T_int; break; case 'B': this.id = TypeIds.T_byte; break; case 'S': this.id = TypeIds.T_short; break; case 'C': this.id = TypeIds.T_char; break; case 'J': this.id = TypeIds.T_long; break; case 'F': this.id = TypeIds.T_float; break; case 'D': this.id = TypeIds.T_double; break; case 'Z': this.id = TypeIds.T_boolean; break; case 'N': this.id = TypeIds.T_null; break; case 'V': this.id = TypeIds.T_void; break; } } } }
protected boolean matches(char[][] compoundName) { int length = compoundName.length; if (length == 0) return false; char[] simpleName = compoundName[length - 1]; int last = length - 1; if (this.typeSimpleName == null || this.pattern.matchesName(simpleName, this.typeSimpleName)) { // most frequent case: simple name equals last segment of compoundName char[][] qualification = new char[last][]; System.arraycopy(compoundName, 0, qualification, 0, last); return this.pattern.matchesName( this.typeQualification, CharOperation.concatWith(qualification, '.')); } if (!CharOperation.endsWith(simpleName, this.typeSimpleName)) return false; // member type -> transform A.B.C$D into A.B.C.D System.arraycopy(compoundName, 0, compoundName = new char[length + 1][], 0, last); int dollar = CharOperation.indexOf('$', simpleName); if (dollar == -1) return false; compoundName[last] = CharOperation.subarray(simpleName, 0, dollar); compoundName[length] = CharOperation.subarray(simpleName, dollar + 1, simpleName.length); return this.matches(compoundName); }
public char[] getMainTypeName() { if (this.compilationResult.compilationUnit == null) { char[] fileName = this.compilationResult.getFileName(); int start = CharOperation.lastIndexOf('/', fileName) + 1; if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName)) start = CharOperation.lastIndexOf('\\', fileName) + 1; int end = CharOperation.lastIndexOf('.', fileName); if (end == -1) end = fileName.length; return CharOperation.subarray(fileName, start, end); } else { return this.compilationResult.compilationUnit.getMainTypeName(); } }
/** * In case emulating local variables, wrap the (recovered) statements inside a try statement so as * to achieve local state commiting (copy local vars back to fields). The CSToCuMapper could not * be used, since it could have interfered with the syntax recovery specific to code snippets. */ protected void consumeMethodDeclaration(boolean isNotAbstract) { // MethodDeclaration ::= MethodHeader MethodBody // AbstractMethodDeclaration ::= MethodHeader ';' super.consumeMethodDeclaration(isNotAbstract); // now we know that we have a method declaration at the top of the ast stack MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr]; // automatically wrap the last statement inside a return statement, if it is an expression // support have to be defined at toplevel only if (this.isTopLevelType()) { int last = methodDecl.statements == null ? -1 : methodDecl.statements.length - 1; if (last >= 0 && methodDecl.statements[last] instanceof Expression) { Expression lastExpression = (Expression) methodDecl.statements[last]; methodDecl.statements[last] = new CodeSnippetReturnStatement( lastExpression, lastExpression.sourceStart, lastExpression.sourceEnd); } } int start = methodDecl.bodyStart - 1, end = start; long position = ((long) start << 32) + end; long[] positions = new long[] {position}; if (this.evaluationContext.localVariableNames != null) { int varCount = this.evaluationContext.localVariableNames.length; // n local decls+ try statement // generate n local variable declarations: [type] [name] = val$[name]; Statement[] newStatements = new Statement[varCount + 1]; for (int i = 0; i < varCount; i++) { char[] trimmedTypeName = this.evaluationContext.localVariableTypeNames[i]; int nameEnd = CharOperation.indexOf('[', trimmedTypeName); if (nameEnd >= 0) { trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd); } nameEnd = CharOperation.indexOf(' ', trimmedTypeName); if (nameEnd >= 0) { trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd); } TypeReference typeReference = new QualifiedTypeReference(CharOperation.splitOn('.', trimmedTypeName), positions); int dimCount = CharOperation.occurencesOf('[', this.evaluationContext.localVariableTypeNames[i]); if (dimCount > 0) { typeReference = this.copyDims(typeReference, dimCount); } NameReference init = new SingleNameReference( CharOperation.concat( LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position); LocalDeclaration declaration = new LocalDeclaration(this.evaluationContext.localVariableNames[i], start, end); declaration.initialization = init; declaration.type = typeReference; declaration.modifiers = this.evaluationContext.localVariableModifiers[i]; newStatements[i] = declaration; } // generate try { [snippet] } finally { [save locals to fields] } // try block TryStatement tryStatement = new TryStatement(); Block tryBlock = new Block(methodDecl.explicitDeclarations); tryBlock.sourceStart = start; tryBlock.sourceEnd = end; tryBlock.statements = methodDecl.statements; // snippet statements tryStatement.tryBlock = tryBlock; // finally block Block finallyBlock = new Block(0); finallyBlock.sourceStart = start; finallyBlock.sourceEnd = end; finallyBlock.statements = new Statement[varCount]; for (int i = 0; i < varCount; i++) { finallyBlock.statements[i] = new Assignment( new SingleNameReference( CharOperation.concat( LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position), new SingleNameReference(this.evaluationContext.localVariableNames[i], position), (int) position); } tryStatement.finallyBlock = finallyBlock; newStatements[varCount] = tryStatement; methodDecl.statements = newStatements; } }
/** Locate declaration in the current class file. This class file is always in a jar. */ public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info) throws CoreException { SearchPattern pattern = locator.pattern; // check annotations references matchAnnotations(pattern, locator, classFile, info); // check class definition BinaryType binaryType = (BinaryType) classFile.getType(); if (matchBinary(pattern, info, null)) { binaryType = new ResolvedBinaryType( (JavaElement) binaryType.getParent(), binaryType.getElementName(), binaryType.getKey()); locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE); return; } // Define arrays to store methods/fields from binary type if necessary IBinaryMethod[] binaryMethods = info.getMethods(); int bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length; IBinaryMethod[] unresolvedMethods = null; char[][] binaryMethodSignatures = null; boolean hasUnresolvedMethods = false; // Get fields from binary type info IBinaryField[] binaryFields = info.getFields(); int bFieldsLength = binaryFields == null ? 0 : binaryFields.length; IBinaryField[] unresolvedFields = null; boolean hasUnresolvedFields = false; // Report as many accurate matches as possible int accuracy = SearchMatch.A_ACCURATE; boolean mustResolve = pattern.mustResolve; if (mustResolve) { BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info); if (binding != null) { // filter out element not in hierarchy scope if (!locator.typeInHierarchy(binding)) return; // Search matches on resolved methods MethodBinding[] availableMethods = binding.availableMethods(); int aMethodsLength = availableMethods == null ? 0 : availableMethods.length; hasUnresolvedMethods = bMethodsLength != aMethodsLength; for (int i = 0; i < aMethodsLength; i++) { MethodBinding method = availableMethods[i]; char[] methodSignature = method.genericSignature(); if (methodSignature == null) methodSignature = method.signature(); // Report the match if possible int level = locator.patternLocator.resolveLevel(method); if (level != PatternLocator.IMPOSSIBLE_MATCH) { IMethod methodHandle = binaryType.getMethod( new String( method.isConstructor() ? binding.compoundName[binding.compoundName.length - 1] : method.selector), CharOperation.toStrings( Signature.getParameterTypes(convertClassFileFormat(methodSignature)))); accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE; locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, accuracy); } // Remove method from unresolved list if (hasUnresolvedMethods) { if (binaryMethodSignatures == null) { // Store binary method signatures to avoid multiple computation binaryMethodSignatures = new char[bMethodsLength][]; for (int j = 0; j < bMethodsLength; j++) { IBinaryMethod binaryMethod = binaryMethods[j]; char[] signature = binaryMethod.getGenericSignature(); if (signature == null) signature = binaryMethod.getMethodDescriptor(); binaryMethodSignatures[j] = signature; } } for (int j = 0; j < bMethodsLength; j++) { if (CharOperation.equals(binaryMethods[j].getSelector(), method.selector) && CharOperation.equals(binaryMethodSignatures[j], methodSignature)) { if (unresolvedMethods == null) { System.arraycopy( binaryMethods, 0, unresolvedMethods = new IBinaryMethod[bMethodsLength], 0, bMethodsLength); } unresolvedMethods[j] = null; break; } } } } // Search matches on resolved fields FieldBinding[] availableFields = binding.availableFields(); int aFieldsLength = availableFields == null ? 0 : availableFields.length; hasUnresolvedFields = bFieldsLength != aFieldsLength; for (int i = 0; i < aFieldsLength; i++) { FieldBinding field = availableFields[i]; // Report the match if possible int level = locator.patternLocator.resolveLevel(field); if (level != PatternLocator.IMPOSSIBLE_MATCH) { IField fieldHandle = binaryType.getField(new String(field.name)); accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE; locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, accuracy); } // Remove the field from unresolved list if (hasUnresolvedFields) { for (int j = 0; j < bFieldsLength; j++) { if (CharOperation.equals(binaryFields[j].getName(), field.name)) { if (unresolvedFields == null) { System.arraycopy( binaryFields, 0, unresolvedFields = new IBinaryField[bFieldsLength], 0, bFieldsLength); } unresolvedFields[j] = null; break; } } } } // If all methods/fields were accurate then returns now if (!hasUnresolvedMethods && !hasUnresolvedFields) { return; } } accuracy = SearchMatch.A_INACCURATE; } // Report inaccurate methods if (mustResolve) binaryMethods = unresolvedMethods; bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length; for (int i = 0; i < bMethodsLength; i++) { IBinaryMethod method = binaryMethods[i]; if (method == null) continue; // impossible match or already reported as accurate if (matchBinary(pattern, method, info)) { char[] name; if (method.isConstructor()) { name = info.getName(); int lastSlash = CharOperation.lastIndexOf('/', name); if (lastSlash != -1) { name = CharOperation.subarray(name, lastSlash + 1, name.length); } } else { name = method.getSelector(); } String selector = new String(name); char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i]; if (methodSignature == null) { methodSignature = method.getGenericSignature(); if (methodSignature == null) methodSignature = method.getMethodDescriptor(); } String[] parameterTypes = CharOperation.toStrings( Signature.getParameterTypes(convertClassFileFormat(methodSignature))); IMethod methodHandle = binaryType.getMethod(selector, parameterTypes); methodHandle = new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey()); locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy); } } // Report inaccurate fields if (mustResolve) binaryFields = unresolvedFields; bFieldsLength = binaryFields == null ? 0 : binaryFields.length; for (int i = 0; i < bFieldsLength; i++) { IBinaryField field = binaryFields[i]; if (field == null) continue; // impossible match or already reported as accurate if (matchBinary(pattern, field, info)) { String fieldName = new String(field.getName()); IField fieldHandle = binaryType.getField(fieldName); fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey()); locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy); } } }
public static char[] getSimpleNameAsCharArray(char[] name) { int index = CharOperation.lastIndexOf('.', name); char[] subarray = CharOperation.subarray(name, index + 1, name.length); subarray = CharOperation.replaceOnCopy(subarray, '$', '.'); return subarray; }