Skip to content

Commit

Permalink
add API endpoint for getting file definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
vladak committed Dec 8, 2023
1 parent 6fb5eee commit faeb6fa
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 7 deletions.
84 changes: 84 additions & 0 deletions apiary.apib
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,90 @@ The `Content-type` header of the reply will be set accordingly.

genre as identified by analyzer, could be PLAIN, XREFABLE, IMAGE, DATA, HTML

## File definitions [/file/defs{?path}]

### get file definitions [GET]

+ Parameters
+ path (string) - path of file, relative to source root

+ Response 200 (application/json)
+ Body

[
{
"type": "function",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,",
"symbol": "AES_cbc_encrypt",
"lineStart": 5,
"lineEnd": 20,
"line": 20,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "in",
"lineStart": 21,
"lineEnd": 44,
"line": 20,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "out",
"lineStart": 46,
"lineEnd": 64,
"line": 20,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "len",
"lineStart": 21,
"lineEnd": 31,
"line": 21,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "key",
"lineStart": 33,
"lineEnd": 51,
"line": 21,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "ivec",
"lineStart": 21,
"lineEnd": 40,
"line": 22,
"namespace": null
},
{
"type": "argument",
"signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
"symbol": "enc",
"lineStart": 42,
"lineEnd": 55,
"line": 22,
"namespace": null
}
]


## History [/history{?path,withFiles,start,max}]

### get history entries [GET]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package org.opengrok.indexer.analysis;

import org.jetbrains.annotations.Nullable;
import org.opengrok.indexer.util.DTOElement;
import org.opengrok.indexer.util.WhitelistObjectInputFilter;

import java.io.ByteArrayInputStream;
Expand Down Expand Up @@ -206,47 +207,92 @@ public static class Tag implements Serializable {

private static final long serialVersionUID = 1217869075425651465L;

public int getLine() {
return line;
}

public String getSymbol() {
return symbol;
}

/**
* Line number of the tag.
*/
@DTOElement
public final int line;
/**
* The symbol used in the definition.
*/
@DTOElement
public final String symbol;

public String getType() {
return type;
}

public String getText() {
return text;
}

public String getNamespace() {
return namespace;
}

public String getSignature() {
return signature;
}

public int getLineStart() {
return lineStart;
}

public int getLineEnd() {
return lineEnd;
}

/**
* The type of the tag.
*/
@DTOElement
public final String type;
/**
* The full line on which the definition occurs.
*/
@DTOElement
public final String text;
/**
* Namespace/class of tag definition.
*/
@DTOElement
public final String namespace;
/**
* Scope of tag definition.
*/
@DTOElement
public final String signature;
/**
* The starting offset (possibly approximate) of {@link #symbol} from
* the start of the line.
*/
@DTOElement
public final int lineStart;
/**
* The ending offset (possibly approximate) of {@link #symbol} from
* the start of the line.
*/
@DTOElement
public final int lineEnd;

/**
* A non-serialized marker for marking a tag to avoid its reuse.
*/
private transient boolean used;

protected Tag(int line, String symbol, String type, String text,
public Tag() {
this(0, null, null, null, null, null, 0, 0);
}

public Tag(int line, String symbol, String type, String text,
String namespace, String signature, int lineStart,
int lineEnd) {
this.line = line;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>.
*/
package org.opengrok.web.api.v1.controller;
Expand All @@ -35,16 +35,23 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.queryparser.classic.ParseException;
import org.opengrok.indexer.analysis.AbstractAnalyzer;
import org.opengrok.indexer.analysis.Definitions;
import org.opengrok.indexer.index.IndexDatabase;
import org.opengrok.indexer.search.QueryBuilder;
import org.opengrok.web.api.v1.filter.CorsEnable;
import org.opengrok.web.api.v1.filter.PathAuthorized;
import org.opengrok.web.util.DTOUtil;
import org.opengrok.web.util.NoPathParameterException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.opengrok.indexer.index.IndexDatabase.getDocument;
import static org.opengrok.web.util.FileUtil.toFile;
Expand All @@ -54,6 +61,8 @@ public class FileController {

public static final String PATH = "file";



private StreamingOutput transfer(File file) throws FileNotFoundException {
if (!file.exists()) {
throw new FileNotFoundException(String.format("file %s does not exist", file));
Expand Down Expand Up @@ -141,4 +150,21 @@ public String getGenre(@Context HttpServletRequest request,

return genre.toString();
}

@GET
@CorsEnable
@PathAuthorized
@Path("/defs")
@Produces(MediaType.APPLICATION_JSON)
public List<Object> getDefinitions(@Context HttpServletRequest request,
@Context HttpServletResponse response,
@QueryParam("path") final String path)
throws IOException, NoPathParameterException, ParseException, ClassNotFoundException {

File file = toFile(path);
Definitions defs = IndexDatabase.getDefinitions(file);
return Optional.ofNullable(defs).
map(Definitions::getTags).orElse(Collections.emptyList()).
stream().map(DTOUtil::createDTO).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,41 @@
*/

/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>.
*/
package org.opengrok.web.api.v1.controller;

import jakarta.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.ws.rs.core.GenericType;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opengrok.indexer.analysis.Definitions;
import org.opengrok.indexer.configuration.RuntimeEnvironment;
import org.opengrok.indexer.history.HistoryGuru;
import org.opengrok.indexer.history.RepositoryFactory;
import org.opengrok.indexer.index.Indexer;
import org.opengrok.indexer.util.TestRepository;
import org.opengrok.web.api.v1.RestApp;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

class FileControllerTest extends OGKJerseyTest {

Expand All @@ -50,10 +61,16 @@ class FileControllerTest extends OGKJerseyTest {
private TestRepository repository;

@Override
protected Application configure() {
return new ResourceConfig(FileController.class);
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forServlet(new ServletContainer(new RestApp())).build();
}

@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}


@BeforeEach
@Override
public void setUp() throws Exception {
Expand Down Expand Up @@ -113,4 +130,25 @@ void testFileGenre() {
.get(String.class);
assertEquals("PLAIN", genre);
}

@Test
void testFileDefinitions() {
final String path = "git/main.c";
GenericType<List<Definitions.Tag>> type = new GenericType<>() {
};
List<Definitions.Tag> defs = target("file")
.path("defs")
.queryParam("path", path)
.request()
.get(type);
assertFalse(defs.isEmpty());
assertAll(() -> assertFalse(defs.stream().map(Definitions.Tag::getType).anyMatch(Objects::isNull)),
() -> assertFalse(defs.stream().map(Definitions.Tag::getSymbol).anyMatch(Objects::isNull)),
() -> assertFalse(defs.stream().map(Definitions.Tag::getText).anyMatch(Objects::isNull)),
() -> assertFalse(defs.stream().filter(e -> !e.getType().equals("local")).
map(Definitions.Tag::getSignature).anyMatch(Objects::isNull)),
() -> assertFalse(defs.stream().map(Definitions.Tag::getLine).anyMatch(e -> e <= 0)),
() -> assertFalse(defs.stream().map(Definitions.Tag::getLineStart).anyMatch(e -> e <= 0)),
() -> assertFalse(defs.stream().map(Definitions.Tag::getLineEnd).anyMatch(e -> e <= 0)));
}
}

0 comments on commit faeb6fa

Please sign in to comment.