Skip to content

Commit 65ffe6c

Browse files
authored
fix: Open a new gradle project in VS Code and code completion won't work (#1019)
1 parent 66569ab commit 65ffe6c

File tree

5 files changed

+73
-45
lines changed

5 files changed

+73
-45
lines changed

extension/src/Extension.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import { DependencyTreeItem } from './views/gradleTasks/DependencyTreeItem';
4040
import { GRADLE_DEPENDENCY_REVEAL } from './views/gradleTasks/DependencyUtils';
4141
import { GradleDependencyProvider } from './dependencies/GradleDependencyProvider';
4242
import { getSpecificVersionStatus } from './views/gradleDaemons/util';
43-
import { startLanguageServer } from './languageServer/languageServer';
43+
import {
44+
isLanguageServerStarted,
45+
startLanguageServer,
46+
} from './languageServer/languageServer';
4447
import { DefaultProjectsTreeDataProvider } from './views/defaultProject/DefaultProjectsTreeDataProvider';
4548

4649
export class Extension {
@@ -311,6 +314,9 @@ export class Extension {
311314
this.gradleWrapperWatcher.onDidChange(async (uri: vscode.Uri) => {
312315
logger.info('Gradle wrapper properties changed:', uri.fsPath);
313316
await this.restartServer();
317+
if (isLanguageServerStarted) {
318+
void vscode.commands.executeCommand('gradle.distributionChanged');
319+
}
314320
});
315321
}
316322

extension/src/languageServer/languageServer.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,15 @@ export async function startLanguageServer(
9191
serverOptions,
9292
clientOptions
9393
);
94-
languageClient.onReady().then(resolve, (e) => {
95-
resolve();
96-
isLanguageServerStarted = true;
97-
void vscode.window.showErrorMessage(e);
98-
});
94+
void languageClient.onReady().then(
95+
() => {
96+
isLanguageServerStarted = true;
97+
resolve();
98+
},
99+
(e) => {
100+
void vscode.window.showErrorMessage(e);
101+
}
102+
);
99103
const disposable = languageClient.start();
100104
context.subscriptions.push(disposable);
101105
context.subscriptions.push(

gradle-language-server/src/main/java/com/microsoft/gradle/GradleServices.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383

8484
public class GradleServices implements TextDocumentService, WorkspaceService, LanguageClientAware {
8585

86-
public static final List<String> supportedCommands = List.of("gradle.getDependencies");
86+
public static final List<String> supportedCommands = List.of("gradle.getDependencies", "gradle.distributionChanged");
8787

8888
private LanguageClient client;
8989
private GradleFilesManager gradleFilesManager;
@@ -157,7 +157,7 @@ public void applySetting(Object settings) {
157157
this.getLibraryResolver().setGradleVersion((String) ((Map<?, ?>) settings).get("gradleVersion"));
158158
this.getLibraryResolver().setGradleWrapperEnabled((Boolean) ((Map<?, ?>) settings).get("gradleWrapperEnabled"));
159159
this.getLibraryResolver().setGradleUserHome((String) ((Map<?, ?>) settings).get("gradleUserHome"));
160-
this.getLibraryResolver().resolve();
160+
this.getLibraryResolver().resolveGradleAPI();
161161
}
162162
}
163163

@@ -279,6 +279,7 @@ public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completio
279279
containingCall = call;
280280
}
281281
}
282+
this.libraryResolver.loadGradleClasses();
282283
boolean javaPluginsIncluded = this.libraryResolver.isJavaPluginsIncluded(this.completionVisitor.getPlugins(uri));
283284
CompletionHandler handler = new CompletionHandler();
284285
// check again
@@ -318,6 +319,8 @@ public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
318319
}
319320
List<DefaultDependencyItem> result = defaultDependenciesHandler.getDefaultDependencies(dependencies);
320321
return CompletableFuture.completedFuture(result);
322+
} else if (command.equals("gradle.distributionChanged")) {
323+
this.libraryResolver.resolveGradleAPI();
321324
}
322325
return CompletableFuture.completedFuture(null);
323326
}

