/* * Record a statement - regular method should have been created a block body */ public RecoveredElement add(Statement statement, int bracketBalanceValue) { this.resetPendingModifiers(); /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (methodDeclaration.declarationSourceEnd != 0 && statement.sourceStart > methodDeclaration.declarationSourceEnd) { if (this.parent == null) { return this; // ignore } else { return this.parent.add(statement, bracketBalanceValue); } } if (methodBody == null) { Block block = new Block(0); block.sourceStart = methodDeclaration.bodyStart; RecoveredElement currentBlock = this.add(block, 1); if (this.bracketBalance > 0) { for (int i = 0; i < this.bracketBalance - 1; i++) { currentBlock = currentBlock.add(new Block(0), 1); } this.bracketBalance = 1; } return currentBlock.add(statement, bracketBalanceValue); } return methodBody.add(statement, bracketBalanceValue, true); }
/* * Record a local declaration - regular method should have been created a block body */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { this.resetPendingModifiers(); /* local variables inside method can only be final and non void */ /* char[][] localTypeName; if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final || (localDeclaration.type == null) // initializer || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ if (this.parent == null){ return this; // ignore } else { this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1)); return this.parent.add(localDeclaration, bracketBalance); } } */ /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (methodDeclaration.declarationSourceEnd != 0 && localDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd) { if (this.parent == null) { return this; // ignore } else { return this.parent.add(localDeclaration, bracketBalanceValue); } } if (methodBody == null) { Block block = new Block(0); block.sourceStart = methodDeclaration.bodyStart; RecoveredElement currentBlock = this.add(block, 1); if (this.bracketBalance > 0) { for (int i = 0; i < this.bracketBalance - 1; i++) { currentBlock = currentBlock.add(new Block(0), 1); } this.bracketBalance = 1; } return currentBlock.add(localDeclaration, bracketBalanceValue); } return methodBody.add(localDeclaration, bracketBalanceValue, true); }
/** * 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; } }
public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (methodDeclaration.declarationSourceEnd != 0 && typeDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd) { if (this.parent == null) { return this; // ignore } return this.parent.add(typeDeclaration, bracketBalanceValue); } if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated) { if (methodBody == null) { Block block = new Block(0); block.sourceStart = methodDeclaration.bodyStart; this.add(block, 1); } methodBody.attachPendingModifiers( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); this.resetPendingModifiers(); return methodBody.add(typeDeclaration, bracketBalanceValue, true); } switch (TypeDeclaration.kind(typeDeclaration.modifiers)) { case TypeDeclaration.INTERFACE_DECL: case TypeDeclaration.ANNOTATION_TYPE_DECL: resetPendingModifiers(); this.updateSourceEndIfNecessary( this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1)); if (this.parent == null) { return this; // ignore } // close the constructor return this.parent.add(typeDeclaration, bracketBalanceValue); } if (localTypes == null) { localTypes = new RecoveredType[5]; localTypeCount = 0; } else { if (localTypeCount == localTypes.length) { System.arraycopy( localTypes, 0, (localTypes = new RecoveredType[2 * localTypeCount]), 0, localTypeCount); } } RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); localTypes[localTypeCount++] = element; if (this.pendingAnnotationCount > 0) { element.attach( pendingAnnotations, pendingAnnotationCount, pendingModifiers, pendingModifersSourceStart); } this.resetPendingModifiers(); /* consider that if the opening brace was not found, it is there */ if (!foundOpeningBrace) { foundOpeningBrace = true; this.bracketBalance++; } return element; }