Package org.codehaus.groovy.control

Source Code of org.codehaus.groovy.control.LabelVerifier

/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.control;

import java.util.Iterator;
import java.util.LinkedList;

import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.stmt.BreakStatement;
import org.codehaus.groovy.ast.stmt.ContinueStatement;
import org.codehaus.groovy.ast.stmt.DoWhileStatement;
import org.codehaus.groovy.ast.stmt.ForStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.SwitchStatement;
import org.codehaus.groovy.ast.stmt.WhileStatement;

/**
* This class checks the handling of labels in the AST
*
* @author Jochen Theodorou
*/
public class LabelVerifier extends ClassCodeVisitorSupport {

    private SourceUnit source;
    private LinkedList visitedLabels;
    private LinkedList continueLabels;
    private LinkedList breakLabels;
    boolean inLoop=false;
    boolean inSwitch=false;
   
    public LabelVerifier(SourceUnit src) {
        source = src;
    }
   
    protected SourceUnit getSourceUnit() {
        return source;
    }
   
    private void init(){
        visitedLabels = new LinkedList();
        continueLabels = new LinkedList();
        breakLabels = new LinkedList();
        inLoop=false;
        inSwitch=false;
    }
   
    protected void visitClassCodeContainer(Statement code) {
        init();
        super.visitClassCodeContainer(code);
        assertNoLabelsMissed();
    }
   
   public void visitStatement(Statement statement) {
       String label = statement.getStatementLabel();
      
       if (label!=null) {
           for (Iterator iter = breakLabels.iterator(); iter.hasNext();) {
               BreakStatement element = (BreakStatement) iter.next();
               if (element.getLabel().equals(label)) iter.remove();
           }
          
           for (Iterator iter = continueLabels.iterator(); iter.hasNext();) {
               ContinueStatement element = (ContinueStatement) iter.next();
               if (element.getLabel().equals(label)) iter.remove();
           }
          
           visitedLabels.add(label);
       }
      
       super.visitStatement(statement);
}
   
    public void visitForLoop(ForStatement forLoop) {
        boolean oldInLoop = inLoop;
        inLoop = true;
        super.visitForLoop(forLoop);
        inLoop = oldInLoop;
    }
   
    public void visitDoWhileLoop(DoWhileStatement loop) {
        boolean oldInLoop = inLoop;
        inLoop = true;
        super.visitDoWhileLoop(loop);
        inLoop = oldInLoop;
    }    
   
    public void visitWhileLoop(WhileStatement loop) {
        boolean oldInLoop = inLoop;
        inLoop = true;
        super.visitWhileLoop(loop);
        inLoop = oldInLoop;
    }
   
    public void visitBreakStatement(BreakStatement statement) {
        String label = statement.getLabel();
        boolean hasNamedLabel = label!=null;
        if (!hasNamedLabel && !inLoop && !inSwitch) {
            addError("the break statement is only allowed inside loops or switches",statement);
        } else if (hasNamedLabel && !inLoop) {
            addError("the break statement with named label is only allowed inside loops",statement);
        }
        if (label!=null) {
            boolean found=false;
            for (Iterator iter = visitedLabels.iterator(); iter.hasNext();) {
                String element = (String) iter.next();
                if (element.equals(label)) {
                    found = true;
                    break;
                }
            }
            if (!found) breakLabels.add(statement);
        }
       
        super.visitBreakStatement(statement);
    }
   
    public void visitContinueStatement(ContinueStatement statement) {
        String label = statement.getLabel();
        boolean hasNamedLabel = label!=null;
        if (!hasNamedLabel && !inLoop) {
            addError("the continue statement is only allowed inside loops",statement);
        }
        if (label!=null) {
            boolean found=false;
            for (Iterator iter = visitedLabels.iterator(); iter.hasNext();) {
                String element = (String) iter.next();
                if (element.equals(label)) {
                    found = true;
                    break;
                }
            }
            if (!found) continueLabels.add(statement);
        }
       
        super.visitContinueStatement(statement);
    }
   
    protected void assertNoLabelsMissed() {
        //TODO: report multiple missing labels of the same name only once
        for (Iterator iter = continueLabels.iterator(); iter.hasNext();) {
            ContinueStatement element = (ContinueStatement) iter.next();
            addError("continue to missing label",element);
        }
        for (Iterator iter = breakLabels.iterator(); iter.hasNext();) {
            BreakStatement element = (BreakStatement) iter.next();
            addError("break to missing label",element);
        }
    }
   
    public void visitSwitch(SwitchStatement statement) {
        inSwitch=true;
        super.visitSwitch(statement);
    }

}
TOP

Related Classes of org.codehaus.groovy.control.LabelVerifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.