Search in sources :

Example 1 with Hit

use of org.opengrok.indexer.search.Hit in project OpenGrok by OpenGrok.

the class Context method getContext.

/**
 * ???.
 * Closes the given <var>in</var> reader on return.
 *
 * @param in File to be matched
 * @param out to write the context
 * @param urlPrefix URL prefix
 * @param morePrefix to link to more... page
 * @param path path of the file
 * @param tags format to highlight defs.
 * @param limit should the number of matching lines be limited?
 * @param isDefSearch is definition search
 * @param hits list of hits
 * @param scopes scopes object
 * @return Did it get any matching context?
 */
public boolean getContext(Reader in, Writer out, String urlPrefix, String morePrefix, String path, Definitions tags, boolean limit, boolean isDefSearch, List<Hit> hits, Scopes scopes) {
    if (m == null) {
        IOUtils.close(in);
        return false;
    }
    boolean anything = false;
    TreeMap<Integer, String[]> matchingTags = null;
    String urlPrefixE = (urlPrefix == null) ? "" : Util.uriEncodePath(urlPrefix);
    String pathE = Util.uriEncodePath(path);
    if (tags != null) {
        matchingTags = new TreeMap<>();
        try {
            for (Definitions.Tag tag : tags.getTags()) {
                for (LineMatcher lineMatcher : m) {
                    if (lineMatcher.match(tag.symbol) == LineMatcher.MATCHED) {
                        String scope = null;
                        String scopeUrl = null;
                        if (scopes != null) {
                            Scope scp = scopes.getScope(tag.line);
                            scope = scp.getName() + "()";
                            scopeUrl = "<a href=\"" + urlPrefixE + pathE + "#" + scp.getLineFrom() + "\">" + scope + "</a>";
                        }
                        /* desc[0] is matched symbol
                             * desc[1] is line number
                             * desc[2] is type
                             * desc[3] is matching line;
                             * desc[4] is scope
                             */
                        String[] desc = { tag.symbol, Integer.toString(tag.line), tag.type, tag.text, scope };
                        if (in == null) {
                            if (out == null) {
                                Hit hit = new Hit(path, Util.htmlize(desc[3]).replace(desc[0], "<b>" + desc[0] + "</b>"), desc[1], false, alt);
                                hits.add(hit);
                            } else {
                                out.write("<a class=\"s\" href=\"");
                                out.write(urlPrefixE);
                                out.write(pathE);
                                out.write("#");
                                out.write(desc[1]);
                                out.write("\"><span class=\"l\">");
                                out.write(desc[1]);
                                out.write("</span> ");
                                out.write(Util.htmlize(desc[3]).replace(desc[0], "<b>" + desc[0] + "</b>"));
                                out.write("</a> ");
                                if (desc[4] != null) {
                                    out.write("<span class=\"scope\"><a href\"");
                                    out.write(scopeUrl);
                                    out.write("\">in ");
                                    out.write(desc[4]);
                                    out.write("</a></span> ");
                                }
                                out.write("<i>");
                                out.write(desc[2]);
                                out.write("</i><br/>");
                            }
                            anything = true;
                        } else {
                            matchingTags.put(tag.line, desc);
                        }
                        break;
                    }
                }
            }
        } catch (Exception e) {
            if (hits != null) {
                // @todo verify why we ignore all exceptions?
                LOGGER.log(Level.WARNING, "Could not get context for " + path, e);
            }
        }
    }
    // Just to get the matching tag send a null in
    if (in == null) {
        return anything;
    }
    PlainLineTokenizer tokens = new PlainLineTokenizer(null);
    boolean truncated = false;
    boolean lim = limit;
    RuntimeEnvironment env = RuntimeEnvironment.getInstance();
    if (!env.isQuickContextScan()) {
        lim = false;
    }
    if (lim) {
        char[] buffer = new char[MAXFILEREAD];
        int charsRead;
        try {
            charsRead = in.read(buffer);
            if (charsRead == MAXFILEREAD) {
                // we probably only read parts of the file, so set the
                // truncated flag to enable the [all...] link that
                // requests all matches
                truncated = true;
                // characters back)
                for (int i = charsRead - 1; i > charsRead - 100; i--) {
                    if (buffer[i] == '\n') {
                        charsRead = i;
                        break;
                    }
                }
            }
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "An error occurred while reading data", e);
            return anything;
        }
        if (charsRead == 0) {
            return anything;
        }
        tokens.reInit(buffer, charsRead, out, urlPrefixE + pathE + "#", matchingTags, scopes);
    } else {
        tokens.reInit(in, out, urlPrefixE + pathE + "#", matchingTags, scopes);
    }
    if (hits != null) {
        tokens.setAlt(alt);
        tokens.setHitList(hits);
        tokens.setFilename(path);
    }
    int limit_max_lines = env.getContextLimit();
    try {
        String token;
        int matchState;
        int matchedLines = 0;
        while ((token = tokens.yylex()) != null && (!lim || matchedLines < limit_max_lines)) {
            for (LineMatcher lineMatcher : m) {
                matchState = lineMatcher.match(token);
                if (matchState == LineMatcher.MATCHED) {
                    if (!isDefSearch) {
                        tokens.printContext();
                    } else if (tokens.tags.containsKey(tokens.markedLine)) {
                        tokens.printContext();
                    }
                    matchedLines++;
                    break;
                } else if (matchState == LineMatcher.WAIT) {
                    tokens.holdOn();
                } else {
                    tokens.neverMind();
                }
            }
        }
        anything = matchedLines > 0;
        tokens.dumpRest();
        if (lim && (truncated || matchedLines == limit_max_lines) && out != null) {
            out.write("<a href=\"" + Util.uriEncodePath(morePrefix) + pathE + "?" + queryAsURI + "\">[all...]</a>");
        }
    } catch (IOException e) {
        LOGGER.log(Level.WARNING, "Could not get context for " + path, e);
    } finally {
        IOUtils.close(in);
        if (out != null) {
            try {
                out.flush();
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, "Failed to flush stream: ", e);
            }
        }
    }
    return anything;
}
Also used : RuntimeEnvironment(org.opengrok.indexer.configuration.RuntimeEnvironment) Definitions(org.opengrok.indexer.analysis.Definitions) IOException(java.io.IOException) IOException(java.io.IOException) Hit(org.opengrok.indexer.search.Hit) Scope(org.opengrok.indexer.analysis.Scopes.Scope)

