xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/search/Results.java (revision d6df19e1b22784c78f567cf74c42f18e3901b900)
1b5840353SAdam Hornáček /*
2b5840353SAdam Hornáček  * CDDL HEADER START
3b5840353SAdam Hornáček  *
4b5840353SAdam Hornáček  * The contents of this file are subject to the terms of the
5b5840353SAdam Hornáček  * Common Development and Distribution License (the "License").
6b5840353SAdam Hornáček  * You may not use this file except in compliance with the License.
7b5840353SAdam Hornáček  *
8b5840353SAdam Hornáček  * See LICENSE.txt included in this distribution for the specific
9b5840353SAdam Hornáček  * language governing permissions and limitations under the License.
10b5840353SAdam Hornáček  *
11b5840353SAdam Hornáček  * When distributing Covered Code, include this CDDL HEADER in each
12b5840353SAdam Hornáček  * file and include the License file at LICENSE.txt.
13b5840353SAdam Hornáček  * If applicable, add the following below this CDDL HEADER, with the
14b5840353SAdam Hornáček  * fields enclosed by brackets "[]" replaced with your own identifying
15b5840353SAdam Hornáček  * information: Portions Copyright [yyyy] [name of copyright owner]
16b5840353SAdam Hornáček  *
17b5840353SAdam Hornáček  * CDDL HEADER END
18b5840353SAdam Hornáček  */
19b5840353SAdam Hornáček 
20b5840353SAdam Hornáček /*
21c6f0939bSAdam Hornacek  * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
225d9f3aa0SAdam Hornáček  * Portions Copyright (c) 2011, Jens Elkner.
235d9f3aa0SAdam Hornáček  * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>.
24b5840353SAdam Hornáček  */
259805b761SAdam Hornáček package org.opengrok.indexer.search;
26b5840353SAdam Hornáček 
2757eefa47SKryštof Tulinger import static org.opengrok.indexer.web.messages.MessagesContainer.MESSAGES_MAIN_PAGE_TAG;
2857eefa47SKryštof Tulinger 
29b5840353SAdam Hornáček import java.io.BufferedReader;
30b5840353SAdam Hornáček import java.io.File;
31b5840353SAdam Hornáček import java.io.FileInputStream;
32b5840353SAdam Hornáček import java.io.IOException;
33b5840353SAdam Hornáček import java.io.Reader;
34b5840353SAdam Hornáček import java.io.Writer;
35b5840353SAdam Hornáček import java.nio.charset.StandardCharsets;
36b5840353SAdam Hornáček import java.text.DateFormat;
37b5840353SAdam Hornáček import java.text.ParseException;
38b5840353SAdam Hornáček import java.util.ArrayList;
39b5840353SAdam Hornáček import java.util.LinkedHashMap;
40b5840353SAdam Hornáček import java.util.Map;
41b5840353SAdam Hornáček import java.util.logging.Level;
42b5840353SAdam Hornáček import java.util.logging.Logger;
43b5840353SAdam Hornáček import java.util.zip.GZIPInputStream;
44b5840353SAdam Hornáček import org.apache.lucene.analysis.charfilter.HTMLStripCharFilter;
45b5840353SAdam Hornáček import org.apache.lucene.document.DateTools;
46b5840353SAdam Hornáček import org.apache.lucene.document.Document;
47b5840353SAdam Hornáček import org.apache.lucene.index.CorruptIndexException;
48b5840353SAdam Hornáček import org.apache.lucene.index.IndexableField;
49b5840353SAdam Hornáček import org.apache.lucene.search.IndexSearcher;
50b5840353SAdam Hornáček import org.apache.lucene.search.ScoreDoc;
5157eefa47SKryštof Tulinger import org.opengrok.indexer.analysis.AbstractAnalyzer;
529805b761SAdam Hornáček import org.opengrok.indexer.analysis.Definitions;
539805b761SAdam Hornáček import org.opengrok.indexer.analysis.Scopes;
549805b761SAdam Hornáček import org.opengrok.indexer.configuration.Project;
559805b761SAdam Hornáček import org.opengrok.indexer.configuration.RuntimeEnvironment;
569805b761SAdam Hornáček import org.opengrok.indexer.history.HistoryException;
579805b761SAdam Hornáček import org.opengrok.indexer.logger.LoggerFactory;
58ae1c323bSVladimir Kotal import org.opengrok.indexer.search.context.HistoryContext;
599805b761SAdam Hornáček import org.opengrok.indexer.util.IOUtils;
604da26a1eSChris Fraire import org.opengrok.indexer.util.TandemPath;
619805b761SAdam Hornáček import org.opengrok.indexer.web.Prefix;
629805b761SAdam Hornáček import org.opengrok.indexer.web.SearchHelper;
639805b761SAdam Hornáček import org.opengrok.indexer.web.Util;
643db691beSVladimir Kotal import org.opengrok.indexer.web.messages.MessagesUtils;
653db691beSVladimir Kotal 
66b5840353SAdam Hornáček /**
67b5840353SAdam Hornáček  * @author Chandan slightly rewritten by Lubos Kosco
68b5840353SAdam Hornáček  */
69b5840353SAdam Hornáček public final class Results {
70b5840353SAdam Hornáček 
71b5840353SAdam Hornáček     private static final Logger LOGGER = LoggerFactory.getLogger(Results.class);
72b5840353SAdam Hornáček 
Results()73b5840353SAdam Hornáček     private Results() {
74b5840353SAdam Hornáček         // Util class, should not be constructed
75b5840353SAdam Hornáček     }
76b5840353SAdam Hornáček 
77b5840353SAdam Hornáček     /**
78b5840353SAdam Hornáček      * Create a has map keyed by the directory of the document found.
79b5840353SAdam Hornáček      *
80b5840353SAdam Hornáček      * @param searcher searcher to use.
81b5840353SAdam Hornáček      * @param hits hits produced by the given searcher's search
82b5840353SAdam Hornáček      * @param startIdx the index of the first hit to check
83b5840353SAdam Hornáček      * @param stopIdx the index of the last hit to check
84b5840353SAdam Hornáček      * @return a (directory, hitDocument) hashmap
85b5840353SAdam Hornáček      * @throws CorruptIndexException
86b5840353SAdam Hornáček      * @throws IOException
87b5840353SAdam Hornáček      */
createMap( IndexSearcher searcher, ScoreDoc[] hits, int startIdx, long stopIdx)88b5840353SAdam Hornáček     private static Map<String, ArrayList<Integer>> createMap(
89b5840353SAdam Hornáček         IndexSearcher searcher, ScoreDoc[] hits, int startIdx, long stopIdx)
90b5840353SAdam Hornáček             throws CorruptIndexException, IOException {
91b5840353SAdam Hornáček 
92b5840353SAdam Hornáček         LinkedHashMap<String, ArrayList<Integer>> dirHash =
93b5840353SAdam Hornáček                 new LinkedHashMap<>();
94b5840353SAdam Hornáček         for (int i = startIdx; i < stopIdx; i++) {
95b5840353SAdam Hornáček             int docId = hits[i].doc;
96b5840353SAdam Hornáček             Document doc = searcher.doc(docId);
97b5840353SAdam Hornáček 
98b5840353SAdam Hornáček             String rpath = doc.get(QueryBuilder.PATH);
99b5840353SAdam Hornáček             if (rpath == null) {
100b5840353SAdam Hornáček                 continue;
101b5840353SAdam Hornáček             }
102b5840353SAdam Hornáček 
103b5840353SAdam Hornáček             String parent = rpath.substring(0, rpath.lastIndexOf('/'));
104c6f0939bSAdam Hornacek             ArrayList<Integer> dirDocs = dirHash.computeIfAbsent(parent, k -> new ArrayList<>());
105b5840353SAdam Hornáček             dirDocs.add(docId);
106b5840353SAdam Hornáček         }
107b5840353SAdam Hornáček         return dirHash;
108b5840353SAdam Hornáček     }
109b5840353SAdam Hornáček 
getTags(File basedir, String path, boolean compressed)110b5840353SAdam Hornáček     private static String getTags(File basedir, String path, boolean compressed) {
111b5840353SAdam Hornáček         char[] content = new char[1024 * 8];
112b5840353SAdam Hornáček         try (HTMLStripCharFilter r = new HTMLStripCharFilter(getXrefReader(basedir, path, compressed))) {
113b5840353SAdam Hornáček             int len = r.read(content);
114b5840353SAdam Hornáček             return new String(content, 0, len);
115b5840353SAdam Hornáček         } catch (Exception e) {
1164da26a1eSChris Fraire             String fnm = compressed ? TandemPath.join(basedir + path, ".gz") :
1174da26a1eSChris Fraire                     basedir + path;
1184da26a1eSChris Fraire             LOGGER.log(Level.WARNING, "An error reading tags from " + fnm, e);
119b5840353SAdam Hornáček         }
120b5840353SAdam Hornáček         return "";
121b5840353SAdam Hornáček     }
122b5840353SAdam Hornáček 
123b5840353SAdam Hornáček     /** Return a reader for the specified xref file. */
getXrefReader( File basedir, String path, boolean compressed)124b5840353SAdam Hornáček     private static Reader getXrefReader(
125b5840353SAdam Hornáček                     File basedir, String path, boolean compressed)
126b5840353SAdam Hornáček             throws IOException {
1274da26a1eSChris Fraire         /*
128b5840353SAdam Hornáček          * For backward compatibility, read the OpenGrok-produced document
129b5840353SAdam Hornáček          * using the system default charset.
130b5840353SAdam Hornáček          */
131b5840353SAdam Hornáček         if (compressed) {
132b5840353SAdam Hornáček             return new BufferedReader(IOUtils.createBOMStrippedReader(
1334da26a1eSChris Fraire                     new GZIPInputStream(new FileInputStream(new File(basedir,
1344da26a1eSChris Fraire                             TandemPath.join(path, ".gz"))))));
135b5840353SAdam Hornáček         } else {
136b5840353SAdam Hornáček             return new BufferedReader(IOUtils.createBOMStrippedReader(
137b5840353SAdam Hornáček                     new FileInputStream(new File(basedir, path))));
138b5840353SAdam Hornáček         }
139b5840353SAdam Hornáček     }
140b5840353SAdam Hornáček 
141b5840353SAdam Hornáček     /**
142b5840353SAdam Hornáček      * Prints out results in html form. The following search helper fields are
143b5840353SAdam Hornáček      * required to be properly initialized: <ul>
144b5840353SAdam Hornáček      * <li>{@link SearchHelper#dataRoot}</li>
145b5840353SAdam Hornáček      * <li>{@link SearchHelper#contextPath}</li>
146b5840353SAdam Hornáček      * <li>{@link SearchHelper#searcher}</li> <li>{@link SearchHelper#hits}</li>
147b5840353SAdam Hornáček      * <li>{@link SearchHelper#historyContext} (ignored if {@code null})</li>
148b5840353SAdam Hornáček      * <li>{@link SearchHelper#sourceContext} (ignored if {@code null})</li>
149b5840353SAdam Hornáček      * <li>{@link SearchHelper#summarizer} (if sourceContext is not
150384ec09dSChris Fraire      * {@code null})</li> <li>{@link SearchHelper#sourceRoot} (if
151b5840353SAdam Hornáček      * sourceContext or historyContext is not {@code null})</li> </ul>
152b5840353SAdam Hornáček      *
153b5840353SAdam Hornáček      * @param out write destination
154b5840353SAdam Hornáček      * @param sh search helper which has all required fields set
155b5840353SAdam Hornáček      * @param start index of the first hit to print
156b5840353SAdam Hornáček      * @param end index of the last hit to print
15781b586e6SVladimir Kotal      * @throws HistoryException history exception
15881b586e6SVladimir Kotal      * @throws IOException I/O exception
15981b586e6SVladimir Kotal      * @throws ClassNotFoundException class not found
160b5840353SAdam Hornáček      */
prettyPrint(Writer out, SearchHelper sh, int start, long end)161b5840353SAdam Hornáček     public static void prettyPrint(Writer out, SearchHelper sh, int start,
162b5840353SAdam Hornáček             long end)
163b5840353SAdam Hornáček             throws HistoryException, IOException, ClassNotFoundException {
164b5840353SAdam Hornáček         Project p;
165ae1c323bSVladimir Kotal         String contextPath = sh.getContextPath();
166*d6df19e1SAdam Hornacek         String ctxE = Util.uriEncodePath(contextPath);
167ae1c323bSVladimir Kotal         String xrefPrefix = contextPath + Prefix.XREF_P;
168ae1c323bSVladimir Kotal         String morePrefix = contextPath + Prefix.MORE_P;
169b5840353SAdam Hornáček         String xrefPrefixE = ctxE + Prefix.XREF_P;
170ae1c323bSVladimir Kotal         File xrefDataDir = new File(sh.getDataRoot(), Prefix.XREF_P.toString());
171b5840353SAdam Hornáček 
172b5840353SAdam Hornáček         RuntimeEnvironment env = RuntimeEnvironment.getInstance();
173b5840353SAdam Hornáček 
174b5840353SAdam Hornáček         boolean evenRow = true;
175b5840353SAdam Hornáček         out.write("<tbody class=\"search-result\">");
176b5840353SAdam Hornáček         for (Map.Entry<String, ArrayList<Integer>> entry :
177ae1c323bSVladimir Kotal                 createMap(sh.getSearcher(), sh.getHits(), start, end).entrySet()) {
178b5840353SAdam Hornáček             String parent = entry.getKey();
179b5840353SAdam Hornáček             out.write("<tr class=\"dir\"><td colspan=\"3\"><a href=\"");
180b5840353SAdam Hornáček             out.write(xrefPrefixE);
181*d6df19e1SAdam Hornacek             out.write(Util.uriEncodePath(parent));
182b5840353SAdam Hornáček             out.write("/\">");
183b5840353SAdam Hornáček             out.write(htmlize(parent));
184b5840353SAdam Hornáček             out.write("/</a>");
185ae1c323bSVladimir Kotal             if (sh.getDesc() != null) {
186b5840353SAdam Hornáček                 out.write(" - <i>");
187ae1c323bSVladimir Kotal                 out.write(sh.getDesc().get(parent));
188b5840353SAdam Hornáček                 out.write("</i>");
189b5840353SAdam Hornáček             }
1903db691beSVladimir Kotal 
1913db691beSVladimir Kotal             p = Project.getProject(parent);
1923db691beSVladimir Kotal             String messages = MessagesUtils.messagesToJson(p, MESSAGES_MAIN_PAGE_TAG);
1933db691beSVladimir Kotal             if (p != null && !messages.isEmpty()) {
194b5840353SAdam Hornáček                 out.write(" <a href=\"" + xrefPrefix + "/" + p.getName() + "\">");
19557396dcbSVladimir Kotal                 out.write("<span class=\"note-" + MessagesUtils.getMessageLevel(p.getName(), MESSAGES_MAIN_PAGE_TAG) +
19657396dcbSVladimir Kotal                         " important-note important-note-rounded\" data-messages='" + messages + "'>!</span>");
197b5840353SAdam Hornáček                 out.write("</a>");
198b5840353SAdam Hornáček             }
199b5840353SAdam Hornáček 
200b5840353SAdam Hornáček             int tabSize = sh.getTabSize(p);
201b5840353SAdam Hornáček             PrintPlainFinalArgs fargs = new PrintPlainFinalArgs(out, sh, env,
202b5840353SAdam Hornáček                 xrefPrefix, tabSize, morePrefix);
203b5840353SAdam Hornáček 
204b5840353SAdam Hornáček             out.write("</td></tr>");
205b5840353SAdam Hornáček             for (int docId : entry.getValue()) {
206ae1c323bSVladimir Kotal                 Document doc = sh.getSearcher().doc(docId);
207b5840353SAdam Hornáček                 String rpath = doc.get(QueryBuilder.PATH);
208*d6df19e1SAdam Hornacek                 String rpathE = Util.uriEncodePath(rpath);
209b5840353SAdam Hornáček                 if (evenRow) {
210b5840353SAdam Hornáček                     out.write("<tr class=\"search-result-even-row\">");
211b5840353SAdam Hornáček                 } else {
212b5840353SAdam Hornáček                     out.write("<tr>");
213b5840353SAdam Hornáček                 }
214b5840353SAdam Hornáček                 evenRow = !evenRow;
215ae1c323bSVladimir Kotal                 Util.writeHAD(out, sh.getContextPath(), rpathE, false);
216b5840353SAdam Hornáček                 out.write("<td class=\"f\"><a href=\"");
217b5840353SAdam Hornáček                 out.write(xrefPrefixE);
218b5840353SAdam Hornáček                 out.write(rpathE);
219b5840353SAdam Hornáček                 out.write("\"");
220b5840353SAdam Hornáček                 if (env.isLastEditedDisplayMode()) {
221b5840353SAdam Hornáček                     printLastEditedDate(out, doc);
222b5840353SAdam Hornáček                 }
223b5840353SAdam Hornáček                 out.write(">");
224b5840353SAdam Hornáček                 out.write(htmlize(rpath.substring(rpath.lastIndexOf('/') + 1)));
225b5840353SAdam Hornáček                 out.write("</a>");
226b5840353SAdam Hornáček                 out.write("</td><td><code class=\"con\">");
227ae1c323bSVladimir Kotal                 if (sh.getSourceContext() != null) {
2281c830032SChris Fraire                     AbstractAnalyzer.Genre genre = AbstractAnalyzer.Genre.get(
2291c830032SChris Fraire                             doc.get(QueryBuilder.T));
230ae1c323bSVladimir Kotal                     Summarizer summarizer = sh.getSummarizer();
231ae1c323bSVladimir Kotal                     if (AbstractAnalyzer.Genre.XREFABLE == genre && summarizer != null) {
23253377eb8SChris Fraire                         String xtags = getTags(xrefDataDir, rpath, env.isCompressXref());
233b5840353SAdam Hornáček                         // FIXME use Highlighter from lucene contrib here,
234b5840353SAdam Hornáček                         // instead of summarizer, we'd also get rid of
235b5840353SAdam Hornáček                         // apache lucene in whole source ...
236ae1c323bSVladimir Kotal                         out.write(summarizer.getSummary(xtags).toString());
237ae1c323bSVladimir Kotal                     } else if (AbstractAnalyzer.Genre.HTML == genre && summarizer != null) {
238ae1c323bSVladimir Kotal                         String htags = getTags(sh.getSourceRoot(), rpath, false);
239ae1c323bSVladimir Kotal                         out.write(summarizer.getSummary(htags).toString());
24057eefa47SKryštof Tulinger                     } else if (genre == AbstractAnalyzer.Genre.PLAIN) {
241b5840353SAdam Hornáček                         printPlain(fargs, doc, docId, rpath);
242b5840353SAdam Hornáček                     }
243b5840353SAdam Hornáček                 }
244b5840353SAdam Hornáček 
245ae1c323bSVladimir Kotal                 HistoryContext historyContext = sh.getHistoryContext();
246ae1c323bSVladimir Kotal                 if (historyContext != null) {
247ae1c323bSVladimir Kotal                     historyContext.getContext(new File(sh.getSourceRoot(), rpath),
248ae1c323bSVladimir Kotal                             rpath, out, sh.getContextPath());
249b5840353SAdam Hornáček                 }
250b5840353SAdam Hornáček                 out.write("</code></td></tr>\n");
251b5840353SAdam Hornáček             }
252b5840353SAdam Hornáček         }
253b5840353SAdam Hornáček         out.write("</tbody>");
254b5840353SAdam Hornáček     }
255b5840353SAdam Hornáček 
printLastEditedDate(final Writer out, final Document doc)256b5840353SAdam Hornáček     private static void printLastEditedDate(final Writer out, final Document doc) throws IOException {
257b5840353SAdam Hornáček         try {
258b5840353SAdam Hornáček             DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
259b5840353SAdam Hornáček             String dd = df.format(DateTools.stringToDate(doc.get("date")));
260b5840353SAdam Hornáček             out.write(" class=\"result-annotate\" title=\"");
261b5840353SAdam Hornáček             out.write("Last modified: ");
262b5840353SAdam Hornáček             out.write(dd);
263b5840353SAdam Hornáček             out.write("\"");
264b5840353SAdam Hornáček         } catch (ParseException ex) {
265b5840353SAdam Hornáček             LOGGER.log(Level.WARNING, "An error parsing date information", ex);
266b5840353SAdam Hornáček         }
267b5840353SAdam Hornáček     }
268b5840353SAdam Hornáček 
printPlain(PrintPlainFinalArgs fargs, Document doc, int docId, String rpath)269b5840353SAdam Hornáček     private static void printPlain(PrintPlainFinalArgs fargs, Document doc,
270b5840353SAdam Hornáček         int docId, String rpath) throws ClassNotFoundException, IOException {
271b5840353SAdam Hornáček 
272ae1c323bSVladimir Kotal         fargs.shelp.getSourceContext().toggleAlt();
273b5840353SAdam Hornáček 
274ae1c323bSVladimir Kotal         boolean didPresentNew = fargs.shelp.getSourceContext().getContext2(fargs.env,
275ae1c323bSVladimir Kotal             fargs.shelp.getSearcher(), docId, fargs.out, fargs.xrefPrefix,
276b5840353SAdam Hornáček             fargs.morePrefix, true, fargs.tabSize);
277b5840353SAdam Hornáček 
278b5840353SAdam Hornáček         if (!didPresentNew) {
279174f246bSChris Fraire             /*
280b5840353SAdam Hornáček              * Fall back to the old view, which re-analyzes text using
281b5840353SAdam Hornáček              * PlainLinetokenizer. E.g., when source code is updated (thus
282b5840353SAdam Hornáček              * affecting timestamps) but re-indexing is not yet complete.
283b5840353SAdam Hornáček              */
284b5840353SAdam Hornáček             Definitions tags = null;
285b5840353SAdam Hornáček             IndexableField tagsField = doc.getField(QueryBuilder.TAGS);
286b5840353SAdam Hornáček             if (tagsField != null) {
287b5840353SAdam Hornáček                 tags = Definitions.deserialize(tagsField.binaryValue().bytes);
288b5840353SAdam Hornáček             }
289b5840353SAdam Hornáček             Scopes scopes;
290b5840353SAdam Hornáček             IndexableField scopesField = doc.getField(QueryBuilder.SCOPES);
291b5840353SAdam Hornáček             if (scopesField != null) {
292b5840353SAdam Hornáček                 scopes = Scopes.deserialize(scopesField.binaryValue().bytes);
293b5840353SAdam Hornáček             } else {
294b5840353SAdam Hornáček                 scopes = new Scopes();
295b5840353SAdam Hornáček             }
296ae1c323bSVladimir Kotal             boolean isDefSearch = fargs.shelp.getBuilder().isDefSearch();
297b5840353SAdam Hornáček             // SRCROOT is read with UTF-8 as a default.
298ae1c323bSVladimir Kotal             File sourceFile = new File(fargs.shelp.getSourceRoot(), rpath);
2994b613dedSAdam Hornacek             try (FileInputStream fis = new FileInputStream(sourceFile);
3004b613dedSAdam Hornacek                  Reader r = IOUtils.createBOMStrippedReader(fis, StandardCharsets.UTF_8.name())) {
301ae1c323bSVladimir Kotal                 fargs.shelp.getSourceContext().getContext(r, fargs.out,
302b5840353SAdam Hornáček                     fargs.xrefPrefix, fargs.morePrefix, rpath, tags, true,
303b5840353SAdam Hornáček                     isDefSearch, null, scopes);
304174f246bSChris Fraire             } catch (IOException ex) {
30530bba29fSChris Fraire                 String errMsg = String.format("No context for %s", sourceFile);
30630bba29fSChris Fraire                 if (LOGGER.isLoggable(Level.FINE)) {
30730bba29fSChris Fraire                     // WARNING but with FINE detail
30830bba29fSChris Fraire                     LOGGER.log(Level.WARNING, errMsg, ex);
30930bba29fSChris Fraire                 } else {
31030bba29fSChris Fraire                     LOGGER.log(Level.WARNING, errMsg);
31130bba29fSChris Fraire                 }
312b5840353SAdam Hornáček             }
313b5840353SAdam Hornáček         }
314b5840353SAdam Hornáček     }
315b5840353SAdam Hornáček 
htmlize(String raw)316b5840353SAdam Hornáček     private static String htmlize(String raw) {
317b5840353SAdam Hornáček         return Util.htmlize(raw);
318b5840353SAdam Hornáček     }
319b5840353SAdam Hornáček 
320b5840353SAdam Hornáček     private static class PrintPlainFinalArgs {
321b5840353SAdam Hornáček         final Writer out;
322b5840353SAdam Hornáček         final SearchHelper shelp;
323b5840353SAdam Hornáček         final RuntimeEnvironment env;
324b5840353SAdam Hornáček         final String xrefPrefix;
325b5840353SAdam Hornáček         final String morePrefix;
326b5840353SAdam Hornáček         final int tabSize;
327b5840353SAdam Hornáček 
PrintPlainFinalArgs(Writer out, SearchHelper shelp, RuntimeEnvironment env, String xrefPrefix, int tabSize, String morePrefix)328d1e826faSAdam Hornáček         PrintPlainFinalArgs(Writer out, SearchHelper shelp,
329b5840353SAdam Hornáček                 RuntimeEnvironment env, String xrefPrefix, int tabSize,
330b5840353SAdam Hornáček                 String morePrefix) {
331b5840353SAdam Hornáček             this.out = out;
332b5840353SAdam Hornáček             this.shelp = shelp;
333b5840353SAdam Hornáček             this.env = env;
334b5840353SAdam Hornáček             this.xrefPrefix = xrefPrefix;
335b5840353SAdam Hornáček             this.morePrefix = morePrefix;
336b5840353SAdam Hornáček             this.tabSize = tabSize;
337b5840353SAdam Hornáček         }
338b5840353SAdam Hornáček     }
339b5840353SAdam Hornáček }
340