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); }
/** * 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; } }
/* Take a type and apply annotations to various components of it. By construction when we see the type reference @Outer Outer.@Middle Middle.@Inner Inner, we first construct the binding for Outer.Middle.Inner and then annotate various parts of it. Likewise for PQTR's binding. */ public TypeBinding getAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations) { if (type == null || !type.isValidBinding() || annotations == null || annotations.length == 0) return type; TypeBinding annotatedType = null; switch (type.kind()) { case Binding.ARRAY_TYPE: ArrayBinding arrayBinding = (ArrayBinding) type; annotatedType = getArrayType( arrayBinding.leafComponentType, arrayBinding.dimensions, flattenedAnnotations(annotations)); break; case Binding.BASE_TYPE: case Binding.TYPE: case Binding.GENERIC_TYPE: case Binding.PARAMETERIZED_TYPE: case Binding.RAW_TYPE: case Binding.TYPE_PARAMETER: case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: case Binding.INTERSECTION_CAST_TYPE: /* Taking the binding of QTR as an example, there could be different annotatable components, but we come in a with a single binding, e.g: @T Z; type => Z annotations => [[@T]] @T Y.@T Z type => Z annotations => [[@T][@T]] @T X.@T Y.@T Z type => Z annotations => [[@T][@T][@T]] java.lang.@T X.@T Y.@T Z type => Z annotations => [[][][@T][@T][@T]] in all these cases the incoming type binding is for Z, but annotations are for different levels. We need to align their layout for proper attribution. */ if (type.isUnresolvedType() && CharOperation.indexOf('$', type.sourceName()) > 0) type = BinaryTypeBinding.resolveType( type, this.environment, true); // must resolve member types before asking for enclosingType int levels = type.depth() + 1; TypeBinding[] types = new TypeBinding[levels]; types[--levels] = type; TypeBinding enclosingType = type.enclosingType(); while (enclosingType != null) { types[--levels] = enclosingType; enclosingType = enclosingType.enclosingType(); } // Locate the outermost type being annotated. Beware annotations.length could be > // types.length (for package qualified names in QTR/PQTR) levels = annotations.length; int i, j = types.length - levels; for (i = 0; i < levels; i++, j++) { if (annotations[i] != null && annotations[i].length > 0) break; } if (i == levels) // empty annotations array ? return type; if (j < 0) // Not kosher, broken type that is not flagged as invalid while reporting // compilation error ? don't touch. return type; // types[j] is the first component being annotated. Its annotations are annotations[i] for (enclosingType = j == 0 ? null : types[j - 1]; i < levels; i++, j++) { final TypeBinding currentType = types[j]; // while handling annotations from SE7 locations, take care not to drop existing // annotations. AnnotationBinding[] currentAnnotations = annotations[i] != null && annotations[i].length > 0 ? annotations[i] : currentType.getTypeAnnotations(); annotatedType = getAnnotatedType(currentType, enclosingType, currentAnnotations); enclosingType = annotatedType; } break; default: throw new IllegalStateException(); } return annotatedType; }
@Override public BinaryGenericTypeSignature getTypeErasure() { int end = CharOperation.indexOf(Signature.C_GENERIC_START, chars, offset, offset + length); if (end == -1) return this; return new BinaryErasureTypeSignature(this, getArrayDimensions()); }
private static boolean dependencyExists(IFile buildConfigFile, String dependencyText) throws CoreException { char[] contents = ((CompilationUnit) JavaCore.create(buildConfigFile)).getContents(); return CharOperation.indexOf(dependencyText.toCharArray(), contents, true) >= 0; }