/*
 * 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.antlr;

/**
 * Process to decorate antlr AST with ending line/col info, and if
 * possible the snipppet of source from the start/end line/col for each node.
 *
 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
 * @version $Revision$
 */

import antlr.collections.AST;
import java.util.*;

public class AntlrASTProcessSnippets implements AntlrASTProcessor{
    private final SourceBuffer sourceBuffer;

    public AntlrASTProcessSnippets(SourceBuffer sourceBuffer) {
        this.sourceBuffer = sourceBuffer;
    }

    /**
     * decorate antlr AST with ending line/col info, and if
     * possible the snipppet of source from the start/end line/col for each node.
     * @param t the AST to decorate
     * @return the decorated AST
     */
    public AST process(AST t) {
        // first visit
        List l = new ArrayList();
        t = traverse((GroovySourceAST)t,l,null);

        //System.out.println("l:" + l);
        // second visit
        Iterator itr = l.iterator();
        if (itr.hasNext()) { itr.next(); /* discard first */ }
        t = traverse((GroovySourceAST)t,null,itr);
        return t;
    }

    /**
     * traverse an AST node
     * @param t the AST node to traverse
     * @param l A list to add line/col info to
     * @param itr An iterator over a list of line/col
     * @return A decorated AST node
     */
    private AST traverse(GroovySourceAST t,List l,Iterator itr) {
        if (t == null) { return t; }

        // first visit of node
        if (l != null) {
            l.add(new LineColumn(t.getLine(),t.getColumn()));
        }

        // second vist of node
        if (itr != null && itr.hasNext()) {
            LineColumn lc = (LineColumn)itr.next();
            if (t.getLineLast() == 0) {
                int nextLine = lc.getLine();
                int nextColumn = lc.getColumn();
                if (nextLine < t.getLine() || (nextLine == t.getLine() && nextColumn < t.getColumn())) {
                    nextLine = t.getLine();
                    nextColumn = t.getColumn();
                }
                t.setLineLast(nextLine);
                t.setColumnLast(nextColumn);
                // This is a good point to call t.setSnippet(),
                // but it bulks up the AST too much for production code.
            }
        }

        GroovySourceAST child = (GroovySourceAST)t.getFirstChild();
        if (child != null) {
            traverse(child,l,itr);
        }

        GroovySourceAST sibling = (GroovySourceAST)t.getNextSibling();
        if (sibling != null) {
            traverse(sibling,l,itr);
        }

        return t;
    }
}

@@ -1491,36 +1491,32 @@
 yList();%0A       
- t =
  traverse((Groov
@@ -1713,12 +1713,8 @@
     
- t =
  tra
@@ -2074,15 +2074,19 @@
     
-if
+ while
  (t 
-=
+!
 = nu
@@ -2094,22 +2094,14 @@
 l) %7B
- return t; %7D%0A%0A
+%0A     
     
@@ -2131,24 +2131,29 @@
 ode%0A        
+     
 if (l != nul
@@ -2169,16 +2169,21 @@
         
+  
+   
 l.add(ne
@@ -2224,35 +2224,45 @@
 mn()));%0A        
-%7D%0A%0A
+     %7D%0A%0A     
         // secon
@@ -2280,24 +2280,29 @@
 ode%0A        
+  
+   
 if (itr != n
@@ -2337,16 +2337,21 @@
         
+    
+ 
 LineColu
@@ -2390,24 +2390,29 @@
             
+     
 if (t.getLin
@@ -2435,32 +2435,37 @@
                 
+ 
+    
 int nextLine = l
@@ -2469,32 +2469,37 @@
 = lc.getLine();%0A
+     
                 
@@ -2523,32 +2523,37 @@
 lc.getColumn();%0A
+     
                 
@@ -2657,24 +2657,29 @@
             
+ 
+    
 nextLine = t
@@ -2682,32 +2682,37 @@
  = t.getLine();%0A
+     
                 
@@ -2735,32 +2735,37 @@
  t.getColumn();%0A
+     
                 
@@ -2778,24 +2778,29 @@
             
+     
 t.setLineLas
@@ -2812,16 +2812,21 @@
 tLine);%0A
+     
         
@@ -2862,16 +2862,21 @@
 olumn);%0A
+     
         
@@ -2947,16 +2947,21 @@
         
+     
 // but i
@@ -3021,26 +3021,35 @@
         
-%7D%0A
+     %7D%0A    
         
 %7D%0A%0A     
@@ -3032,35 +3032,41 @@
   %7D%0A            
+ 
 %7D%0A%0A
+     
         GroovySo
@@ -3121,24 +3121,29 @@
 ();%0A        
+     
 if (child !=
@@ -3155,32 +3155,37 @@
 ) %7B%0A            
+    
+ 
 traverse(child,l
@@ -3191,32 +3191,37 @@
 l,itr);%0A        
+     
 %7D%0A%0A        Groov
@@ -3219,31 +3219,14 @@
     
-GroovySourceAST sibling
+     t
  = (
@@ -3266,75 +3266,8 @@
 );%0A 
-       if (sibling != null) %7B%0A            traverse(sibling,l,itr);%0A
     

Fix for GROOVY-2816