Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android project has no code suggestions #3284

Open
zykowal opened this issue Sep 25, 2024 · 7 comments
Open

Android project has no code suggestions #3284

zykowal opened this issue Sep 25, 2024 · 7 comments

Comments

@zykowal
Copy link

zykowal commented Sep 25, 2024

In Android project how can I get android code suggestions?

OS: windows 10
Gradle: 6.5
JDK: installed 8, 11 ,17
IDE: Neovim 0.10.1

I set JAVA_HOME and ANDROID_HOME in the system variables, but after building the project and install dependences, no errors, I only get basic JDK code suggestions and no Android code suggestions. Do I need to make any special settings in my lua file, or is there any other configuration needed? I'm a newbie in this area and would appreciate any help! Thanks!

my config

config = {
        -- set jdtls server settings
        jdtls = {
          function()
            -- use this function notation to build some variables
            local root_markers = { ".git", "mvnw", "gradlew", "pom.xml", "build.gradle" }
            local root_dir = require("jdtls.setup").find_root(root_markers)
            -- calculate workspace dir
            local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
            local workspace_dir = vim.fn.stdpath "data" .. "/site/java/workspace-root/" .. project_name
            os.execute("mkdir " .. workspace_dir)
            -- get the mason install path
            local install_path = require("mason-registry").get_package("jdtls"):get_install_path()
            -- get the current OS
            local os
            if vim.fn.has "macunix" then
              os = "mac"
            elseif vim.fn.has "win32" then
              os = "win"
            else
              os = "linux"
            end
            -- return the server config
            return {
              cmd = {
                "java",
                "-Declipse.application=org.eclipse.jdt.ls.core.id1",
                "-Dosgi.bundles.defaultStartLevel=4",
                "-Declipse.product=org.eclipse.jdt.ls.core.product",
                "-Dlog.protocol=true",
                "-Dlog.level=ALL",
                "-javaagent:" .. install_path .. "/lombok.jar",
                "-Xms1g",
                "--add-modules=ALL-SYSTEM",
                "--add-opens",
                "java.base/java.util=ALL-UNNAMED",
                "--add-opens",
                "java.base/java.lang=ALL-UNNAMED",
                "-jar",
                vim.fn.glob(install_path .. "/plugins/org.eclipse.equinox.launcher_*.jar"),
                "-configuration",
                install_path .. "/config_" .. os,
                "-data",
                workspace_dir,
              },
              root_dir = root_dir,
            }
          end,
        },
      },
@zykowal
Copy link
Author

zykowal commented Sep 25, 2024

If someone could help me, I would be extremely grateful. 😃

@amgdev9
Copy link

amgdev9 commented Oct 31, 2024

Having exactly the same issue, seems that jdtls is not able to get the classpath from the gradle project if it is using the android gradle plugin or something. Manually adding jars from the android dependencies (extracting the .aar files to get the classes.jar file) to the .classpath file I managed to get some autocomplete, but not all. Also enabling the setting to enable android project support didn't have any effect either

@amgdev9
Copy link

amgdev9 commented Nov 1, 2024

@codewithtoucans I finally managed to get it to work, but as the gradle classpath resolver is not working properly we need to workaround it adding the necessary jars from the android sdk and dependencies to the .classpath file in the app module. Here is my raw setup, but beware that some tweaking is needed depending on the project (adjusting the sdk version, configured variants, sdk path...):

Add this task to the app build.gradle.kts, which is used to get the compile classpath for the declared dependencies:

tasks.register("printCompileClasspath") {
    doLast {
        println("---START---")
        configurations.getByName("debugCompileClasspath").files.forEach { file ->
            println(file.absolutePath)
        }
        println("---END---")
    }
}

And then run this script to fill the .classpath file:

import subprocess
import os

result = subprocess.run(['./gradlew', 'app:printCompileClasspath'], stdout=subprocess.PIPE).stdout.decode("utf-8")

# Split by lines
lines = result.split('\n')
# Get the lines between ---START--- and ---END--- lines
start = lines.index("---START---") + 1
end = lines.index("---END---")
lines = lines[start:end]
print(lines)

final_lines = []

for line in lines:
    if line.endswith('.aar'):
        # Get the folder path
        folder = os.path.dirname(line)
        # Extract the aar in that folder
        subprocess.run(['unzip', '-o', line, '-d', folder])
        # Add the classes.jar
        final_lines.append(os.path.join(folder, 'classes.jar'))
    else:
        final_lines.append(line)

with open('app/.classpath', 'w') as f:
    f.write("""
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="output" path="bin/default"/>
    <classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="lib" path="/home/amg/Projects/JavaApp/app/build/intermediates/compile_and_runtime_not_namespaced_r_class_jar/debug/processDebugResources/R.jar"/>
    <classpathentry kind="lib" path="/home/amg/SDK/android/platforms/android-34/android.jar"/>
<classpathentry kind="lib" path="/home/amg/SDK/android/platforms/android-34/core-for-system-modules.jar"/>
""")
    for line in final_lines:
        f.write(f'  <classpathentry kind="lib" path="{line}"/>\n')

I haven't configured it yet to support some features (such as viewbinding or buildconfig), but it should be straightforward to add the support for these with this base

@mickaelistria
Copy link
Contributor

JDT-LS relies on Eclipse BuildShip to compute a proper Gradle classpath. Maybe the issue should also be reported at https://github.com/eclipse/buildship/issues ?

@nolanpollack
Copy link

JDT-LS relies on Eclipse BuildShip to compute a proper Gradle classpath. Maybe the issue should also be reported at https://github.com/eclipse/buildship/issues ?

This seems like a jdt-ls issue, as Android support was implemented directly in jdt-ls here: #2197

I also tried running this in the demo Android application that was added in that PR and experienced the same issue, so presumably something has broken the support.

@zykowal
Copy link
Author

zykowal commented Dec 1, 2024

@amgdev9 It doesn't work for me. I have tried many settings, but none of them work. However, if I just run a gradle project, like a Spring Boot project, it works perfectly fine. I don't have a good idea about Android project.

@zykowal
Copy link
Author

zykowal commented Dec 1, 2024

@nolanpollack @mickaelistria I looked through the #2197 PR and didn't find any configuration they mentioned, so I just followed the normal configuration, but it didn't work. The eclipse.jdt.ls wiki.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants