1/*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug     4994049
27 * @summary Unit test for SourcePosition.column with respect to tab expansion
28 * @author  Peter von der Ah\u00e9
29 * @modules jdk.javadoc/jdk.javadoc.internal.tool
30 * @run main T4994049 FileWithTabs.java
31 */
32
33import java.io.*;
34import java.util.ArrayList;
35import java.util.Collections;
36import java.util.List;
37import java.util.Locale;
38import java.util.Set;
39
40import javax.lang.model.SourceVersion;
41import javax.lang.model.element.ElementKind;
42import javax.lang.model.element.ExecutableElement;
43import javax.lang.model.element.TypeElement;
44import javax.lang.model.util.ElementFilter;
45
46import com.sun.source.tree.CompilationUnitTree;
47import com.sun.source.tree.LineMap;
48import com.sun.source.util.DocTrees;
49import com.sun.source.util.SourcePositions;
50import com.sun.source.util.TreePath;
51import jdk.javadoc.doclet.Doclet;
52import jdk.javadoc.doclet.Reporter;
53import jdk.javadoc.doclet.DocletEnvironment;
54
55import static jdk.javadoc.internal.tool.Main.execute;
56
57public class T4994049 implements Doclet {
58
59    public boolean run(DocletEnvironment root) {
60        DocTrees trees = root.getDocTrees();
61
62        SourcePositions sourcePositions = trees.getSourcePositions();
63        for (TypeElement klass : ElementFilter.typesIn(root.getIncludedElements())) {
64            for (ExecutableElement method : getMethods(klass)) {
65                if (method.getSimpleName().toString().equals("tabbedMethod")) {
66                    TreePath path = trees.getPath(method);
67                    CompilationUnitTree cu = path.getCompilationUnit();
68                    long pos = sourcePositions.getStartPosition(cu, path.getLeaf());
69                    LineMap lineMap = cu.getLineMap();
70                    long columnNumber = lineMap.getColumnNumber(pos);
71                    if (columnNumber == 9) {
72                        System.out.println(columnNumber + ": OK!");
73                        return true;
74                    } else {
75                        System.err.println(columnNumber + ": wrong tab expansion");
76                        return false;
77                    }
78                }
79            }
80        }
81        return false;
82    }
83
84    public static void main(String... args) throws Exception {
85        File testSrc = new File(System.getProperty("test.src"));
86        File tmpSrc = new File("tmpSrc");
87        initTabs(testSrc, tmpSrc);
88
89
90        for (String file : args) {
91            File source = new File(tmpSrc, file);
92            String[] array = {
93                "-docletpath", System.getProperty("test.classes", "."),
94                "-doclet", "T4994049",
95                source.getPath()
96            };
97            int rc = execute(array);
98            if (rc != 0)
99                throw new Error("Unexpected return code from javadoc: " + rc);
100        }
101    }
102
103    static void initTabs(File from, File to) throws IOException {
104        for (File f: from.listFiles()) {
105            File t = new File(to, f.getName());
106            if (f.isDirectory()) {
107                initTabs(f, t);
108            } else if (f.getName().endsWith(".java")) {
109                write(t, read(f).replace("\\t", "\t"));
110            }
111        }
112    }
113
114    static String read(File f) throws IOException {
115        StringBuilder sb = new StringBuilder();
116        try (BufferedReader in = new BufferedReader(new FileReader(f))) {
117            String line;
118            while ((line = in.readLine()) != null) {
119                sb.append(line);
120                sb.append("\n");
121            }
122        }
123        return sb.toString();
124    }
125
126    static void write(File f, String s) throws IOException {
127        f.getParentFile().mkdirs();
128        try (Writer out = new FileWriter(f)) {
129            out.write(s);
130        }
131    }
132
133    List<ExecutableElement> getMethods(TypeElement klass) {
134        List<ExecutableElement> methods = new ArrayList<>();
135        klass.getEnclosedElements()
136                .stream()
137                .filter((e) -> (e.getKind() == ElementKind.METHOD))
138                .forEach((e) -> {
139                    methods.add((ExecutableElement) e);
140                });
141        return methods;
142    }
143
144    @Override
145    public String getName() {
146        return "Test";
147    }
148
149    @Override
150    public Set<Option> getSupportedOptions() {
151        return Collections.emptySet();
152    }
153
154    @Override
155    public SourceVersion getSupportedSourceVersion() {
156        return SourceVersion.latest();
157    }
158
159    @Override
160    public void init(Locale locale, Reporter reporter) {
161        return;
162    }
163}
164