Example 2 with Hit

use of org.opengrok.indexer.search.Hit in project OpenGrok by OpenGrok.

the class ContextTest method bug17582.

/**
 * Helper method which does the work for {@link #bug17582()}.
 * @param builder builder for the query we want to test
 * @param lines the expected line numbers in the hit list
 * @param tags the expected tags in the hit list
 * @throws Exception exception
 */
private void bug17582(QueryBuilder builder, int[] lines, String[] tags) throws Exception {
    assertEquals(lines.length, tags.length);
    StringReader in = new StringReader("abc\nbug17582\nBug17582\n");
    Definitions defs = new Definitions();
    defs.addTag(2, "bug17582", "type1", "text1", 0, 0);
    defs.addTag(3, "Bug17582", "type2", "text2", 0, 0);
    Context context = new Context(builder.build(), builder);
    ArrayList<Hit> hits = new ArrayList<>();
    assertEquals(lines.length != 0, context.getContext(in, null, "", "", "", defs, false, builder.isDefSearch(), hits));
    assertEquals(lines.length, hits.size(), "Unexpected number of hits");
    for (int i = 0; i < lines.length; i++) {
        assertEquals(Integer.toString(lines[i]), hits.get(i).getLineno());
        assertEquals(tags[i], hits.get(i).getTag());
    }
}
Also used : Hit(org.opengrok.indexer.search.Hit) Definitions(org.opengrok.indexer.analysis.Definitions) StringReader(java.io.StringReader) ArrayList(java.util.ArrayList)

Example 3 with Hit

use of org.opengrok.indexer.search.Hit in project OpenGrok by OpenGrok.

