From 33ff3ba8cde78cd813e34b2a6a5e4f53778295d7 Mon Sep 17 00:00:00 2001 From: Miguel Molina Date: Mon, 7 Aug 2017 14:39:32 +0200 Subject: [PATCH 1/6] add C exports for enry Signed-off-by: Miguel Molina --- shared/enry.go | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 shared/enry.go diff --git a/shared/enry.go b/shared/enry.go new file mode 100644 index 0000000..3bff8ad --- /dev/null +++ b/shared/enry.go @@ -0,0 +1,140 @@ +// +build darwin,cgo linux,cgo +// +build amd64 + +package main + +import "C" +import "gopkg.in/src-d/enry.v1" + +//export GetLanguage +func GetLanguage(filename string, content []byte) string { + return enry.GetLanguage(filename, content) +} + +//export GetLanguageByContent +func GetLanguageByContent(filename string, content []byte) (language string, safe bool) { + return enry.GetLanguageByContent(filename, content) +} + +//export GetLanguageByEmacsModeline +func GetLanguageByEmacsModeline(content []byte) (language string, safe bool) { + return enry.GetLanguageByModeline(content) +} + +//export GetLanguageByExtension +func GetLanguageByExtension(filename string) (language string, safe bool) { + return enry.GetLanguageByExtension(filename) +} + +//export GetLanguageByFilename +func GetLanguageByFilename(filename string) (language string, safe bool) { + return enry.GetLanguageByFilename(filename) +} + +//export GetLanguageByModeline +func GetLanguageByModeline(content []byte) (language string, safe bool) { + return enry.GetLanguageByModeline(content) +} + +//export GetLanguageByShebang +func GetLanguageByShebang(content []byte) (language string, safe bool) { + return enry.GetLanguageByShebang(content) +} + +//export GetLanguageByVimModeline +func GetLanguageByVimModeline(content []byte) (language string, safe bool) { + return enry.GetLanguageByVimModeline(content) +} + +//export GetLanguageExtensions +func GetLanguageExtensions(language string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguageExtensions(language)) +} + +//export GetLanguages +func GetLanguages(filename string, content []byte, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguages(filename, content)) +} + +//export GetLanguagesByContent +func GetLanguagesByContent(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByContent(filename, content, candidates)) +} + +//export GetLanguagesByEmacsModeline +func GetLanguagesByEmacsModeline(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByEmacsModeline(filename, content, candidates)) +} + +//export GetLanguagesByExtension +func GetLanguagesByExtension(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByExtension(filename, content, candidates)) +} + +//export GetLanguagesByFilename +func GetLanguagesByFilename(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByFilename(filename, content, candidates)) +} + +//export GetLanguagesByModeline +func GetLanguagesByModeline(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByModeline(filename, content, candidates)) +} + +//export GetLanguagesByShebang +func GetLanguagesByShebang(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByShebang(filename, content, candidates)) +} + +//export GetLanguagesByVimModeline +func GetLanguagesByVimModeline(filename string, content []byte, candidates []string, result *[]*C.char) { + strSliceCopy(result, enry.GetLanguagesByVimModeline(filename, content, candidates)) +} + +//export GetMimeType +func GetMimeType(path string, language string) string { + return enry.GetMimeType(path, language) +} + +//export IsAuxiliaryLanguage +func IsAuxiliaryLanguage(lang string) bool { + return enry.IsAuxiliaryLanguage(lang) +} + +//export IsBinary +func IsBinary(data []byte) bool { + return enry.IsBinary(data) +} + +//export IsConfiguration +func IsConfiguration(path string) bool { + return enry.IsConfiguration(path) +} + +//export IsDocumentation +func IsDocumentation(path string) bool { + return enry.IsDocumentation(path) +} + +//export IsDotFile +func IsDotFile(path string) bool { + return enry.IsDotFile(path) +} + +//export IsImage +func IsImage(path string) bool { + return enry.IsImage(path) +} + +//export IsVendor +func IsVendor(path string) bool { + return enry.IsVendor(path) +} + +func strSliceCopy(result *[]*C.char, slice []string) { + for _, str := range slice { + *result = append(*result, C.CString(str)) + } +} + +func main() {} From d8fc4fe92f57ade4ce578e2090e5369a04384dce Mon Sep 17 00:00:00 2001 From: Miguel Molina Date: Tue, 8 Aug 2017 12:02:27 +0200 Subject: [PATCH 2/6] java implementation of enry Signed-off-by: Miguel Molina --- .gitignore | 1 + Makefile | 28 ++- java/.gitignore | 27 +++ java/Makefile | 61 +++++ java/README.md | 35 +++ java/build.sbt | 38 +++ java/project/build.properties | 1 + java/project/plugins.sbt | 1 + .../src/main/java/tech/sourced/enry/Enry.java | 224 ++++++++++++++++++ .../main/java/tech/sourced/enry/GoUtils.java | 73 ++++++ .../main/java/tech/sourced/enry/Guess.java | 23 ++ .../test/java/tech/sourced/enry/EnryTest.java | 150 ++++++++++++ 12 files changed, 661 insertions(+), 1 deletion(-) create mode 100644 java/.gitignore create mode 100644 java/Makefile create mode 100644 java/README.md create mode 100644 java/build.sbt create mode 100644 java/project/build.properties create mode 100644 java/project/plugins.sbt create mode 100644 java/src/main/java/tech/sourced/enry/Enry.java create mode 100644 java/src/main/java/tech/sourced/enry/GoUtils.java create mode 100644 java/src/main/java/tech/sourced/enry/Guess.java create mode 100644 java/src/test/java/tech/sourced/enry/EnryTest.java diff --git a/.gitignore b/.gitignore index bf8b345..8596d00 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ benchmarks/output .ci Makefile.main +.shared diff --git a/Makefile b/Makefile index d17633b..0f1c332 100644 --- a/Makefile +++ b/Makefile @@ -24,13 +24,25 @@ LOCAL_COMMIT := $(shell git rev-parse --short HEAD) LOCAL_BUILD := $(shell date +"%m-%d-%Y_%H_%M_%S") LOCAL_LDFLAGS = -s -X main.version=$(LOCAL_TAG) -X main.build=$(LOCAL_BUILD) -X main.commit=$(LOCAL_COMMIT) +# shared objects +RESOURCES_DIR=./.shared +LINUX_DIR=$(RESOURCES_DIR)/linux-x86-64 +LINUX_SHARED_LIB=$(LINUX_DIR)/libenry.so +DARWIN_DIR=$(RESOURCES_DIR)/darwin +DARWIN_SHARED_LIB=$(DARWIN_DIR)/libenry.dylib +HEADER_FILE=libenry.h +NATIVE_LIB=./shared/enry.go + $(LINGUIST_PATH): git clone https://github.com/github/linguist.git $@ clean-linguist: rm -rf $(LINGUIST_PATH) -clean: clean-linguist +clean-shared: + rm -rf $(RESOURCES_DIR) + +clean: clean-linguist clean-shared code-generate: $(LINGUIST_PATH) mkdir -p data @@ -48,3 +60,17 @@ benchmarks-slow: $(LINGUST_PATH) build-cli: go build -o enry -ldflags "$(LOCAL_LDFLAGS)" cli/enry/main.go + +linux-shared: $(LINUX_SHARED_LIB) + +darwin-shared: $(DARWIN_SHARED_LIB) + +$(DARWIN_SHARED_LIB): + mkdir -p $(DARWIN_DIR) && \ + GOOS=darwin GOARCH=amd64 go build -buildmode=c-shared -o $(DARWIN_SHARED_LIB) $(NATIVE_LIB) && \ + mv $(DARWIN_DIR)/$(HEADER_FILE) $(RESOURCES_DIR)/$(HEADER_FILE) + +$(LINUX_SHARED_LIB): + mkdir -p $(LINUX_DIR) && \ + GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o $(LINUX_SHARED_LIB) $(NATIVE_LIB) && \ + mv $(LINUX_DIR)/$(HEADER_FILE) $(RESOURCES_DIR)/$(HEADER_FILE) diff --git a/java/.gitignore b/java/.gitignore new file mode 100644 index 0000000..bbf3ec5 --- /dev/null +++ b/java/.gitignore @@ -0,0 +1,27 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +target +.idea +.jnaerator +shared +*.jar diff --git a/java/Makefile b/java/Makefile new file mode 100644 index 0000000..1c776ef --- /dev/null +++ b/java/Makefile @@ -0,0 +1,61 @@ +JNAERATOR_VERSION=ac73c9e +JARS_DIR=./lib +JAR=$(JARS_DIR)/enry.jar +JNAERATOR_DIR=./.jnaerator +JNAERATOR_JAR=$(JNAERATOR_DIR)/jnaerator.jar +RESOURCES_SRC=../.shared +RESOURCES_DIR=./shared +HEADER_FILE=$(RESOURCES_DIR)/libenry.h + +all: $(JAR) + +$(JAR): $(RESOURCES_DIR) $(JNAERATOR_JAR) + mkdir -p lib && \ + java -jar $(JNAERATOR_JAR) \ + -package tech.sourced.enry.nativelib \ + -library enry \ + $(HEADER_FILE) \ + -o $(JARS_DIR) \ + -mode StandaloneJar \ + -runtime JNA; + +$(RESOURCES_DIR): os-shared-lib + cp -R $(RESOURCES_SRC) $(RESOURCES_DIR) + +$(JNAERATOR_JAR): $(RESOURCES_DIR) + git clone --depth 1 https://github.com/nativelibs4java/jnaerator.git $(JNAERATOR_DIR) && \ + cd $(JNAERATOR_DIR) && \ + git checkout $(JNAERATOR_VERSION) && \ + mvn clean install && \ + mv jnaerator/target/jnaerator-*-shaded.jar ./jnaerator.jar && \ + cd ..; + +os-shared-lib: + @os_name="$(shell uname -s)" && \ + if [ "$$os_name" == "Linux" ]; then \ + $(MAKE) linux-shared; \ + elif [ "$$os_name" == "Darwin" ]; then \ + $(MAKE) darwin-shared; \ + else \ + echo "Unsupported operating system, can't build shared library"; \ + exit 1; \ + fi; + +linux-shared: + cd .. && \ + $(MAKE) linux-shared + +darwin-shared: + cd .. && \ + $(MAKE) darwin-shared + +test: + sbt clean test + +package: + sbt clean assembly + +clean: + rm -rf $(JAR) + rm -rf $(RESOURCES_DIR) + diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000..31b11e6 --- /dev/null +++ b/java/README.md @@ -0,0 +1,35 @@ +# enry-java + +### Requirements + +* `sbt` +* `Java` (tested with Java 1.8) +* `maven` install and on the PATH (only for local usage) +* `Go` (only for building the shared objects for your operating system) + +### Generate jar with Java bindings and shared libraries + +You need to do this before exporting the jar and/or testing. + +``` +make +``` + +This will download JNAerator and build its jar to generate the code from the `libenry.h` header file (hence the need for `mvn` installed), it will be placed under `lib`. +The shared libraries for your operating system will be built if needed and copied inside the `shared` directory. + +For IntelliJ and other IDEs remember to mark `shared` folder as sources and add `lib/enry.jar` as library. If you use `sbt` from the command line directly that's already taken care of. + +### Run tests + +``` +make test +``` + +### Export jar + +``` +make package +``` + +Jar will be located in `./target/enry-java-assembly-X.X.X.jar`. diff --git a/java/build.sbt b/java/build.sbt new file mode 100644 index 0000000..08b41fb --- /dev/null +++ b/java/build.sbt @@ -0,0 +1,38 @@ +name := "enry-java" +organization := "tech.sourced" +version := "1.0" + +crossPaths := false +autoScalaLibrary := false +publishMavenStyle := true +exportJars := true + +libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test + +unmanagedBase := baseDirectory.value / "lib" +unmanagedClasspath in Test += baseDirectory.value / "shared" +unmanagedClasspath in Runtime += baseDirectory.value / "shared" +unmanagedClasspath in Compile += baseDirectory.value / "shared" +testOptions += Tests.Argument(TestFrameworks.JUnit) + +lazy val buildNative = taskKey[Unit]("builds native code") + +buildNative := { + val res = "make"!; + if (res != 0) throw new RuntimeException("unable to generate shared libraries and native jar bindings") +} + +test := { + buildNative.value + (test in Test).value +} + +compile := { + buildNative.value + (compile in Compile).value +} + +assembly := { + buildNative.value + assembly.value +} diff --git a/java/project/build.properties b/java/project/build.properties new file mode 100644 index 0000000..826c0bd --- /dev/null +++ b/java/project/build.properties @@ -0,0 +1 @@ +sbt.version = 0.13.16 \ No newline at end of file diff --git a/java/project/plugins.sbt b/java/project/plugins.sbt new file mode 100644 index 0000000..cc9a881 --- /dev/null +++ b/java/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") \ No newline at end of file diff --git a/java/src/main/java/tech/sourced/enry/Enry.java b/java/src/main/java/tech/sourced/enry/Enry.java new file mode 100644 index 0000000..7fad0eb --- /dev/null +++ b/java/src/main/java/tech/sourced/enry/Enry.java @@ -0,0 +1,224 @@ +package tech.sourced.enry; + +import tech.sourced.enry.nativelib.*; + +import static tech.sourced.enry.GoUtils.*; + +public class Enry { + private static final EnryLibrary nativeLib = EnryLibrary.INSTANCE; + + /** + * Returns whether the given language is auxiliary or not. + * + * @param language name of the language, e.g. PHP, HTML, ... + * @return if it's an auxiliary language + */ + public static boolean isAuxiliaryLanguage(String language) { + return toJavaBool(nativeLib.IsAuxiliaryLanguage(toGoString(language))); + } + + /** + * Returns the language of the given file based on the filename and its + * contents. + * + * @param filename name of the file with the extension + * @param content array of bytes with the contents of the file (the code) + * @return the guessed language + */ + public static String getLanguage(String filename, byte[] content) { + return toJavaString(nativeLib.GetLanguage( + toGoString(filename), + toGoByteSlice(content) + )); + } + + /** + * Returns detected language by its content. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param content of the file + * @return guessed result + */ + public static Guess getLanguageByContent(byte[] content) { + GetLanguageByContent_return.ByValue res = nativeLib.GetLanguageByContent(toGoByteSlice(content)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by its emacs modeline. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param content of the file + * @return guessed result + */ + public static Guess getLanguageByEmacsModeline(byte[] content) { + GetLanguageByEmacsModeline_return.ByValue res = nativeLib.GetLanguageByEmacsModeline(toGoByteSlice(content)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by the extension of the filename. + * If there are more than one possible languages, it returns + * the first language in alphabetical order and safe to false. + * + * @param filename of the file + * @return guessed result + */ + public static Guess getLanguageByExtension(String filename) { + GetLanguageByExtension_return.ByValue res = nativeLib.GetLanguageByExtension(toGoString(filename)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by its shebang. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param content of the file + * @return guessed result + */ + public static Guess getLanguageByShebang(byte[] content) { + GetLanguageByShebang_return.ByValue res = nativeLib.GetLanguageByShebang(toGoByteSlice(content)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by its filename. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param filename of the file + * @return guessed result + */ + public static Guess getLanguageByFilename(String filename) { + GetLanguageByFilename_return.ByValue res = nativeLib.GetLanguageByFilename(toGoString(filename)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by its modeline. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param content of the file + * @return guessed result + */ + public static Guess getLanguageByModeline(byte[] content) { + GetLanguageByModeline_return.ByValue res = nativeLib.GetLanguageByModeline(toGoByteSlice(content)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns detected language by its vim modeline. + * If there are more than one possible language, it returns the first + * language in alphabetical order and safe to false. + * + * @param content of the file + * @return guessed result + */ + public static Guess getLanguageByVimModeline(byte[] content) { + GetLanguageByVimModeline_return.ByValue res = nativeLib.GetLanguageByVimModeline(toGoByteSlice(content)); + return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); + } + + /** + * Returns all the possible extensions for a file in the given language. + * + * @param language to get extensions from + * @return extensions + */ + public static String[] getLanguageExtensions(String language) { + GoSlice result = new GoSlice(); + nativeLib.GetLanguageExtensions(toGoString(language), result); + return toJavaStringArray(result); + } + + /** + * Returns all possible languages for the given file. + * + * @param filename of the file + * @param content of the file + * @return all possible languages + */ + public static String[] getLanguages(String filename, byte[] content) { + GoSlice result = new GoSlice(); + nativeLib.GetLanguages(toGoString(filename), toGoByteSlice(content), result); + return toJavaStringArray(result); + } + + /** + * Returns the mime type of the file. + * + * @param path of the file + * @param language of the file + * @return mime type + */ + public static String getMimeType(String path, String language) { + return toJavaString(nativeLib.GetMimeType(toGoString(path), toGoString(language))); + } + + /** + * Reports whether the given file content is binary or not. + * + * @param content of the file + * @return whether it's binary or not + */ + public static boolean isBinary(byte[] content) { + return toJavaBool(nativeLib.IsBinary(toGoByteSlice(content))); + } + + /** + * Reports whether the given file or directory is a config file or directory. + * + * @param path of the file or directory + * @return whether it's config or not + */ + public static boolean isConfiguration(String path) { + return toJavaBool(nativeLib.IsConfiguration(toGoString(path))); + } + + /** + * Reports whether the given file or directory it's documentation. + * + * @param path of the file or directory. It must not contain its parents and + * if it's a directory it must end in a slash e.g. "docs/" or + * "foo.json". + * @return whether it's docs or not + */ + public static boolean isDocumentation(String path) { + return toJavaBool(nativeLib.IsDocumentation(toGoString(path))); + } + + /** + * Reports whether the given file is a dotfile. + * + * @param path of the file + * @return whether it's a dotfile or not + */ + public static boolean isDotFile(String path) { + return toJavaBool(nativeLib.IsDotFile(toGoString(path))); + } + + /** + * Reports whether the given path is an image or not. + * + * @param path of the file + * @return whether it's an image or not + */ + public static boolean isImage(String path) { + return toJavaBool(nativeLib.IsImage(toGoString(path))); + } + + /** + * Reports whether the given path is a vendor path or not. + * + * @param path of the file or directory + * @return whether it's vendor or not + */ + public static boolean isVendor(String path) { + return toJavaBool(nativeLib.IsVendor(toGoString(path))); + } + +} diff --git a/java/src/main/java/tech/sourced/enry/GoUtils.java b/java/src/main/java/tech/sourced/enry/GoUtils.java new file mode 100644 index 0000000..c845841 --- /dev/null +++ b/java/src/main/java/tech/sourced/enry/GoUtils.java @@ -0,0 +1,73 @@ +package tech.sourced.enry; + +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import tech.sourced.enry.nativelib.GoSlice; +import tech.sourced.enry.nativelib.GoString; + +import java.io.UnsupportedEncodingException; + +class GoUtils { + + static GoString.ByValue toGoString(String str) { + byte[] bytes; + try { + bytes = str.getBytes("utf-8"); + } catch (UnsupportedEncodingException e) { + bytes = str.getBytes(); + } + + GoString.ByValue val = new GoString.ByValue(); + val.n = bytes.length; + Pointer ptr = new Memory(bytes.length); + ptr.write(0, bytes, 0, bytes.length); + val.p = ptr; + return val; + } + + static String toJavaString(GoString str) { + if (str.n == 0) { + return ""; + } + + byte[] bytes = new byte[(int) str.n]; + str.p.read(0, bytes, 0, (int) str.n); + try { + return new String(bytes, "utf-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("utf-8 encoding is not supported"); + } + } + + static String[] toJavaStringArray(GoSlice slice) { + String[] result = new String[(int) slice.len]; + Pointer[] ptrArr = slice.data.getPointerArray(0, (int) slice.len); + for (int i = 0; i < (int) slice.len; i++) { + result[i] = ptrArr[i].getString(0); + } + return result; + } + + static GoSlice.ByValue toGoByteSlice(byte[] bytes) { + return sliceFromPtr(bytes.length, ptrFromBytes(bytes)); + } + + static GoSlice.ByValue sliceFromPtr(int len, Pointer ptr) { + GoSlice.ByValue val = new GoSlice.ByValue(); + val.cap = len; + val.len = len; + val.data = ptr; + return val; + } + + static Pointer ptrFromBytes(byte[] bytes) { + Pointer ptr = new Memory(bytes.length); + ptr.write(0, bytes, 0, bytes.length); + return ptr; + } + + static boolean toJavaBool(byte goBool) { + return goBool == 1; + } + +} diff --git a/java/src/main/java/tech/sourced/enry/Guess.java b/java/src/main/java/tech/sourced/enry/Guess.java new file mode 100644 index 0000000..8b7731e --- /dev/null +++ b/java/src/main/java/tech/sourced/enry/Guess.java @@ -0,0 +1,23 @@ +package tech.sourced.enry; + +/** + * Guess denotes a language detection result of which enry can be + * completely sure or not. + */ +public class Guess { + /** + * Result is the resultant language of the detection. + */ + public String result; + + /** + * Sure indicates whether the enry was completely sure the language is + * the correct one or it might not be. + */ + public boolean sure; + + public Guess(String result, boolean sure) { + this.result = result; + this.sure = sure; + } +} diff --git a/java/src/test/java/tech/sourced/enry/EnryTest.java b/java/src/test/java/tech/sourced/enry/EnryTest.java new file mode 100644 index 0000000..540d69e --- /dev/null +++ b/java/src/test/java/tech/sourced/enry/EnryTest.java @@ -0,0 +1,150 @@ +package tech.sourced.enry; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class EnryTest { + + @Test + public void isAuxiliaryLanguage() { + assertTrue(Enry.isAuxiliaryLanguage("HTML")); + assertFalse(Enry.isAuxiliaryLanguage("Go")); + } + + @Test + public void getLanguage() { + String code = " class { X i; };"; + assertGuess( + "C++", + true, + Enry.getLanguageByEmacsModeline(code.getBytes()) + ); + } + + @Test + public void getLanguageByExtension() { + assertGuess( + "Ruby", + true, + Enry.getLanguageByExtension("foo.rb") + ); + } + + @Test + public void getLanguageByShebang() { + String code = "#!/usr/bin/env python"; + assertGuess( + "Python", + true, + Enry.getLanguageByShebang(code.getBytes()) + ); + } + + @Test + public void getLanguageByModeline() { + String code = "// -*- font:bar;mode:c++ -*-\n" + + "template class { X i; };"; + assertGuess( + "C++", + true, + Enry.getLanguageByModeline(code.getBytes()) + ); + + code = "# vim: noexpandtab: ft=javascript"; + assertGuess( + "JavaScript", + true, + Enry.getLanguageByModeline(code.getBytes()) + ); + } + + @Test + public void getLanguageByVimModeline() { + String code = "# vim: noexpandtab: ft=javascript"; + assertGuess( + "JavaScript", + true, + Enry.getLanguageByVimModeline(code.getBytes()) + ); + } + + @Test + public void getLanguageExtensions() { + String[] exts = Enry.getLanguageExtensions("Go"); + String[] expected = {".go"}; + assertArrayEquals(expected, exts); + } + + @Test + public void getLanguages() { + String code = "#include " + + "" + + "extern int foo(void *bar);"; + + String[] result = Enry.getLanguages("foo.h", code.getBytes()); + String[] expected = {"C", "C++", "Objective-C"}; + assertArrayEquals(expected, result); + } + + @Test + public void getMimeType() { + assertEquals( + "text/x-ruby", + Enry.getMimeType("foo.rb", "Ruby") + ); + } + + @Test + public void isBinary() { + assertFalse(Enry.isBinary("hello = 'world'".getBytes())); + } + + @Test + public void isConfiguration() { + assertTrue(Enry.isConfiguration("config.yml")); + assertFalse(Enry.isConfiguration("FooServiceProviderImplementorFactory.java")); + } + + @Test + public void isDocumentation() { + assertTrue(Enry.isDocumentation("docs/")); + assertFalse(Enry.isDocumentation("src/")); + } + + @Test + public void isDotFile() { + assertTrue(Enry.isDotFile(".env")); + assertFalse(Enry.isDotFile("config.json")); + } + + @Test + public void isImage() { + assertTrue(Enry.isImage("yup.jpg")); + assertFalse(Enry.isImage("nope.go")); + } + + void assertGuess(String language, boolean sure, Guess result) { + assertEquals(language, result.result); + assertEquals(sure, result.sure); + } + +} From f53abe6bc254680fa375da35c9a3c71d0553c31c Mon Sep 17 00:00:00 2001 From: Miguel Molina Date: Tue, 8 Aug 2017 12:32:32 +0200 Subject: [PATCH 3/6] travis configuration Signed-off-by: Miguel Molina --- .travis.yml | 21 ++++++++++++++++++++- java/Makefile | 2 ++ java/build.sbt | 21 --------------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32c42be..866622c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: go +sudo: required go: - 1.8 @@ -7,6 +8,24 @@ go: matrix: allow_failures: - go: tip + include: + - language: scala + jdk: oraclejdk8 + + install: + - GIMME_OUTPUT=$(gimme 1.8 | tee -a $HOME/.bashrc) && eval "$GIMME_OUTPUT" + - export GOPATH=$HOME/gopath + - mkdir -p $GOPATH/src/gopkg.in/src-d/enry.v1 + - rsync -az ${TRAVIS_BUILD_DIR}/ $GOPATH/src/gopkg.in/src-d/enry.v1 + - go get -v gopkg.in/src-d/enry.v1/... + - sudo apt-get install maven + + before_script: + - cd java + - make + + script: + - make test install: - rm -rf $GOPATH/src/gopkg.in/src-d @@ -26,7 +45,7 @@ before_deploy: deploy: provider: releases - api_key: $GITHUB_TOKEN + api_key: $GITHUB_TOKEN file_glob: true file: build/*.tar.gz skip_cleanup: true diff --git a/java/Makefile b/java/Makefile index 1c776ef..ceb89c3 100644 --- a/java/Makefile +++ b/java/Makefile @@ -7,6 +7,8 @@ RESOURCES_SRC=../.shared RESOURCES_DIR=./shared HEADER_FILE=$(RESOURCES_DIR)/libenry.h +SHELL := /bin/bash + all: $(JAR) $(JAR): $(RESOURCES_DIR) $(JNAERATOR_JAR) diff --git a/java/build.sbt b/java/build.sbt index 08b41fb..59f91ed 100644 --- a/java/build.sbt +++ b/java/build.sbt @@ -15,24 +15,3 @@ unmanagedClasspath in Runtime += baseDirectory.value / "shared" unmanagedClasspath in Compile += baseDirectory.value / "shared" testOptions += Tests.Argument(TestFrameworks.JUnit) -lazy val buildNative = taskKey[Unit]("builds native code") - -buildNative := { - val res = "make"!; - if (res != 0) throw new RuntimeException("unable to generate shared libraries and native jar bindings") -} - -test := { - buildNative.value - (test in Test).value -} - -compile := { - buildNative.value - (compile in Compile).value -} - -assembly := { - buildNative.value - assembly.value -} From 2825eb22e660e22917f268bb5001ef7278ede088 Mon Sep 17 00:00:00 2001 From: Miguel Molina Date: Tue, 8 Aug 2017 17:36:52 +0200 Subject: [PATCH 4/6] get jnaerator from a jitpack jar Signed-off-by: Miguel Molina --- java/Makefile | 9 +++------ java/src/main/java/tech/sourced/enry/Enry.java | 10 +++++++--- java/src/test/java/tech/sourced/enry/EnryTest.java | 5 ++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/Makefile b/java/Makefile index ceb89c3..af1905c 100644 --- a/java/Makefile +++ b/java/Makefile @@ -3,6 +3,7 @@ JARS_DIR=./lib JAR=$(JARS_DIR)/enry.jar JNAERATOR_DIR=./.jnaerator JNAERATOR_JAR=$(JNAERATOR_DIR)/jnaerator.jar +JNAERATOR_JAR_URL="https://jitpack.io/com/github/nativelibs4java/JNAerator/jnaerator/$(JNAERATOR_VERSION)/jnaerator-$(JNAERATOR_VERSION)-shaded.jar" RESOURCES_SRC=../.shared RESOURCES_DIR=./shared HEADER_FILE=$(RESOURCES_DIR)/libenry.h @@ -25,12 +26,8 @@ $(RESOURCES_DIR): os-shared-lib cp -R $(RESOURCES_SRC) $(RESOURCES_DIR) $(JNAERATOR_JAR): $(RESOURCES_DIR) - git clone --depth 1 https://github.com/nativelibs4java/jnaerator.git $(JNAERATOR_DIR) && \ - cd $(JNAERATOR_DIR) && \ - git checkout $(JNAERATOR_VERSION) && \ - mvn clean install && \ - mv jnaerator/target/jnaerator-*-shaded.jar ./jnaerator.jar && \ - cd ..; + mkdir $(JNAERATOR_DIR) && \ + wget $(JNAERATOR_JAR_URL) -O $(JNAERATOR_JAR) os-shared-lib: @os_name="$(shell uname -s)" && \ diff --git a/java/src/main/java/tech/sourced/enry/Enry.java b/java/src/main/java/tech/sourced/enry/Enry.java index 7fad0eb..a1eaa21 100644 --- a/java/src/main/java/tech/sourced/enry/Enry.java +++ b/java/src/main/java/tech/sourced/enry/Enry.java @@ -37,11 +37,15 @@ public class Enry { * If there are more than one possible language, it returns the first * language in alphabetical order and safe to false. * - * @param content of the file + * @param filename name of the file with the extension + * @param content of the file * @return guessed result */ - public static Guess getLanguageByContent(byte[] content) { - GetLanguageByContent_return.ByValue res = nativeLib.GetLanguageByContent(toGoByteSlice(content)); + public static Guess getLanguageByContent(String filename, byte[] content) { + GetLanguageByContent_return.ByValue res = nativeLib.GetLanguageByContent( + toGoString(filename), + toGoByteSlice(content) + ); return new Guess(toJavaString(res.r0), toJavaBool(res.r1)); } diff --git a/java/src/test/java/tech/sourced/enry/EnryTest.java b/java/src/test/java/tech/sourced/enry/EnryTest.java index 540d69e..9311d57 100644 --- a/java/src/test/java/tech/sourced/enry/EnryTest.java +++ b/java/src/test/java/tech/sourced/enry/EnryTest.java @@ -18,14 +18,13 @@ public class EnryTest { assertEquals("PHP", Enry.getLanguage("foobar.php", code.getBytes())); } - // TODO: this is a bug in enry, fix when it's fixed there - @Test(expected = AssertionError.class) + @Test public void getLanguageByContent() { String code = " Date: Wed, 9 Aug 2017 10:14:47 +0200 Subject: [PATCH 5/6] remove references to maven usage in both README and travis.yml Signed-off-by: Miguel Molina --- .travis.yml | 2 -- java/README.md | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 866622c..019f3c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: go -sudo: required go: - 1.8 @@ -18,7 +17,6 @@ matrix: - mkdir -p $GOPATH/src/gopkg.in/src-d/enry.v1 - rsync -az ${TRAVIS_BUILD_DIR}/ $GOPATH/src/gopkg.in/src-d/enry.v1 - go get -v gopkg.in/src-d/enry.v1/... - - sudo apt-get install maven before_script: - cd java diff --git a/java/README.md b/java/README.md index 31b11e6..f89cf5e 100644 --- a/java/README.md +++ b/java/README.md @@ -4,7 +4,7 @@ * `sbt` * `Java` (tested with Java 1.8) -* `maven` install and on the PATH (only for local usage) +* `wget` * `Go` (only for building the shared objects for your operating system) ### Generate jar with Java bindings and shared libraries @@ -15,7 +15,7 @@ You need to do this before exporting the jar and/or testing. make ``` -This will download JNAerator and build its jar to generate the code from the `libenry.h` header file (hence the need for `mvn` installed), it will be placed under `lib`. +This will download JNAerator jar to generate the code from the `libenry.h` header file, it will be placed under `lib`. The shared libraries for your operating system will be built if needed and copied inside the `shared` directory. For IntelliJ and other IDEs remember to mark `shared` folder as sources and add `lib/enry.jar` as library. If you use `sbt` from the command line directly that's already taken care of. From 4da1c5605c36e7982424505068f6f8447f5d3e02 Mon Sep 17 00:00:00 2001 From: Miguel Molina Date: Wed, 9 Aug 2017 11:29:45 +0200 Subject: [PATCH 6/6] rename result and sure in Guess to language and safe Signed-off-by: Miguel Molina --- java/src/main/java/tech/sourced/enry/Guess.java | 14 +++++++------- java/src/test/java/tech/sourced/enry/EnryTest.java | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/java/src/main/java/tech/sourced/enry/Guess.java b/java/src/main/java/tech/sourced/enry/Guess.java index 8b7731e..ff9fbaa 100644 --- a/java/src/main/java/tech/sourced/enry/Guess.java +++ b/java/src/main/java/tech/sourced/enry/Guess.java @@ -6,18 +6,18 @@ package tech.sourced.enry; */ public class Guess { /** - * Result is the resultant language of the detection. + * The resultant language of the detection. */ - public String result; + public String language; /** - * Sure indicates whether the enry was completely sure the language is + * Indicates whether the enry was completely sure the language is * the correct one or it might not be. */ - public boolean sure; + public boolean safe; - public Guess(String result, boolean sure) { - this.result = result; - this.sure = sure; + public Guess(String language, boolean safe) { + this.language = language; + this.safe = safe; } } diff --git a/java/src/test/java/tech/sourced/enry/EnryTest.java b/java/src/test/java/tech/sourced/enry/EnryTest.java index 9311d57..9eac865 100644 --- a/java/src/test/java/tech/sourced/enry/EnryTest.java +++ b/java/src/test/java/tech/sourced/enry/EnryTest.java @@ -141,9 +141,9 @@ public class EnryTest { assertFalse(Enry.isImage("nope.go")); } - void assertGuess(String language, boolean sure, Guess result) { - assertEquals(language, result.result); - assertEquals(sure, result.sure); + void assertGuess(String language, boolean safe, Guess guess) { + assertEquals(language, guess.language); + assertEquals(safe, guess.safe); } }