gradle-language-server/src/main/java/com/microsoft/gradle/handlers/CompletionHandler.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public List<CompletionItem> getCompletionItems(MethodCallExpression containingCa
4848
if (delegateClassName == null) {
4949
return Collections.emptyList();
5050
}
51-
JavaClass delegateClass = resolver.getGradleLibraries().get(delegateClassName);
51+
JavaClass delegateClass = resolver.getGradleClasses().get(delegateClassName);
5252
if (delegateClass == null) {
5353
return Collections.emptyList();
5454
}
@@ -61,13 +61,13 @@ private List<CompletionItem> getCompletionItemsFromClass(JavaClass javaClass, Gr
6161
}
6262
List<CompletionItem> results = new ArrayList<>();
6363
for (String superInterface : javaClass.getInterfaceNames()) {
64-
if (resolver.getGradleLibraries().containsKey(superInterface)) {
65-
results.addAll(getCompletionItemsFromClass(resolver.getGradleLibraries().get(superInterface), resolver, javaPluginsIncluded, resultSet));
64+
if (resolver.getGradleClasses().containsKey(superInterface)) {
65+
results.addAll(getCompletionItemsFromClass(resolver.getGradleClasses().get(superInterface), resolver, javaPluginsIncluded, resultSet));
6666
}
6767
}
6868
String superClass = javaClass.getSuperclassName();
69-
if (resolver.getGradleLibraries().containsKey(superClass)) {
70-
results.addAll(getCompletionItemsFromClass(resolver.getGradleLibraries().get(superClass), resolver, javaPluginsIncluded, resultSet));
69+
if (resolver.getGradleClasses().containsKey(superClass)) {
70+
results.addAll(getCompletionItemsFromClass(resolver.getGradleClasses().get(superClass), resolver, javaPluginsIncluded, resultSet));
7171
}
7272
List<String> methodNames = new ArrayList<>();
7373
Method[] methods = javaClass.getMethods();

gradle-language-server/src/main/java/com/microsoft/gradle/resolver/GradleLibraryResolver.java

+47-32
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,21 @@ public class GradleLibraryResolver {
3636

3737
private static String JAVA_PLUGIN = "org.gradle.api.plugins.JavaPlugin";
3838

39-
private Map<String, JavaClass> gradleLibraries = new HashMap<>();
39+
private Map<String, JavaClass> gradleClasses = new HashMap<>();
4040
private Set<String> javaConfigurations = new HashSet<>();
4141
private Set<String> javaPlugins = new HashSet<>();
4242
private String gradleHome;
4343
private String gradleVersion;
4444
private boolean gradleWrapperEnabled;
4545
private String gradleUserHome;
4646
private Path workspacePath;
47+
private File coreAPI;
48+
private File pluginAPI;
49+
private boolean needToLoadClasses;
4750

4851
public GradleLibraryResolver() {
4952
this.javaPlugins.addAll(Arrays.asList("java", "application", "groovy", "java-library", "war"));
53+
this.needToLoadClasses = true;
5054
}
5155

5256
public void setGradleHome(String gradleHome) {
@@ -69,47 +73,52 @@ public void setWorkspacePath(Path workspacePath) {
6973
this.workspacePath = workspacePath;
7074
}
7175

72-
public Map<String, JavaClass> getGradleLibraries() {
73-
return this.gradleLibraries;
76+
public Map<String, JavaClass> getGradleClasses() {
77+
return this.gradleClasses;
7478
}
7579

7680
public Set<String> getJavaConfigurations() {
7781
return this.javaConfigurations;
7882
}
7983

80-
public void resolve() {
84+
public boolean resolveGradleAPI() {
85+
this.needToLoadClasses = true;
8186
Path gradleUserHomePath = (this.gradleUserHome == null) ? Path.of(System.getProperty("user.home"), ".gradle")
8287
: Path.of(this.gradleUserHome);
83-
File libFile = null;
8488
if (this.gradleWrapperEnabled) {
85-
libFile = findLibWithWrapper(gradleUserHomePath);
89+
this.coreAPI = findCoreAPIWithWrapper(gradleUserHomePath);
8690
} else if (this.gradleVersion != null) {
87-
libFile = findLibWithDist(gradleUserHomePath, "gradle-" + this.gradleVersion);
91+
this.coreAPI = findCoreAPIWithDist(gradleUserHomePath, "gradle-" + this.gradleVersion);
8892
} else if (this.gradleHome != null) {
89-
Path libPath = Path.of(this.gradleHome).resolve("lib");
90-
libFile = findLibFile(libPath.toFile());
93+
this.coreAPI = findCoreAPI(Path.of(this.gradleHome).resolve("lib").toFile());
9194
} else {
92-
return;
95+
return false;
96+
}
97+
if (!isValidFile(this.coreAPI)) {
98+
return false;
9399
}
94-
if (libFile == null || !libFile.exists()) {
100+
this.pluginAPI = findPluginAPI(this.coreAPI.toPath().getParent().resolve(Path.of("plugins")).toFile());
101+
return isValidFile(this.pluginAPI);
102+
}
103+
104+
public void loadGradleClasses() {
105+
boolean isAPIValid = isValidFile(this.coreAPI) && isValidFile(this.pluginAPI);
106+
if (!this.needToLoadClasses || (!isAPIValid && !this.resolveGradleAPI())) {
95107
return;
96108
}
97109
try {
98-
JarFile libJar = new JarFile(libFile);
99-
getGradleLibraries(libFile.toPath(), libJar);
100-
File pluginLibFile = findPluginLibFile(libFile.toPath().getParent().resolve(Path.of("plugins")).toFile());
101-
if (pluginLibFile == null) {
102-
return;
103-
}
104-
JarFile pluginLibJar = new JarFile(pluginLibFile);
105-
getGradleLibraries(pluginLibFile.toPath(), pluginLibJar);
106-
resolveJavaConfigurations();
110+
JarFile coreAPIJar = new JarFile(this.coreAPI);
111+
loadClasses(this.coreAPI.toPath(), coreAPIJar);
112+
JarFile pluginAPIJar = new JarFile(this.pluginAPI);
113+
loadClasses(this.pluginAPI.toPath(), pluginAPIJar);
114+
loadJavaConfigurations();
115+
this.needToLoadClasses = false;
107116
} catch (Exception e) {
108117
// Do Nothing
109118
}
110119
}
111120

112-
private File findLibWithWrapper(Path gradleUserHomePath) {
121+
private File findCoreAPIWithWrapper(Path gradleUserHomePath) {
113122
if (this.workspacePath == null) {
114123
return null;
115124
}
@@ -128,7 +137,7 @@ private File findLibWithWrapper(Path gradleUserHomePath) {
128137
Matcher matcher = p.matcher(content);
129138
if (matcher.find()) {
130139
String gradleDist = matcher.group(1);
131-
return findLibWithDist(gradleUserHomePath, gradleDist);
140+
return findCoreAPIWithDist(gradleUserHomePath, gradleDist);
132141
}
133142
}
134143
}
@@ -138,12 +147,12 @@ private File findLibWithWrapper(Path gradleUserHomePath) {
138147
return null;
139148
}
140149

141-
private File findLibWithDist(Path gradleUserHomePath, String gradleDist) {
150+
private File findCoreAPIWithDist(Path gradleUserHomePath, String gradleDist) {
142151
Path distPath = gradleUserHomePath.resolve(Path.of("wrapper", "dists"));
143152
File distFolder = searchInFolder(gradleDist, distPath.toFile());
144153
if (distFolder != null && distFolder.exists()) {
145154
Path libPath = distFolder.toPath().resolve("lib");
146-
return findLibFile(libPath.toFile());
155+
return findCoreAPI(libPath.toFile());
147156
}
148157
return null;
149158
}
@@ -164,14 +173,15 @@ private File searchInFolder(String gradleDist, File folder) {
164173
return null;
165174
}
166175

167-
private File findLibFile(File folder) {
176+
private File findCoreAPI(File folder) {
168177
for (File file : folder.listFiles()) {
169178
String name = file.getName();
170179
if (name.startsWith("gradle-core-api") && name.endsWith(".jar")) {
171180
return file;
172181
}
173182
}
174-
// For Gradle version under 5.6, the name of library file is like gradle-core-${version}.jar
183+
// For Gradle version under 5.6, the name of library file is like
184+
// gradle-core-${version}.jar
175185
for (File file : folder.listFiles()) {
176186
String name = file.getName();
177187
if (name.startsWith("gradle-core") && name.endsWith(".jar")) {
@@ -181,7 +191,7 @@ private File findLibFile(File folder) {
181191
return null;
182192
}
183193

184-
private File findPluginLibFile(File folder) {
194+
private File findPluginAPI(File folder) {
185195
for (File file : folder.listFiles()) {
186196
String name = file.getName();
187197
if (name.startsWith("gradle-plugins") && name.endsWith(".jar")) {
@@ -191,7 +201,7 @@ private File findPluginLibFile(File folder) {
191201
return null;
192202
}
193203

194-
private void getGradleLibraries(Path jarPath, JarFile jarFile) {
204+
private void loadClasses(Path jarPath, JarFile jarFile) {
195205
Enumeration<JarEntry> entries = jarFile.entries();
196206
while (entries.hasMoreElements()) {
197207
JarEntry entry = entries.nextElement();
@@ -202,15 +212,15 @@ private void getGradleLibraries(Path jarPath, JarFile jarFile) {
202212
try {
203213
JavaClass javaClass = parser.parse();
204214
String className = javaClass.getClassName();
205-
this.gradleLibraries.put(className, javaClass);
215+
this.gradleClasses.put(className, javaClass);
206216
} catch (IOException | ClassFormatException e) {
207217
// Do Nothing
208218
}
209219
}
210220
}
211221

212-
private void resolveJavaConfigurations() {
213-
JavaClass javaPluginClass = this.gradleLibraries.get(GradleLibraryResolver.JAVA_PLUGIN);
222+
private void loadJavaConfigurations() {
223+
JavaClass javaPluginClass = this.gradleClasses.get(GradleLibraryResolver.JAVA_PLUGIN);
214224
if (javaPluginClass == null) {
215225
return;
216226
}
@@ -222,7 +232,8 @@ private void resolveJavaConfigurations() {
222232
}
223233

224234
private static String removeQuotes(String original) {
225-
// for those fields parsed from class files, we get ""values"", so we remove the starting and ending quotes here
235+
// for those fields parsed from class files, we get ""values"", so we remove the
236+
// starting and ending quotes here
226237
if (original.length() < 3) {
227238
return original;
228239
}
@@ -237,4 +248,8 @@ public boolean isJavaPluginsIncluded(Set<String> plugins) {
237248
}
238249
return false;
239250
}
251+
252+
private static boolean isValidFile(File file) {
253+
return file != null && file.exists();
254+
}
240255
}

0 commit comments

Comments
 (0)