001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.internal.compiler.ASTVisitor;
013: import org.eclipse.jdt.internal.compiler.flow.*;
014: import org.eclipse.jdt.internal.compiler.lookup.*;
015:
016: public class BreakStatement extends BranchStatement {
017:
018: public BreakStatement(char[] label, int sourceStart, int e) {
019: super (label, sourceStart, e);
020: }
021:
022: public FlowInfo analyseCode(BlockScope currentScope,
023: FlowContext flowContext, FlowInfo flowInfo) {
024:
025: // here requires to generate a sequence of finally blocks invocations depending corresponding
026: // to each of the traversed try statements, so that execution will terminate properly.
027:
028: // lookup the label, this should answer the returnContext
029: FlowContext targetContext = (this .label == null) ? flowContext
030: .getTargetContextForDefaultBreak() : flowContext
031: .getTargetContextForBreakLabel(this .label);
032:
033: if (targetContext == null) {
034: if (this .label == null) {
035: currentScope.problemReporter().invalidBreak(this );
036: } else {
037: currentScope.problemReporter().undefinedLabel(this );
038: }
039: return flowInfo; // pretend it did not break since no actual target
040: }
041:
042: this .initStateIndex = currentScope.methodScope()
043: .recordInitializationStates(flowInfo);
044:
045: this .targetLabel = targetContext.breakLabel();
046: FlowContext traversedContext = flowContext;
047: int subCount = 0;
048: this .subroutines = new SubRoutineStatement[5];
049:
050: do {
051: SubRoutineStatement sub;
052: if ((sub = traversedContext.subroutine()) != null) {
053: if (subCount == this .subroutines.length) {
054: System
055: .arraycopy(
056: this .subroutines,
057: 0,
058: (this .subroutines = new SubRoutineStatement[subCount * 2]),
059: 0, subCount); // grow
060: }
061: this .subroutines[subCount++] = sub;
062: if (sub.isSubRoutineEscaping()) {
063: break;
064: }
065: }
066: traversedContext.recordReturnFrom(flowInfo
067: .unconditionalInits());
068: traversedContext.recordBreakTo(targetContext);
069:
070: if (traversedContext instanceof InsideSubRoutineFlowContext) {
071: ASTNode node = traversedContext.associatedNode;
072: if (node instanceof TryStatement) {
073: TryStatement tryStatement = (TryStatement) node;
074: flowInfo
075: .addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
076: }
077: } else if (traversedContext == targetContext) {
078: // only record break info once accumulated through subroutines, and only against target context
079: targetContext.recordBreakFrom(flowInfo);
080: break;
081: }
082: } while ((traversedContext = traversedContext.parent) != null);
083:
084: // resize subroutines
085: if (subCount != this .subroutines.length) {
086: System
087: .arraycopy(
088: this .subroutines,
089: 0,
090: (this .subroutines = new SubRoutineStatement[subCount]),
091: 0, subCount);
092: }
093: return FlowInfo.DEAD_END;
094: }
095:
096: public StringBuffer printStatement(int tab, StringBuffer output) {
097: printIndent(tab, output).append("break "); //$NON-NLS-1$
098: if (this .label != null)
099: output.append(this .label);
100: return output.append(';');
101: }
102:
103: public void traverse(ASTVisitor visitor, BlockScope blockscope) {
104: visitor.visit(this, blockscope);
105: visitor.endVisit(this, blockscope);
106: }
107: }
|