12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
3bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/**
4bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert*******************************************************************************
5bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert* Copyright (C) 2002-2010, International Business Machines Corporation and    *
6bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert* others. All Rights Reserved.                                                *
7bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert*******************************************************************************
8bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert*/
9bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/**
10bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * This is a tool to check the tags on ICU4J files.  In particular, we're looking for:
11bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
12bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - methods that have no tags
13bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - custom tags: @draft, @stable, @internal?
14bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - standard tags: @since, @deprecated
15bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
16bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Syntax of tags:
17bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@draft ICU X.X.X'
18bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@stable ICU X.X.X'
19bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@internal'
20bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@since  (don't use)'
21bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@obsolete ICU X.X.X'
22bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * '@deprecated to be removed in ICU X.X. [Use ...]'
23bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
24bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * flags names of classes and their members that have no tags or incorrect syntax.
25bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
26bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Requires JDK 1.4 or later
27bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
28bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Use build.xml 'checktags' ant target, or
29bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * run from directory containing CheckTags.class as follows:
30bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * javadoc -classpath ${JAVA_HOME}/lib/tools.jar -doclet CheckTags -sourcepath ${ICU4J_src} [packagenames]
31bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */
32bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
33bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpackage com.ibm.icu.dev.tool.docs;
34bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
35bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ClassDoc;
36bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ConstructorDoc;
37bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ExecutableMemberDoc;
38bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ProgramElementDoc;
39bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.RootDoc;
40bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.Tag;
41bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
42bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpublic class CheckTags {
43bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    RootDoc root;
44bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean log;
45bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean brief;
46bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean isShort;
47bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    DocStack stack = new DocStack();
48bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
49bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    class DocNode {
50bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private String header;
51bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private boolean printed;
52bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private boolean reportError;
53bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private int errorCount;
54bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
55bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        public void reset(String header, boolean reportError) {
56bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            this.header = header;
57bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            this.printed = false;
58bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            this.errorCount = 0;
59bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            this.reportError = reportError;
60bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
61bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        public String toString() {
62bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return header +
63bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                " printed: " + printed +
64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                " reportError: " + reportError +
65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                " errorCount: " + errorCount;
66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    class DocStack {
70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private DocNode[] stack;
71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private int index;
72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        private boolean newline;
73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
74bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        public void push(String header, boolean reportError) {
75bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (stack == null) {
76bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                stack = new DocNode[5];
77bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else {
78bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (index == stack.length) {
79bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    DocNode[] temp = new DocNode[stack.length * 2];
80bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    System.arraycopy(stack, 0, temp, 0, index);
81bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    stack = temp;
82bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
83bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
84bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (stack[index] == null) {
85bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                stack[index] = new DocNode();
86bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
87bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //  System.out.println("reset [" + index + "] header: " + header + " report: " + reportError);
88bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            stack[index++].reset(header, reportError);
89bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
90bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
91bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        public void pop() {
92bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (index == 0) {
93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                throw new IndexOutOfBoundsException();
94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            --index;
96bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
97bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int ec = stack[index].errorCount; // index already decremented
98bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (ec > 0 || index == 0) { // always report for outermost element
99bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (stack[index].reportError) {
100bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    output("(" + ec + (ec == 1 ? " error" : " errors") + ")", false, true, index);
101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // propagate to parent
104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (index > 0) {
105bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    stack[index-1].errorCount += ec;
106bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
107bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
108bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (index == 0) {
109bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                System.out.println(); // always since we always report number of errors
110bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
111bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
112bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
113bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        public void output(String msg, boolean error, boolean newline) {
114bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            output(msg, error, newline, index-1);
115bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
116bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
117bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        void output(String msg, boolean error, boolean newline, int ix) {
118bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            DocNode last = stack[ix];
119bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (error) {
120bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                last.errorCount += 1;
121bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
122bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
123bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            boolean show = !brief || last.reportError;
124bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // boolean nomsg = show && brief && error;
125bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //            System.out.println(">>> " + last + " error: " + error + " show: " + show + " nomsg: " + nomsg);
126bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
127bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (show) {
128bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (isShort || (brief && error)) {
129bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    msg = null; // nuke error messages if we're brief, just report headers and totals
130bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
131bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                for (int i = 0; i <= ix;) {
132bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    DocNode n = stack[i];
133bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (n.printed) {
134bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        if (msg != null || !last.printed) { // since index > 0 last is not null
135bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            if (this.newline && i == 0) {
136bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                                System.out.println();
137bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                                this.newline = false;
138bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            }
139bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            System.out.print("  ");
140bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        }
141bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        ++i;
142bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } else {
143bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        System.out.print(n.header);
144bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        n.printed = true;
145bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        this.newline = true;
146bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        i = 0;
147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
149bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (msg != null) {
151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (index == 0 && this.newline) {
152bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        System.out.println();
153bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
154bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (error) {
155bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        System.out.print("*** ");
156bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
157bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    System.out.print(msg);
158bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
159bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
160bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
161bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            this.newline = newline;
162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
164bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
165bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static boolean start(RootDoc root) {
166bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return new CheckTags(root).run();
167bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
168bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
169bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static int optionLength(String option) {
170bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (option.equals("-log")) {
171bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
172bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-brief")) {
173bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
174bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-short")) {
175bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
176bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
177bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return 0;
178bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
179bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
180bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    CheckTags(RootDoc root) {
181bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        this.root = root;
182bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
183bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String[][] options = root.options();
184bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < options.length; ++i) {
185bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String opt = options[i][0];
186bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (opt.equals("-log")) {
187bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.log = true;
188bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-brief")) {
189bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.brief = true;
190bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-short")) {
191bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.isShort = true;
192bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
193bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
194bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
195bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
196bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean run() {
197bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        doDocs(root.classes(), "Package", true);
198bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
199bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
200bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
201bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final String[] tagKinds = {
202bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        "@internal", "@draft", "@stable", "@since", "@deprecated", "@author", "@see", "@version",
203bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        "@param", "@return", "@throws", "@obsolete", "@exception", "@serial", "@provisional"
204bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    };
205bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
206bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int UNKNOWN = -1;
207bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int INTERNAL = 0;
208bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int DRAFT = 1;
209bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int STABLE = 2;
210bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int SINCE = 3;
211bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int DEPRECATED = 4;
212bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int AUTHOR = 5;
213bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int SEE = 6;
214bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int VERSION = 7;
215bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int PARAM = 8;
216bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int RETURN = 9;
217bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int THROWS = 10;
218bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int OBSOLETE = 11;
219bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int EXCEPTION = 12;
220bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int SERIAL = 13;
221bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int PROVISIONAL = 14;
222bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
223bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static int tagKindIndex(String kind) {
224bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < tagKinds.length; ++i) {
225bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (kind.equals(tagKinds[i])) {
226bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return i;
227bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
228bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
229bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return UNKNOWN;
230bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
231bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
232bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final String[] icuTagNames = {
233bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        "@icu", "@icunote", "@icuenhanced"
234bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    };
235bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int ICU = 0;
236bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int ICUNOTE = 1;
237bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static final int ICUENHANCED = 2;
238bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    static int icuTagIndex(String name) {
239bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < icuTagNames.length; ++i) {
240bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (icuTagNames[i].equals(name)) {
241bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return i;
242bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
243bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
244bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return UNKNOWN;
245bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
246bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
247bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean newline = false;
248bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
249bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void output(String msg, boolean error, boolean newline) {
250bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        stack.output(msg, error, newline);
251bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
252bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
253bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void log() {
254bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(null, false, false);
255bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
256bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
257bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void logln() {
258bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(null, false, true);
259bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
260bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
261bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void log(String msg) {
262bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(msg, false, false);
263bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
264bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
265bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void logln(String msg) {
266bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(msg, false, true);
267bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
268bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
269bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void err(String msg) {
270bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(msg, true, false);
271bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
272bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
273bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void errln(String msg) {
274bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        output(msg, true, true);
275bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
276bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
277bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void tagErr(String msg, Tag tag) {
278bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Tag.position() requires JDK 1.4, build.xml tests for this
279bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (msg.length() > 0) {
280bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            msg += ": ";
281bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
282bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        errln(msg + tag.toString() + " [" + tag.position() + "]");
283bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    };
284bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
285bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void tagErr(Tag tag) {
286bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        tagErr("", tag);
287bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
288bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
289bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void doDocs(ProgramElementDoc[] docs, String header, boolean reportError) {
290bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (docs != null && docs.length > 0) {
291bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            stack.push(header, reportError);
292bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int i = 0; i < docs.length; ++i) {
293bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDoc(docs[i]);
294bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
295bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            stack.pop();
296bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
297bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
298bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
299bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void doDoc(ProgramElementDoc doc) {
300bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc != null && (doc.isPublic() || doc.isProtected())
301bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            && !(doc instanceof ConstructorDoc && ((ConstructorDoc)doc).isSynthetic())) {
302bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
303bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // unfortunately, in JDK 1.4.1 MemberDoc.isSynthetic is not properly implemented for
304bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // synthetic constructors.  So you'll have to live with spurious errors or 'implement'
305bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // the synthetic constructors...
306bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
307bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            boolean isClass = doc.isClass() || doc.isInterface();
308bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String header;
309bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (!isShort || isClass) {
310bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                header = "--- ";
311bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else {
312bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                header = "";
313bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
314bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            header += (isClass ? doc.qualifiedName() : doc.name());
315bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (doc instanceof ExecutableMemberDoc) {
316bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                header += ((ExecutableMemberDoc)doc).flatSignature();
317bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
318bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (!isShort || isClass) {
319bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                header += " ---";
320bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
321bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            stack.push(header, isClass);
322bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (log) {
323bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                logln();
324bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
325bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            boolean recurse = doTags(doc);
326bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (recurse && isClass) {
327bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                ClassDoc cdoc = (ClassDoc)doc;
328bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDocs(cdoc.fields(), "Fields", !brief);
329bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDocs(cdoc.constructors(), "Constructors", !brief);
330bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDocs(cdoc.methods(), "Methods", !brief);
331bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
332bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            stack.pop();
333bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
334bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
335bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
336bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    /** Return true if subelements of this doc should be checked */
337bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean doTags(ProgramElementDoc doc) {
338bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundRequiredTag = false;
339bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundDraftTag = false;
340bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundProvisionalTag = false;
341bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundDeprecatedTag = false;
342bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundObsoleteTag = false;
343bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundInternalTag = false;
344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean foundStableTag = false;
345bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        boolean retainAll = false;
346bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
347bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // first check inline tags
348bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (Tag tag : doc.inlineTags()) {
349bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int index = icuTagIndex(tag.name());
350bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (index >= 0) {
351bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                String text = tag.text().trim();
352bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                switch (index) {
353bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                case ICU: {
354bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (doc.isClass() || doc.isInterface()) {
355bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        tagErr("tag should appear only in member docs", tag);
356bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
357bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } break;
358bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                case ICUNOTE: {
359bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (text.length() > 0) {
360bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        tagErr("tag should not contain text", tag);
361bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
362bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } break;
363bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                case ICUENHANCED: {
364bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (text.length() == 0) {
365bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        tagErr("text should name related jdk class", tag);
366bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
367bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (!(doc.isClass() || doc.isInterface())) {
368bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        tagErr("tag should appear only in class/interface docs", tag);
369bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
370bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } break;
371bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                default:
372bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    tagErr("unrecognized tag index for tag", tag);
373bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    break;
374bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
375bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
376bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
377bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
378bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // next check regular tags
379bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (Tag tag : doc.tags()) {
380bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String kind = tag.kind();
381bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int ix = tagKindIndex(kind);
382bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
383bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            switch (ix) {
384bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case UNKNOWN:
385bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                errln("unknown kind: " + kind);
386bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
387bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
388bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case INTERNAL:
389bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundRequiredTag = true;
390bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundInternalTag = true;
391bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
392bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
393bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DRAFT:
394bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundRequiredTag = true;
395bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundDraftTag = true;
396bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tag.text().indexOf("ICU 2.8") != -1 &&
397bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    tag.text().indexOf("(retain") == -1) { // catch both retain and retainAll
398bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    tagErr(tag);
399bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    break;
400bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
401bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tag.text().indexOf("ICU") != 0) {
402bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    tagErr(tag);
403bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    break;
404bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
405bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                retainAll |= (tag.text().indexOf("(retainAll)") != -1);
406bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
407bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
408bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case PROVISIONAL:
409bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundProvisionalTag = true;
410bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
411bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
412bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DEPRECATED:
413bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundDeprecatedTag = true;
414bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tag.text().indexOf("ICU") == 0) {
415bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    foundRequiredTag = true;
416bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
417bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
418bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
419bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case OBSOLETE:
420bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tag.text().indexOf("ICU") != 0) {
421bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    tagErr(tag);
422bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
423bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundObsoleteTag = true;
424bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                foundRequiredTag = true;
425bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
426bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
427bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case STABLE:
428bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                {
429bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    String text = tag.text();
430bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (text.length() != 0 && text.indexOf("ICU") != 0) {
431bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        tagErr(tag);
432bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
433bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    foundRequiredTag = true;
434bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    foundStableTag = true;
435bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
436bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
437bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
438bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SINCE:
439bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                tagErr(tag);
440bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
441bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
442bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case EXCEPTION:
443bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                logln("You really ought to use @throws, you know... :-)");
444bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
445bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case AUTHOR:
446bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SEE:
447bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case PARAM:
448bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case RETURN:
449bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case THROWS:
450bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SERIAL:
451bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
452bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
453bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case VERSION:
454bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                tagErr(tag);
455bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
456bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
457bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            default:
458bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                errln("unknown index: " + ix);
459bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
460bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
461bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (!foundRequiredTag) {
462bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            errln("missing required tag [" + doc.position() + "]");
463bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
464bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (foundInternalTag && !foundDeprecatedTag) {
465bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            errln("internal tag missing deprecated");
466bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
467bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (foundDraftTag && !(foundDeprecatedTag || foundProvisionalTag)) {
468bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            errln("draft tag missing deprecated or provisional");
469bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
470bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (foundObsoleteTag && !foundDeprecatedTag) {
471bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            errln("obsolete tag missing deprecated");
472bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
473bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (foundStableTag && foundDeprecatedTag) {
474bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            logln("stable deprecated");
475bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
476bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
477bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return !retainAll;
478bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
479bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert}
480