the class ContextTest method testGetContext.

/**
 * Helper method for testing various paths through the getContext() method.
 * @param limit true if limited, quick context scan should be used
 * @param hitList true if output should be written to a list instead of a
 * writer
 * @throws ParseException parse exception
 */
private void testGetContext(boolean limit, boolean hitList) throws ParseException {
    StringReader in = new StringReader("abc def ghi\n");
    StringWriter out = hitList ? null : new StringWriter();
    List<Hit> hits = hitList ? new ArrayList<>() : null;
    RuntimeEnvironment.getInstance().setQuickContextScan(limit);
    // Search freetext for the term "def"
    QueryBuilder qb = new QueryBuilder().setFreetext("def");
    Context c = new Context(qb.build(), qb);
    assertTrue(c.getContext(in, out, "", "", "", null, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(1, hits.size());
        assertEquals("1", hits.get(0).getLineno());
    }
    String expectedOutput = hitList ? "abc <b>def</b> ghi" : "<a class=\"s\" href=\"#1\"><span class=\"l\">1</span> " + "abc <b>def</b> ghi</a><br/>";
    String actualOutput = hitList ? hits.get(0).getLine() : out.toString();
    assertEquals(expectedOutput, actualOutput);
    // Search with definitions
    Definitions defs = new Definitions();
    defs.addTag(1, "def", "type", "text", 0, 0);
    in = new StringReader("abc def ghi\n");
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    qb = new QueryBuilder().setDefs("def");
    c = new Context(qb.build(), qb);
    assertTrue(c.getContext(in, out, "", "", "", defs, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(1, hits.size());
        assertEquals("1", hits.get(0).getLineno());
    }
    expectedOutput = hitList ? "abc <b>def</b> ghi" : "<a class=\"s\" href=\"#1\"><span class=\"l\">1</span> " + "abc <b>def</b> ghi</a> <i> type</i> <br/>";
    actualOutput = hitList ? hits.get(0).getLine() : out.toString();
    assertEquals(expectedOutput, actualOutput);
    in = new StringReader("abc def ghi\nbah def foobar");
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    assertTrue(c.getContext(in, out, "", "", "", defs, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(1, hits.size());
        assertEquals("1", hits.get(0).getLineno());
    }
    // test case - if this is def search, don't show false results (defs
    // weren't defined)
    assertEquals(expectedOutput, actualOutput);
    // Search with no input (will search definitions)
    in = null;
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    qb = new QueryBuilder().setDefs("def");
    c = new Context(qb.build(), qb);
    assertTrue(c.getContext(in, out, "", "", "", defs, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(1, hits.size());
        assertEquals("1", hits.get(0).getLineno());
    }
    expectedOutput = hitList ? "text" : "<a class=\"s\" href=\"#1\"><span class=\"l\">1</span> " + "text</a> <i>type</i><br/>";
    actualOutput = hitList ? hits.get(0).getLine() : out.toString();
    assertEquals(expectedOutput, actualOutput);
    defs = new Definitions();
    defs.addTag(2, "def", "type", "text", 0, 0);
    in = new StringReader("abc1 def ghi\nabc def ghi\nabc3 def ghi\n");
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    qb = new QueryBuilder().setDefs("def");
    c = new Context(qb.build(), qb);
    assertTrue(c.getContext(in, out, "", "", "", defs, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(1, hits.size());
        assertEquals("2", hits.get(0).getLineno());
    }
    expectedOutput = hitList ? "abc <b>def</b> ghi" : "<a class=\"s\" href=\"#2\"><span class=\"l\">2</span> " + "abc <b>def</b> ghi</a> <i> type</i> <br/>";
    actualOutput = hitList ? hits.get(0).getLine() : out.toString();
    assertEquals(expectedOutput, actualOutput);
    // Search with no results
    in = new StringReader("abc def ghi\n");
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    qb = new QueryBuilder().setFreetext("no_match");
    c = new Context(qb.build(), qb);
    assertFalse(c.getContext(in, out, "", "", "", null, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(0, hits.size());
    } else {
        assertEquals("", out.toString());
    }
    // History search (should not show source context)
    in = new StringReader("abc def ghi\n");
    out = hitList ? null : new StringWriter();
    hits = hitList ? new ArrayList<>() : null;
    qb = new QueryBuilder().setHist("abc");
    c = new Context(qb.build(), qb);
    assertFalse(c.getContext(in, out, "", "", "", null, limit, qb.isDefSearch(), hits));
    if (hitList) {
        assertEquals(0, hits.size());
    } else {
        assertEquals("", out.toString());
    }
}
Also used : Hit(org.opengrok.indexer.search.Hit) StringWriter(java.io.StringWriter) Definitions(org.opengrok.indexer.analysis.Definitions) StringReader(java.io.StringReader) ArrayList(java.util.ArrayList) QueryBuilder(org.opengrok.indexer.search.QueryBuilder)

Example 4 with Hit

use of org.opengrok.indexer.search.Hit in project OpenGrok by OpenGrok.

the class HistoryContext method getHistoryContext.

/**
 * Writes matching History log entries from 'in' to 'out' or to 'hits'.
 * @param in the history to fetch entries from
 * @param out to write matched context
 * @param path path to the file
 * @param hits list of hits
 * @param wcontext web context - beginning of url
 */
private boolean getHistoryContext(History in, String path, Writer out, List<Hit> hits, String wcontext) {
    if (in == null) {
        throw new IllegalArgumentException("`in' is null");
    }
    if ((out == null) == (hits == null)) {
        // none or both are specified, it's a bug.
        throw new IllegalArgumentException("Exactly one of out and hits should be non-null");
    }
    if (m == null) {
        return false;
    }
    int matchedLines = 0;
    Iterator<HistoryEntry> it = in.getHistoryEntries().iterator();
    try {
        HistoryEntry he;
        HistoryEntry nhe = null;
        String nrev;
        while ((it.hasNext() || (nhe != null)) && matchedLines < 10) {
            if (nhe == null) {
                he = it.next();
            } else {
                // nhe is the lookahead revision
                he = nhe;
            }
            String line = he.getLine();
            String rev = he.getRevision();
            if (it.hasNext()) {
                nhe = it.next();
            } else {
                // this prefetch mechanism is here because of the diff link generation
                // we currently generate the diff to previous revision
                nhe = null;
            }
            if (nhe == null) {
                nrev = null;
            } else {
                nrev = nhe.getRevision();
            }
            tokens.reInit(line);
            String token;
            int matchState;
            long start = -1;
            while ((token = tokens.next()) != null) {
                for (LineMatcher lineMatcher : m) {
                    matchState = lineMatcher.match(token);
                    if (matchState == LineMatcher.MATCHED) {
                        if (start < 0) {
                            start = tokens.getMatchStart();
                        }
                        long end = tokens.getMatchEnd();
                        if (start > Integer.MAX_VALUE || end > Integer.MAX_VALUE) {
                            LOGGER.log(Level.INFO, "Unexpected out of bounds for {0}", path);
                        } else if (out == null) {
                            StringBuilder sb = new StringBuilder();
                            writeMatch(sb, line, (int) start, (int) end, true, path, wcontext, nrev, rev);
                            hits.add(new Hit(path, sb.toString(), "", false, false));
                        } else {
                            writeMatch(out, line, (int) start, (int) end, false, path, wcontext, nrev, rev);
                        }
                        matchedLines++;
                        break;
                    } else if (matchState == LineMatcher.WAIT) {
                        if (start < 0) {
                            start = tokens.getMatchStart();
                        }
                    } else {
                        start = -1;
                    }
                }
            }
        }
    } catch (Exception e) {
        LOGGER.log(Level.WARNING, "Could not get history context for " + path, e);
    }
    return matchedLines > 0;
}
Also used : Hit(org.opengrok.indexer.search.Hit) HistoryEntry(org.opengrok.indexer.history.HistoryEntry) HistoryException(org.opengrok.indexer.history.HistoryException) IOException(java.io.IOException)

Example 5 with Hit

use of org.opengrok.indexer.search.Hit in project OpenGrok by OpenGrok.

the class HistoryContextTest method testGetContext3Args.

@Test
@EnabledForRepository(MERCURIAL)
public void testGetContext3Args() throws Exception {
    String path = "/mercurial/Makefile";
    String filename = Paths.get(repositories.getSourceRoot(), "mercurial", "Makefile").toString();
    // Construct a query equivalent to hist:dummy
    TermQuery q1 = new TermQuery(new Term("hist", "dummy"));
    ArrayList<Hit> hits = new ArrayList<>();
    boolean gotCtx = new HistoryContext(q1).getContext(filename, path, hits);
    assertTrue(gotCtx, filename + " has context");
    assertEquals(1, hits.size());
    assertTrue(hits.get(0).getLine().contains("Created a small <b>dummy</b> program"));
    // Construct a query equivalent to hist:"dummy program"
    PhraseQuery.Builder q2 = new PhraseQuery.Builder();
    q2.add(new Term("hist", "dummy"));
    q2.add(new Term("hist", "program"));
    hits.clear();
    gotCtx = new HistoryContext(q2.build()).getContext(filename, path, hits);
    assertTrue(gotCtx, filename + " has context");
    assertEquals(1, hits.size());
    assertTrue(hits.get(0).getLine().contains("Created a small <b>dummy program</b>"));
    // Search for a term that doesn't exist
    TermQuery q3 = new TermQuery(new Term("hist", "term_does_not_exist"));
    hits.clear();
    gotCtx = new HistoryContext(q3).getContext(filename, path, hits);
    assertFalse(gotCtx, filename + " has no context");
    assertEquals(0, hits.size());
    // Search for term with multiple hits - hist:small OR hist:target
    BooleanQuery.Builder q4 = new BooleanQuery.Builder();
    q4.add(new TermQuery(new Term("hist", "small")), Occur.SHOULD);
    q4.add(new TermQuery(new Term("hist", "target")), Occur.SHOULD);
    hits.clear();
    gotCtx = new HistoryContext(q4.build()).getContext(filename, path, hits);
    assertTrue(gotCtx, filename + " has context");
    assertEquals(2, hits.size());
    assertTrue(hits.get(0).getLine().contains("Add lint make <b>target</b> and fix lint warnings"));
    assertTrue(hits.get(1).getLine().contains("Created a <b>small</b> dummy program"));
}
Also used : TermQuery(org.apache.lucene.search.TermQuery) BooleanQuery(org.apache.lucene.search.BooleanQuery) PhraseQuery(org.apache.lucene.search.PhraseQuery) ArrayList(java.util.ArrayList) Term(org.apache.lucene.index.Term) Hit(org.opengrok.indexer.search.Hit) Test(org.junit.jupiter.api.Test) EnabledForRepository(org.opengrok.indexer.condition.EnabledForRepository)

Aggregations

Hit (org.opengrok.indexer.search.Hit)5 ArrayList (java.util.ArrayList)3 Definitions (org.opengrok.indexer.analysis.Definitions)3 IOException (java.io.IOException)2 StringReader (java.io.StringReader)2 StringWriter (java.io.StringWriter)1 Term (org.apache.lucene.index.Term)1 BooleanQuery (org.apache.lucene.search.BooleanQuery)1 PhraseQuery (org.apache.lucene.search.PhraseQuery)1 TermQuery (org.apache.lucene.search.TermQuery)1 Test (org.junit.jupiter.api.Test)1 Scope (org.opengrok.indexer.analysis.Scopes.Scope)1 EnabledForRepository (org.opengrok.indexer.condition.EnabledForRepository)1 RuntimeEnvironment (org.opengrok.indexer.configuration.RuntimeEnvironment)1 HistoryEntry (org.opengrok.indexer.history.HistoryEntry)1 HistoryException (org.opengrok.indexer.history.HistoryException)1 QueryBuilder (org.opengrok.indexer.search.QueryBuilder)1