package com.redhat.ceylon.compiler.js;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.redhat.ceylon.compiler.typechecker.model.Annotation;
import com.redhat.ceylon.compiler.typechecker.model.ProducedType;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.AnyAttribute;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.MemberOrTypeExpression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Parameter;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

/** A Visitor that gathers ceylondoc info for each node's declaration.
 * 
 * @author Enrique Zamudio
 */
public class DocVisitor extends Visitor {

    /** Here we store all the docs, as they are encountered */
    private List<String> docs = new ArrayList<String>();
    /** Here we store all the refs to the docs (index in the 'docs' list), keyed by location. */
    private Map<String, Integer> locs = new HashMap<String, Integer>();

    private void retrieveDocs(List<Annotation> annotations, String location) {
        for (Annotation ann : annotations) {
            if ("doc".equals(ann.getName()) && !ann.getPositionalArguments().isEmpty()) {
                String doc = ann.getPositionalArguments().get(0);
                if (doc.charAt(0) == '"' && doc.charAt(doc.length()-1) == '"') {
                    doc = doc.substring(1, doc.length()-1);
                }
                int idx = docs.indexOf(doc);
                if (idx < 0) {
                    idx = docs.size();
                    docs.add(doc);
                }
                locs.put(location, idx);
            }
        }
    }

    //This catches function calls, method/attribute calls, object refs, constructors.
    @Override
    public void visit(MemberOrTypeExpression that) {
        //Can't get location for this
        if (that.getTypeModel() != null && !that.getTypeModel().getTypeArgumentList().isEmpty()) {
            for (ProducedType pt : that.getTypeModel().getTypeArgumentList()) {
                retrieveDocs(pt.getDeclaration().getAnnotations(), that.getLocation());
            }
        }
        retrieveDocs(that.getDeclaration().getAnnotations(), that.getLocation());
        super.visit(that);
    }
    @Override
    public void visit(Parameter that) {
        //function/method def parameters
        retrieveDocs(that.getDeclarationModel().getTypeDeclaration().getAnnotations(), that.getType().getLocation());
        super.visit(that);
    }
    @Override
    public void visit(AnyAttribute that) {
        //local vars
        retrieveDocs(that.getDeclarationModel().getTypeDeclaration().getAnnotations(), that.getType().getLocation());
        super.visit(that);
    }

    /** Returns a list of all the doc values found, in the order they were found. */
    public List<String> getDocs() {
        return docs;
    }
    /** Returns a map of the references to the docs; the keys are the locations in the source code
     * and the values are the index of the doc in the docs list. */
    public Map<String, Integer> getLocations() {
        return locs;
    }

}

@@ -389,38 +389,91 @@
 ee.Tree.
-MemberOrTypeExpression
+AnyMethod;%0Aimport com.redhat.ceylon.compiler.typechecker.tree.Tree.BaseType
 ;%0Aimport
@@ -522,25 +522,38 @@
 ee.Tree.
-Parameter
+MemberOrTypeExpression
 ;%0Aimport
@@ -1058,20 +1058,23 @@
 private 
-void
+boolean
  retriev
@@ -1124,24 +1124,54 @@
 location) %7B%0A
+        boolean rval = false;%0A
         for 
@@ -1727,16 +1727,45 @@
 , idx);%0A
+                rval = true;%0A
         
@@ -1776,24 +1776,45 @@
 %7D%0A        %7D%0A
+        return rval;%0A
     %7D%0A%0A    /
@@ -2282,32 +2282,111 @@
     %7D%0A        %7D%0A
+        if (that.getDeclaration() != null && that.getLocation() != null) %7B%0A    
         retrieve
@@ -2443,32 +2443,42 @@
 getLocation());%0A
+        %7D%0A
         super.vi
@@ -2534,17 +2534,20 @@
 sit(
-Parame
+AnyAttribu
 te
-r
  tha
@@ -2565,36 +2565,16 @@
   //
-function/method def paramete
+local va
 rs%0A 
@@ -2597,35 +2597,38 @@
 ocs(that.get
-Declaration
+Type().getType
 Model().getT
@@ -2618,36 +2618,32 @@
 tTypeModel().get
-Type
 Declaration().ge
@@ -2714,32 +2714,33 @@
 it(that);%0A    %7D%0A
+%0A
     @Override%0A  
@@ -2766,46 +2766,232 @@
 (Any
-Attribute that) %7B%0A        //local vars
+Method that) %7B%0A        retrieveDocs(that.getDeclarationModel().getType().getDeclaration().getAnnotations(), that.getType().getLocation());%0A        super.visit(that);%0A    %7D%0A    @Override%0A    public void visit(BaseType that) %7B
 %0A   
@@ -3042,16 +3042,22 @@
 .getType
+().get
 Declarat
@@ -3084,34 +3084,24 @@
 (), that.get
-Type().get
 Location());
@@ -3092,32 +3092,170 @@
 .getLocation());
+%0A        super.visit(that);%0A    %7D%0A%0A    @Override%0A    public void visit(com.redhat.ceylon.compiler.typechecker.tree.Tree.Annotation that) %7B
 %0A        super.v

Fix doc retrieval for several nodes