diff --git a/java_indexer/src/io/coati/JavaIndexer.java b/java_indexer/src/io/coati/JavaIndexer.java index 0417badb..83168302 100644 --- a/java_indexer/src/io/coati/JavaIndexer.java +++ b/java_indexer/src/io/coati/JavaIndexer.java @@ -6,12 +6,12 @@ import java.io.StringReader; import java.lang.String; import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.PackageDeclaration; import com.github.javaparser.JavaParser; -import com.github.javaparser.ParseException; import com.github.javaparser.ParseProblemException; import com.github.javaparser.Problem; -import com.github.javaparser.Token; +import me.tomassetti.symbolsolver.javaparser.Navigator; import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade; import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JarTypeSolver; @@ -91,17 +91,31 @@ public class JavaIndexer } JavaParserFacade.clearInstances(); - - // String fileName = filePath.substring(filePath.lastIndexOf("/"), filePath.lastIndexOf(".java")); - - // System.gc(); - // HeapDumper.dumpHeap("D:/dump/" + fileName, false); } - - - - + public static String getPackageName(String fileContent) + { + String packageName = ""; + try + { + CompilationUnit cu = JavaParser.parse(new StringReader(fileContent), true); + PackageDeclaration pd = Navigator.findNodeOfGivenClass(cu, PackageDeclaration.class); + if (pd != null) + { + packageName = JavaparserDeclNameResolver.getQualifiedName(pd.getName()).toString(); + } + } + catch (ParseProblemException e) + { + // do nothing + } + catch (IllegalArgumentException e) + { + // do nothing + } + + return packageName; + } static public void recordSymbol( int address, String symbolName, SymbolType symbolType, diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index 34e033ee..add299f0 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -212,8 +212,7 @@ QtProjectWizzardContentPathsSourceJava::QtProjectWizzardContentPathsSourceJava( { setHelpString( "Project Paths define the files and directories that will be indexed by Coati. Provide a directory to recursively " - "add all contained files. To make sure that type names are resolved correctly, please add the root source directory " - "of your project (the one where all your package names are relative to).
" + "add all contained files.
" "
" "If your project's source code resides in one location, but generated source files are kept at a different location, " "you will also need to add that directory." @@ -465,7 +464,7 @@ QtProjectWizzardContentPathsClassJava::QtProjectWizzardContentPathsClassJava( setTitleString("Class Path"); setHelpString( "Enter all the .jar files your project depends on. If your project depends on uncompiled java code that should " - "not be indexed, please add the root directory of those .java files here." + "not be indexed, please add the root directory of those .java files here (the one where all the package names are relative to)." ); } diff --git a/src/lib_java/JavaProject.cpp b/src/lib_java/JavaProject.cpp index bb8dc2f3..393b12a3 100644 --- a/src/lib_java/JavaProject.cpp +++ b/src/lib_java/JavaProject.cpp @@ -1,9 +1,14 @@ #include "JavaProject.h" +#include "component/view/DialogView.h" #include "data/parser/java/JavaEnvironmentFactory.h" +#include "data/parser/java/JavaEnvironment.h" #include "data/parser/java/TaskParseJava.h" +#include "utility/file/FileRegister.h" +#include "utility/text/TextAccess.h" #include "utility/messaging/type/MessageStatus.h" #include "utility/ResourcePaths.h" +#include "utility/utilityString.h" #include "Application.h" #include "isTrial.h" @@ -31,6 +36,8 @@ const std::shared_ptr JavaProject::getProjectSettings() const bool JavaProject::prepareIndexing() { + m_rootDirectories.reset(); + std::string errorString; if (!JavaEnvironmentFactory::getInstance() && !isTrial()) { @@ -89,11 +96,18 @@ std::shared_ptr JavaProject::createIndexerTask( } } - for (FilePath sourcePath: m_projectSettings->getAbsoluteSourcePaths()) + if (!m_rootDirectories) { - if (sourcePath.extension().empty() && sourcePath.exists()) + getDialogView()->showProgressDialog("Preparing Project", "Gathering Root\nDirectories"); + fetchRootDirectories(); + getDialogView()->hideProgressDialog(); + } + + for (FilePath rootDirectory: *(m_rootDirectories.get())) + { + if (rootDirectory.exists()) { - arguments.javaClassPaths.push_back(sourcePath.str()); + arguments.javaClassPaths.push_back(rootDirectory.str()); } } @@ -114,3 +128,49 @@ void JavaProject::updateFileManager(FileManager& fileManager) fileManager.setPaths(sourcePaths, headerPaths, excludePaths, sourceExtensions); } + +void JavaProject::fetchRootDirectories() +{ + m_rootDirectories = std::make_shared>(); + + FileManager fileManager; + fileManager.setPaths( + m_projectSettings->getAbsoluteSourcePaths(), + std::vector(), + m_projectSettings->getAbsoluteExcludePaths(), + m_projectSettings->getSourceExtensions() + ); + fileManager.fetchFilePaths(std::vector()); + std::shared_ptr javaEnvironment = JavaEnvironmentFactory::getInstance()->createEnvironment(); + for (FilePath filePath: fileManager.getAddedFilePaths()) + { + std::shared_ptr textAccess = TextAccess::createFromFile(filePath.str()); + + std::string packageName = ""; + javaEnvironment->callStaticMethod("io/coati/JavaIndexer", "getPackageName", packageName, textAccess->getText()); + + if (packageName.empty()) + { + continue; + } + + FilePath rootPath = filePath.parentDirectory(); + bool success = true; + + const std::vector packageNameParts = utility::splitToVector(packageName, "."); + for (std::vector::const_reverse_iterator it = packageNameParts.rbegin(); it != packageNameParts.rend(); it++) + { + if (rootPath.fileName() != (*it)) + { + success = false; + break; + } + rootPath = rootPath.parentDirectory(); + } + + if (success) + { + m_rootDirectories->insert(rootPath); + } + } +} diff --git a/src/lib_java/JavaProject.h b/src/lib_java/JavaProject.h index afda2840..14fb33e1 100644 --- a/src/lib_java/JavaProject.h +++ b/src/lib_java/JavaProject.h @@ -30,8 +30,11 @@ private: std::shared_ptr fileRegister); virtual void updateFileManager(FileManager& fileManager); + + void fetchRootDirectories(); std::shared_ptr m_projectSettings; + std::shared_ptr> m_rootDirectories; friend Project; }; diff --git a/src/lib_java/data/parser/java/JavaEnvironment.cpp b/src/lib_java/data/parser/java/JavaEnvironment.cpp index a648531c..b8ae68aa 100644 --- a/src/lib_java/data/parser/java/JavaEnvironment.cpp +++ b/src/lib_java/data/parser/java/JavaEnvironment.cpp @@ -12,31 +12,33 @@ JavaEnvironment::~JavaEnvironment() bool JavaEnvironment::callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4) { - jclass javaClass = m_env->FindClass(className.c_str()); - if(javaClass == nullptr) + jclass javaClass = getJavaClass(className); + jmethodID javaMethodId = getJavaStaticMethod(javaClass, methodName, "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if(javaMethodId != nullptr) { - LOG_ERROR("class " + className + " not found in JVM environment"); - jthrowable exc = m_env->ExceptionOccurred(); - if(exc) - { - m_env->ExceptionDescribe(); - m_env->ExceptionClear(); - } + jint jarg1 = arg1; + jstring jarg2 = m_env->NewStringUTF(arg2.c_str()); + jstring jarg3 = m_env->NewStringUTF(arg3.c_str()); + jstring jarg4 = m_env->NewStringUTF(arg4.c_str()); + m_env->CallStaticVoidMethod(javaClass, javaMethodId, jarg1, jarg2, jarg3, jarg4); + return true; } - else + return false; +} + +bool JavaEnvironment::callStaticMethod(std::string className, std::string methodName, std::string& ret, std::string arg1) +{ + jclass javaClass = getJavaClass(className); + jmethodID javaMethodId = getJavaStaticMethod(javaClass, methodName, "(Ljava/lang/String;)Ljava/lang/String;"); + if(javaMethodId != nullptr) { - jmethodID javaMethodId = m_env->GetStaticMethodID(javaClass, methodName.c_str(), "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - if(javaMethodId == nullptr) + jstring jarg1 = m_env->NewStringUTF(arg1.c_str()); + jstring jret = (jstring)m_env->CallStaticObjectMethod(javaClass, javaMethodId, jarg1); + if (jret) { - LOG_ERROR("method void " + methodName + "(int, String, String, String) not found in JVM environment"); - } - else - { - jint jarg1 = arg1; - jstring jarg2 = m_env->NewStringUTF(arg2.c_str()); - jstring jarg3 = m_env->NewStringUTF(arg3.c_str()); - jstring jarg4 = m_env->NewStringUTF(arg4.c_str()); - m_env->CallStaticVoidMethod(javaClass, javaMethodId, jarg1, jarg2, jarg3, jarg4); + const char *buffer = m_env->GetStringUTFChars(jret, JNI_FALSE); + ret = std::string(buffer); + m_env->ReleaseStringUTFChars(jret, buffer); return true; } } @@ -56,13 +58,6 @@ jstring JavaEnvironment::toJString(std::string s) return m_env->NewStringUTF(s.c_str()); } -JavaEnvironment::JavaEnvironment(JavaVM* jvm, JNIEnv* env) - : m_jvm(jvm) - , m_env(env) -{ - JavaEnvironmentFactory::getInstance()->registerEnvironment(); -} - void JavaEnvironment::registerNativeMethods(std::string className, std::vector methods) { JNINativeMethod* jniMethods = new JNINativeMethod[methods.size()]; @@ -90,3 +85,44 @@ void JavaEnvironment::registerNativeMethods(std::string className, std::vectorregisterEnvironment(); +} + +jclass JavaEnvironment::getJavaClass(const std::string& className) +{ + jclass javaClass = m_env->FindClass(className.c_str()); + if(javaClass == nullptr) + { + LOG_ERROR("class " + className + " not found in JVM environment"); + jthrowable exc = m_env->ExceptionOccurred(); + if(exc) + { + m_env->ExceptionDescribe(); + m_env->ExceptionClear(); + } + } + return javaClass; +} + +jmethodID JavaEnvironment::getJavaStaticMethod(const std::string& className, const std::string& methodName, const std::string& methodSignature) +{ + return getJavaStaticMethod(getJavaClass(className), methodName, methodSignature); +} + +jmethodID JavaEnvironment::getJavaStaticMethod(jclass javaClass, const std::string& methodName, const std::string& methodSignature) +{ + if(javaClass != nullptr) + { + jmethodID javaMethodId = m_env->GetStaticMethodID(javaClass, methodName.c_str(), methodSignature.c_str()); + if(javaMethodId == nullptr) + { + LOG_ERROR("method " + methodName + methodSignature + " not found in JVM environment"); + } + return javaMethodId; + } + return nullptr; +} diff --git a/src/lib_java/data/parser/java/JavaEnvironment.h b/src/lib_java/data/parser/java/JavaEnvironment.h index 4613073f..0e41c26c 100644 --- a/src/lib_java/data/parser/java/JavaEnvironment.h +++ b/src/lib_java/data/parser/java/JavaEnvironment.h @@ -10,9 +10,15 @@ typedef JavaVM_ JavaVM; struct JNIEnv_; typedef JNIEnv_ JNIEnv; +class _jclass; +typedef _jclass *jclass; + class _jstring; typedef _jstring *jstring; +struct _jmethodID; +typedef struct _jmethodID *jmethodID; + class JavaEnvironmentFactory; class JavaEnvironment @@ -27,6 +33,7 @@ public: ~JavaEnvironment(); bool callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4); + bool callStaticMethod(std::string className, std::string methodName, std::string& ret, std::string arg1); std::string toStdString(jstring s); jstring toJString(std::string s); @@ -36,6 +43,9 @@ private: friend class JavaEnvironmentFactory; JavaEnvironment(JavaVM* jvm, JNIEnv* env); + jclass getJavaClass(const std::string& className); + jmethodID getJavaStaticMethod(const std::string& className, const std::string& methodName, const std::string& methodSignature); + jmethodID getJavaStaticMethod(jclass javaClass, const std::string& methodName, const std::string& methodSignature); JavaVM* m_jvm; JNIEnv* m_env;