This is an automated email from the ASF dual-hosted git repository. lkishalmi pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new c43ee9b [NETBEANS-4867] Fix inconsistent Gradle SubProject Detection (#2411) c43ee9b is described below commit c43ee9b5091e16ccd0adfeeb50ebaa0e45be0799 Author: Laszlo Kishalmi <laszlo.kisha...@gmail.com> AuthorDate: Wed Oct 7 09:47:33 2020 -0700 [NETBEANS-4867] Fix inconsistent Gradle SubProject Detection (#2411) * Extract disk cache implementation from GradleProjectCache * [NETBEANS-4867] Use a distinct disk cache for Gradle subprojects --- .../modules/gradle/GradleProjectCache.java | 158 +++------------------ .../modules/gradle/NbGradleProjectFactory.java | 8 +- .../gradle/api/GradleBaseProjectBuilder.java | 7 +- .../modules/gradle/cache/AbstractDiskCache.java | 156 ++++++++++++++++++++ .../modules/gradle/cache/ProjectInfoDiskCache.java | 119 ++++++++++++++++ .../modules/gradle/cache/SubProjectDiskCache.java | 134 +++++++++++++++++ .../modules/gradle/nodes/SubProjectsNode.java | 20 +-- .../gradle/nodes/SubProjectsNodeFactory.java | 16 +-- 8 files changed, 452 insertions(+), 166 deletions(-) diff --git a/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java b/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java index 0453456..f0f69ee 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java @@ -18,6 +18,8 @@ */ package org.netbeans.modules.gradle; +import org.netbeans.modules.gradle.cache.ProjectInfoDiskCache; +import org.netbeans.modules.gradle.cache.SubProjectDiskCache; import org.netbeans.modules.gradle.spi.GradleFiles; import org.netbeans.modules.gradle.api.GradleBaseProject; import org.netbeans.modules.gradle.api.NbGradleProject.Quality; @@ -26,17 +28,10 @@ import org.netbeans.modules.gradle.api.NbProjectInfo; import org.netbeans.modules.gradle.spi.GradleSettings; import org.netbeans.modules.gradle.spi.ProjectInfoExtractor; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -67,8 +62,9 @@ import static org.netbeans.modules.gradle.GradleDaemon.*; import org.netbeans.modules.gradle.api.NbGradleProject; import org.netbeans.modules.gradle.api.execute.GradleCommandLine; import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; import javax.swing.JLabel; +import org.netbeans.modules.gradle.cache.AbstractDiskCache.CacheEntry; +import org.netbeans.modules.gradle.cache.ProjectInfoDiskCache.QualifiedProjectInfo; import org.netbeans.modules.gradle.api.execute.RunUtils; import org.openide.awt.Notification; import org.openide.awt.NotificationDisplayer; @@ -86,18 +82,12 @@ public final class GradleProjectCache { private enum GoOnline { NEVER, ON_DEMAND, ALWAYS } private static final Logger LOG = Logger.getLogger(GradleProjectCache.class.getName()); - private static final String INFO_CACHE_FILE_NAME = "project-info.ser"; //NOI18N private static final Map<File, List<Notification>> NOTIFICATIONS = new WeakHashMap<>(); private static AtomicLong timeInLoad = new AtomicLong(); private static AtomicInteger loadedProjects = new AtomicInteger(); - private static final Map<File, Set<File>> SUB_PROJECT_DIR_CACHE = new ConcurrentHashMap<>(); - - // Increase this number if new info is gathered from the projects. - private static final int COMPATIBLE_CACHE_VERSION = 15; - private GradleProjectCache() { } @@ -121,12 +111,11 @@ public final class GradleProjectCache { GradleProject prev = project.project != null ? project.project : fallbackProject(files); // Try to turn to the cache - if (!(ignoreCache || GradleSettings.getDefault().isCacheDisabled()) - && (prev.getQuality() == FALLBACK)) { - ProjectCacheEntry cacheEntry = loadCachedProject(files); + if (!ignoreCache && (prev.getQuality() == FALLBACK)) { + CacheEntry<QualifiedProjectInfo> cacheEntry = new ProjectInfoDiskCache(files).loadEntry(); if (cacheEntry != null) { if (cacheEntry.isCompatible()) { - prev = createGradleProject(cacheEntry.quality, cacheEntry.data); + prev = createGradleProject(cacheEntry.getData()); if (cacheEntry.isValid()) { updateSubDirectoryCache(prev); return prev; @@ -242,12 +231,13 @@ public final class GradleProjectCache { if (SwingUtilities.isEventDispatchThread()) { LOG.log(FINE, "Load happened on AWT event dispatcher", new RuntimeException()); } - GradleProject ret = createGradleProject(quality, info); + QualifiedProjectInfo qinfo = new QualifiedProjectInfo(quality, info); + GradleProject ret = createGradleProject(qinfo); GradleArtifactStore.getDefault().processProject(ret); if (info.getMiscOnly()) { ret = ctx.previous; } else { - saveCachedProjectInfo(info, ret); + saveCachedProjectInfo(qinfo, ret); } return ret; } @@ -391,24 +381,7 @@ public final class GradleProjectCache { return sb.toString(); } - private static ProjectCacheEntry loadCachedProject(GradleFiles gf) { - File cacheFile = new File(getCacheDir(gf), INFO_CACHE_FILE_NAME); - ProjectCacheEntry ret = null; - if (cacheFile.canRead()) { - try (ObjectInputStream is = new ObjectInputStream(new FileInputStream(cacheFile))) { - try { - ret = (ProjectCacheEntry) is.readObject(); - } catch (ClassNotFoundException ex) { - LOG.log(FINE, "Invalid cache entry.", ex); - } - } catch (IOException ex) { - LOG.log(FINE, "Could no load project info from " + cacheFile, ex); - } - } - return ret; - } - - private static GradleProject createGradleProject(Quality quality, NbProjectInfo info) { + private static GradleProject createGradleProject(QualifiedProjectInfo info) { Collection<? extends ProjectInfoExtractor> extractors = Lookup.getDefault().lookupAll(ProjectInfoExtractor.class); Map<Class, Object> results = new HashMap<>(); Set<String> problems = new LinkedHashSet<>(info.getProblems()); @@ -424,7 +397,7 @@ public final class GradleProjectCache { } } - return new GradleProject(quality, problems, results.values()); + return new GradleProject(info.getQuality(), problems, results.values()); } @@ -432,32 +405,16 @@ public final class GradleProjectCache { if (gp.getQuality().atLeast(EVALUATED)) { GradleBaseProject baseProject = gp.getBaseProject(); if (baseProject.isRoot()) { - SUB_PROJECT_DIR_CACHE.put(baseProject.getProjectDir(), new HashSet<File>(baseProject.getSubProjects().values())); + SubProjectDiskCache spCache = SubProjectDiskCache.get(baseProject.getRootDir()); + spCache.storeData(new SubProjectDiskCache.SubProjectInfo(baseProject)); } } } - static Boolean isKnownSubProject(File rootDir, File subProjectDir) { - Set<File> cache = SUB_PROJECT_DIR_CACHE.get(rootDir); - return (cache != null) ? cache.contains(subProjectDir) : null; - } - - private static void saveCachedProjectInfo(NbProjectInfo data, GradleProject gp) { + private static void saveCachedProjectInfo(QualifiedProjectInfo data, GradleProject gp) { assert gp.getQuality().betterThan(FALLBACK) : "Never attempt to cache FALLBACK projects."; //NOi18N - //TODO: Make it possible to handle external file set as cache. GradleFiles gf = new GradleFiles(gp.getBaseProject().getProjectDir(), true); - Set<File> cacheInvalidators = new HashSet<>(gf.getProjectFiles()); - if (gf.hasWrapper()) cacheInvalidators.add(gf.getWrapperProperties()); - ProjectCacheEntry entry = new ProjectCacheEntry(new StoredProjectInfo(data), gp, cacheInvalidators); - File cacheFile = new File(getCacheDir(gp), INFO_CACHE_FILE_NAME); - if (!cacheFile.exists()) { - cacheFile.getParentFile().mkdirs(); - } - try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(cacheFile))) { - os.writeObject(entry); - } catch (IOException ex) { - LOG.log(FINE, "Failed to persist project info to" + cacheFile, ex); - } + new ProjectInfoDiskCache(gf).storeData(data); } private static GradleProject fallbackProject(GradleFiles files) { @@ -497,7 +454,7 @@ public final class GradleProjectCache { return dir; } - static final class ReloadContext { + private static final class ReloadContext { final NbGradleProjectImpl project; final GradleProject previous; @@ -519,85 +476,4 @@ public final class GradleProjectCache { } } - private static class ProjectCacheEntry implements Serializable { - - int version; - - long timestamp; - Set<File> sourceFiles; - Quality quality; - NbProjectInfo data; - - protected ProjectCacheEntry() { - } - - public ProjectCacheEntry(NbProjectInfo data, GradleProject gp, Set<File> sourceFiles) { - this.sourceFiles = sourceFiles; - this.data = data; - this.quality = gp.getQuality(); - this.timestamp = gp.getEvaluationTime(); - this.version = COMPATIBLE_CACHE_VERSION; - } - - public boolean isCompatible() { - return version == COMPATIBLE_CACHE_VERSION; - } - - public boolean isValid() { - boolean ret = isCompatible(); - if (ret && (sourceFiles != null)) { - for (File f : sourceFiles) { - if (!f.exists() || (f.lastModified() > timestamp)) { - ret = false; - break; - } - } - } - return ret; - } - } - - private static class StoredProjectInfo implements NbProjectInfo { - - private final Map<String, Object> info; - private final Set<String> problems; - private final String gradleException; - - public StoredProjectInfo(NbProjectInfo pinfo) { - info = new LinkedHashMap<>(pinfo.getInfo()); - problems = new LinkedHashSet<>(pinfo.getProblems()); - gradleException = pinfo.getGradleException(); - } - - @Override - public Map<String, Object> getInfo() { - return info; - } - - @Override - public Map<String, Object> getExt() { - return Collections.emptyMap(); - } - - @Override - public Set<String> getProblems() { - return problems; - } - - @Override - public String getGradleException() { - return gradleException; - } - - @Override - public boolean hasException() { - return gradleException != null; - } - - @Override - public boolean getMiscOnly() { - return false; - } - - } } diff --git a/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java b/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java index 8308d51..8137835 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java @@ -19,6 +19,7 @@ package org.netbeans.modules.gradle; +import org.netbeans.modules.gradle.cache.SubProjectDiskCache; import java.io.File; import org.netbeans.modules.gradle.spi.GradleFiles; import org.netbeans.modules.gradle.api.NbGradleProject; @@ -66,9 +67,10 @@ public final class NbGradleProjectFactory implements ProjectFactory2 { } File suspect = FileUtil.toFile(dir); GradleFiles files = new GradleFiles(suspect); - if (!files.isRootProject()) { - Boolean inSubDirCache = GradleProjectCache.isKnownSubProject(files.getRootDir(), suspect); - return inSubDirCache != null ? inSubDirCache : files.isProject(); + if ((files.getSettingsScript() != null) && !files.isRootProject()) { + SubProjectDiskCache spCache = SubProjectDiskCache.get(files.getRootDir()); + SubProjectDiskCache.SubProjectInfo data = spCache.loadData(); + return data != null && data.getProjectPath(suspect) != null; } else { return true; } diff --git a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java index 7cdfed9..5c2c4e5 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java @@ -91,7 +91,12 @@ class GradleBaseProjectBuilder implements ProjectInfoExtractor.Result { prj.license = (String) info.get("license"); prj.plugins = new TreeSet<>(createSet((Set<String>) info.get("plugins"))); - prj.subProjects = (Map<String, File>) info.get("project_subProjects"); + Map<String, File> rawSubprojects = (Map<String, File>) info.get("project_subProjects"); + Map<String, File> refinedSubprojects = (Map<String, File>) info.get("project_subProjects"); + for (Map.Entry<String, File> entry : rawSubprojects.entrySet()) { + refinedSubprojects.put(entry.getKey(), entry.getValue().isAbsolute() ? entry.getValue() : new File(prj.rootDir, entry.getValue().toString())); + } + prj.subProjects = Collections.unmodifiableMap(refinedSubprojects); prj.includedBuilds = (Map<String, File>) info.get("project_includedBuilds"); if (info.containsKey("buildClassPath")) { prj.buildClassPath = (Set<File>) info.get("buildClassPath"); diff --git a/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java b/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java new file mode 100644 index 0000000..06299ba --- /dev/null +++ b/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.gradle.cache; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Date; +import java.util.Set; +import static java.util.logging.Level.*; +import java.util.logging.Logger; +import org.netbeans.modules.gradle.spi.GradleSettings; + +/** + * + * @author lkishalmi + */ +public abstract class AbstractDiskCache <K extends Serializable, T extends Serializable> implements Serializable { + + private static final Logger LOG = Logger.getLogger(AbstractDiskCache.class.getName()); + + protected K key; + private boolean valid = false; + private transient CacheEntry<T> entry; + + protected AbstractDiskCache() {} + + protected AbstractDiskCache(K key) { + this.key = key; + } + + public synchronized final CacheEntry<T> loadEntry() { + CacheEntry<T> ret = entry; + if (ret == null && !GradleSettings.getDefault().isCacheDisabled()) { + File cacheFile = cacheFile(); + if (cacheFile.canRead()) { + try (ObjectInputStream is = new ObjectInputStream(new FileInputStream(cacheFile))) { + ret = (CacheEntry<T>) is.readObject(); + valid = true; + } catch (ClassNotFoundException | IOException ex) { + LOG.log(INFO, "Could no load project info from {0} due to: {1}", new Object[]{cacheFile, ex.getMessage()}); + cacheFile.delete(); + } + } + entry = ret; + } + return ret; + + } + + public synchronized final T loadData() { + CacheEntry<T> e = loadEntry(); + return e != null && e.isValid() ? e.getData() : null; + } + + public synchronized final void storeData(T data) { + File cacheFile = cacheFile(); + if (!cacheFile.exists()) { + cacheFile.getParentFile().mkdirs(); + } + try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(cacheFile))) { + CacheEntry e = new CacheEntryImpl(data); + os.writeObject(e); + entry = e; + } catch (IOException ex) { + LOG.log(INFO, "Failed to persist info to {0} due to {1}", new Object[]{cacheFile, ex.getMessage()}); + cacheFile.delete(); + } + } + + public synchronized final void invalidate() { + File cacheFile = cacheFile(); + valid = false; + if (cacheFile.canRead()) { + cacheFile.delete(); + } + } + protected abstract int cacheVersion(); + protected abstract File cacheFile(); + protected abstract Set<File> cacheInvalidators(); + + public interface CacheEntry <D extends Serializable> extends Serializable { + boolean isCompatible(); + boolean isValid(); + D getData(); + } + + private final class CacheEntryImpl <T extends Serializable> implements CacheEntry<T> { + int version; + + long timestamp; + Set<File> sourceFiles; + T data; + + protected CacheEntryImpl() { + } + + protected CacheEntryImpl(T data) { + timestamp = System.currentTimeMillis(); + version = cacheVersion(); + this.sourceFiles = cacheInvalidators(); + this.data = data; + } + + @Override + public boolean isCompatible() { + return version == cacheVersion(); + } + + @Override + public boolean isValid() { + boolean ret = (data != null) && isCompatible(); + if (AbstractDiskCache.this.valid && ret && (sourceFiles != null)) { + for (File f : sourceFiles) { + if (!f.exists() || (f.lastModified() > timestamp)) { + ret = false; + break; + } + } + } + return ret; + } + + @Override + public T getData() { + return data; + } + + @Override + public String toString() { + Class dataClass = data != null ? data.getClass() : null; + return "CacheEntryImpl{" + "data:version=" + dataClass + ":" + version + ", timestamp=" + new Date(timestamp) + ", sourceFiles=" + sourceFiles + '}'; + } + + } +} diff --git a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java new file mode 100644 index 0000000..66b5256 --- /dev/null +++ b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.gradle.cache; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import org.netbeans.modules.gradle.GradleProjectCache; +import org.netbeans.modules.gradle.cache.ProjectInfoDiskCache.QualifiedProjectInfo; +import org.netbeans.modules.gradle.api.NbGradleProject.Quality; +import org.netbeans.modules.gradle.api.NbProjectInfo; +import org.netbeans.modules.gradle.spi.GradleFiles; + +/** + * + * @author lkishalmi + */ +public final class ProjectInfoDiskCache extends AbstractDiskCache<GradleFiles, QualifiedProjectInfo> { + + // Increase this number if new info is gathered from the projects. + private static final int COMPATIBLE_CACHE_VERSION = 16; + private static final String INFO_CACHE_FILE_NAME = "project-info.ser"; //NOI18N + + public ProjectInfoDiskCache(GradleFiles gf) { + super(gf); + } + + @Override + protected int cacheVersion() { + return COMPATIBLE_CACHE_VERSION; + } + + @Override + protected File cacheFile() { + return new File(GradleProjectCache.getCacheDir(key), INFO_CACHE_FILE_NAME); + } + + @Override + protected Set<File> cacheInvalidators() { + Set<File> ret = new HashSet<>(key.getProjectFiles()); + if (key.hasWrapper()) ret.add(key.getWrapperProperties()); + return ret; + } + + public static final class QualifiedProjectInfo implements NbProjectInfo { + + private final Quality quality; + private final Map<String, Object> info; + private final Set<String> problems; + private final String gradleException; + + public QualifiedProjectInfo(Quality quality, NbProjectInfo pinfo) { + this.quality = quality; + info = new LinkedHashMap<>(pinfo.getInfo()); + problems = new LinkedHashSet<>(pinfo.getProblems()); + gradleException = pinfo.getGradleException(); + } + + @Override + public Map<String, Object> getInfo() { + return info; + } + + @Override + public Map<String, Object> getExt() { + return Collections.emptyMap(); + } + + @Override + public Set<String> getProblems() { + return problems; + } + + @Override + public String getGradleException() { + return gradleException; + } + + @Override + public boolean hasException() { + return gradleException != null; + } + + @Override + public boolean getMiscOnly() { + return false; + } + + public Quality getQuality() { + return quality; + } + + @Override + public String toString() { + return "QualifiedProjectInfo{" + "quality=" + quality + '}'; + } + + } +} diff --git a/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java b/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java new file mode 100644 index 0000000..91423ac --- /dev/null +++ b/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.gradle.cache; + +import java.io.File; +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import org.netbeans.modules.gradle.cache.SubProjectDiskCache.SubProjectInfo; +import org.netbeans.modules.gradle.spi.GradleFiles; +import org.gradle.tooling.model.GradleProject; +import org.netbeans.modules.gradle.api.GradleBaseProject; + +/** + * + * @author lkishalmi + */ +public class SubProjectDiskCache extends AbstractDiskCache<File, SubProjectInfo> { + + private static final String SUBPROJECT_CACHE_FILE_NAME = ".gradle/nb-cache/subprojects.ser"; //NOI18N + private static final int COMPATIBLE_CACHE_VERSION = 1; + + private static Map<File, SubProjectDiskCache> diskCaches = new WeakHashMap<>(); + + protected SubProjectDiskCache() {} + + private SubProjectDiskCache(File key) { + super(key); + } + + @Override + protected int cacheVersion() { + return COMPATIBLE_CACHE_VERSION; + } + + @Override + protected File cacheFile() { + return new File(key, SUBPROJECT_CACHE_FILE_NAME); + } + + @Override + protected Set<File> cacheInvalidators() { + return Collections.singleton(new GradleFiles(key).getSettingsScript()); + } + + public static SubProjectDiskCache get(File key) { + SubProjectDiskCache ret = diskCaches.get(key); + if (ret == null) { + ret = new SubProjectDiskCache(key); + diskCaches.put(key, ret); + } + return ret; + } + + public static final class SubProjectInfo implements Serializable { + String rootProjectName; + Map<String, String> path2Name; + Map<File, String> file2Path; + + protected SubProjectInfo() {} + + public SubProjectInfo(GradleProject prj) { + assert prj.getParent() == null : "This shall be called only on a root project!"; + rootProjectName = prj.getName(); + path2Name = new HashMap<>(); + file2Path = new HashMap<>(); + for (GradleProject child : prj.getChildren()) { + path2Name.put(child.getPath(), child.getName()); + File dir = child.getProjectDirectory(); + if (!dir.isAbsolute()) { + dir = new File(prj.getProjectDirectory(), dir.toString()); + } + file2Path.put(dir, child.getPath()); + } + } + + public SubProjectInfo(GradleBaseProject gbp) { + assert gbp.isRoot() : "This shall be called only on a root project!"; + rootProjectName = gbp.getName(); + path2Name = new HashMap<>(); + file2Path = new HashMap<>(); + for (Map.Entry<String, File> sprj : gbp.getSubProjects().entrySet()) { + file2Path.put(sprj.getValue(), sprj.getKey()); + path2Name.put(sprj.getKey(), sprj.getKey()); + } + } + + public String gerRootProjectName() { + return rootProjectName; + } + + public String getProjectName(String path) { + return path2Name.get(path); + } + + public String getProjectName(File dir) { + String path = file2Path.get(dir); + return path != null ? path2Name.get(path) : null; + } + + public String getProjectPath(File dir) { + return file2Path.get(dir); + } + + public boolean isSubproject(File dir) { + return file2Path.containsKey(dir); + } + + @Override + public String toString() { + return "SubProjects of [" + rootProjectName + "]: " + file2Path.keySet(); + } + + } +} diff --git a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java index 721cf95..b50fb52 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java @@ -30,7 +30,6 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; @@ -117,12 +116,10 @@ public class SubProjectsNode extends AbstractNode { project = proj; this.rootPath = rootPath; NbGradleProject watcher = project.getProjectWatcher(); - listener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) { - refresh(false); - } + listener = (PropertyChangeEvent evt) -> { + if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) { + ProjectManager.getDefault().clearNonProjectCache(); + refresh(false); } }; @@ -133,7 +130,7 @@ public class SubProjectsNode extends AbstractNode { @Override protected boolean createKeys(final List<String> paths) { Map<String, File> subProjects = project.getGradleProject().getBaseProject().getSubProjects(); - Set<String> components = new TreeSet<String>(); + Set<String> components = new TreeSet<>(); Set<String> projects = new TreeSet<>(); for (String path : subProjects.keySet()) { if (path.startsWith(rootPath)) { @@ -228,11 +225,8 @@ public class SubProjectsNode extends AbstractNode { final NbGradleProjectImpl[] projectsArray = projects.toArray(new NbGradleProjectImpl[0]); OpenProjects.getDefault().open(projectsArray, false, true); if (projectsArray.length > 0) { - RequestProcessor.getDefault().post(new Runnable() { - public @Override - void run() { - OpenProjects.getDefault().open(projectsArray, false, true); - } + RequestProcessor.getDefault().post(() -> { + OpenProjects.getDefault().open(projectsArray, false, true); }, 500); } } diff --git a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java index 6451bab..39d54ce 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java @@ -24,10 +24,12 @@ import org.netbeans.modules.gradle.NbGradleProjectImpl; import org.netbeans.modules.gradle.api.NbGradleProject; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.File; import java.util.Collections; import java.util.List; -import java.util.Set; +import java.util.Map; import org.netbeans.api.project.Project; +import org.netbeans.modules.gradle.GradleProject; import org.netbeans.spi.project.ui.support.NodeFactory; import org.netbeans.spi.project.ui.support.NodeList; import org.openide.nodes.Node; @@ -39,15 +41,13 @@ import org.openide.nodes.Node; @NodeFactory.Registration(projectType = NbGradleProject.GRADLE_PROJECT_TYPE, position = 400) public class SubProjectsNodeFactory implements NodeFactory { - private static final String KEY_SUBPROJECTS = "subprojects"; //NOI18N - @Override public NodeList<?> createNodes(Project project) { NbGradleProjectImpl prj = project.getLookup().lookup(NbGradleProjectImpl.class); return new NList(prj); } - private static class NList extends AbstractGradleNodeList<String> implements PropertyChangeListener { + private static class NList extends AbstractGradleNodeList<GradleProject> implements PropertyChangeListener { private final NbGradleProjectImpl project; @@ -63,13 +63,13 @@ public class SubProjectsNodeFactory implements NodeFactory { } @Override - public List<String> keys() { - Set<String> subProjects = project.getGradleProject().getBaseProject().getSubProjects().keySet(); - return subProjects.isEmpty() ? Collections.<String>emptyList() : Collections.singletonList(KEY_SUBPROJECTS); + public List<GradleProject> keys() { + Map<String, File> subProjects = project.getGradleProject().getBaseProject().getSubProjects(); + return subProjects.isEmpty() ? Collections.<GradleProject>emptyList() : Collections.singletonList(project.getGradleProject()); } @Override - public Node node(String key) { + public Node node(GradleProject key) { return new SubProjectsNode(project); } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists