From 94fa0c2e18a540c505b7ff8e053c3c6265b620da Mon Sep 17 00:00:00 2001 From: Michael Kaspera Date: Tue, 27 Sep 2022 07:30:39 +0200 Subject: [PATCH] feat: ignored warnings now work in modularized projects --- .../nodejs/impl/ls/IgnoredWarningsCache.java | 82 ---------- .../nodejs/impl/ls/IgnoredWarningsFacade.java | 9 +- .../impl/ls/IgnoredWarningsProvider.java | 142 ++++++++++++++++++ .../nbm/nodejs/impl/ls/JSHintsFilter.java | 7 +- .../options/IgnoredWarningsTablePanel.java | 6 +- 5 files changed, 154 insertions(+), 92 deletions(-) delete mode 100644 src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsCache.java create mode 100644 src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsProvider.java diff --git a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsCache.java b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsCache.java deleted file mode 100644 index e2d6645..0000000 --- a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsCache.java +++ /dev/null @@ -1,82 +0,0 @@ -package de.adito.aditoweb.nbm.nodejs.impl.ls; - -import com.google.gson.Gson; -import de.adito.notification.INotificationFacade; -import de.adito.observables.netbeans.FileObservable; -import de.adito.util.reactive.cache.ObservableCache; -import io.reactivex.rxjava3.core.Observable; -import org.jetbrains.annotations.*; -import org.netbeans.api.project.Project; -import org.openide.filesystems.FileUtil; - -import java.io.*; -import java.util.*; - -/** - * @author m.kaspera, 26.08.2022 - */ -public class IgnoredWarningsCache -{ - - private static final IgnoredWarningsCache INSTANCE = new IgnoredWarningsCache(); - private final ObservableCache cacheObs = new ObservableCache(); - - private IgnoredWarningsCache() - { - } - - @NotNull - public static IgnoredWarningsCache getInstance() - { - return INSTANCE; - } - - @NotNull - public Observable> get(@NotNull Project pProject) - { - return cacheObs.calculateParallel(pProject, () -> { - try - { - File ignoredWarningsFile = getIgnoredWarningsFile(pProject); - return FileObservable.createForPlainFile(ignoredWarningsFile) - .map(pFile -> readIgnoredWarnings(ignoredWarningsFile)); - } - catch (IOException pE) - { - INotificationFacade.INSTANCE.error(pE); - return Observable.just(Set.of()); - } - }); - } - - @SuppressWarnings("ResultOfMethodCallIgnored") // ignore for mkdirs and createNewFile - @NotNull - public static File getIgnoredWarningsFile(@NotNull Project pProject) throws IOException - { - File ignoredWarnings = new File(FileUtil.toFile(pProject.getProjectDirectory()), ".aditoprj/ignoredWarnings"); - if (!ignoredWarnings.exists()) - { - ignoredWarnings.getParentFile().mkdirs(); - ignoredWarnings.createNewFile(); - } - return ignoredWarnings; - } - - private Set readIgnoredWarnings(@Nullable File pIgnoreFile) throws FileNotFoundException - { - if (pIgnoreFile == null) - return Set.of(); - IgnoreWarningFix.FileContent fileContent = new Gson().fromJson(new FileReader(pIgnoreFile), IgnoreWarningFix.FileContent.class); - HashSet warningsSet = new HashSet<>(); - Set> entrySet = Optional.ofNullable(fileContent) - .map(pFileContent -> pFileContent.content) - .map(Map::entrySet) - .orElse(Set.of()); - for (Map.Entry warningItem : entrySet) - { - warningsSet.add(new IgnoredWarningsFacade.WarningsItem(Integer.parseInt(warningItem.getKey()), warningItem.getValue())); - } - return warningsSet; - } - -} diff --git a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsFacade.java b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsFacade.java index 35d27f4..84141ce 100644 --- a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsFacade.java +++ b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsFacade.java @@ -17,7 +17,6 @@ public class IgnoredWarningsFacade { - private static final IgnoredWarningsCache warningsCache = IgnoredWarningsCache.getInstance(); private IgnoredWarningsFacade() { @@ -26,7 +25,9 @@ private IgnoredWarningsFacade() @NotNull public static Observable> getIgnoredWarnings(@NotNull Project pProject) { - return warningsCache.get(pProject); + return Optional.ofNullable(pProject.getLookup().lookup(IgnoredWarningsProvider.class)) + .map(IgnoredWarningsProvider::get) + .orElse(Observable.just(Set.of())); } public static void addIgnoredWarning(@NotNull Project pProject, int pId, @NotNull String pDescription) throws IOException @@ -70,12 +71,12 @@ private static void writeToFile(@NotNull Project pProject, Stream fileContent.content = pWarningsItemStream .distinct() .collect(Collectors.toMap(pWarningsItem -> String.valueOf(pWarningsItem.getId()), WarningsItem::getDescription)); - try (FileWriter writer = new FileWriter(IgnoredWarningsCache.getIgnoredWarningsFile(pProject))) + try (FileWriter writer = new FileWriter(IgnoredWarningsProvider.getIgnoredWarningsFile(pProject))) { writer.write(new GsonBuilder().setPrettyPrinting().create().toJson(fileContent)); writer.flush(); } - FileUtil.toFileObject(IgnoredWarningsCache.getIgnoredWarningsFile(pProject)).refresh(); + FileUtil.toFileObject(IgnoredWarningsProvider.getIgnoredWarningsFile(pProject)).refresh(); } public static class WarningsItem diff --git a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsProvider.java b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsProvider.java new file mode 100644 index 0000000..477aefe --- /dev/null +++ b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/IgnoredWarningsProvider.java @@ -0,0 +1,142 @@ +package de.adito.aditoweb.nbm.nodejs.impl.ls; + +import com.google.gson.Gson; +import de.adito.aditoweb.nbm.nbide.nbaditointerface.project.IProjectVisibility; +import de.adito.notification.INotificationFacade; +import de.adito.observables.netbeans.FileObservable; +import io.reactivex.rxjava3.core.Observable; +import org.jetbrains.annotations.*; +import org.netbeans.api.project.*; +import org.openide.filesystems.FileUtil; +import org.openide.util.lookup.ServiceProvider; + +import java.io.*; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author m.kaspera, 26.08.2022 + */ +@ServiceProvider(service = IgnoredWarningsProvider.class, path = "Projects/de-adito-project/Lookup") +public class IgnoredWarningsProvider +{ + + private Observable> warningsObs = null; + private final Project project; + + public IgnoredWarningsProvider() + { + project = null; + } + + public IgnoredWarningsProvider(Project pProject) + { + project = pProject; + } + + /** + * IMPORTANT: only use this method if the instance of this serviceProvider was obtained by querying the lookup of the actual project, + * if you got obtained this instance by querying the default lookup use the get(Project pProject) method. + * + * @return Observable of the Set of WarningsItems that are ignored for the given project. Contains items of the parent project(s) if this project + * is only used as a module, or an empty Observable if this serviceProvider did not get a project + */ + @NotNull + public Observable> get() + { + if (project != null) + return get(project); + else + return Observable.just(Set.of()); + } + + /** + * @param pProject Project whose warningsItems should be obtained + * @return Observable of the Set of WarningsItems that are ignored for the given project. Contains items of the parent project(s) if this project + * is only used as a module + */ + @NotNull + public Observable> get(@NotNull Project pProject) + { + if (warningsObs == null) + { + try + { + if (Boolean.TRUE.equals(pProject.getLookup().lookup(IProjectVisibility.class).isVisible())) + { + File ignoredWarningsFile = getIgnoredWarningsFile(pProject); + warningsObs = FileObservable.createForPlainFile(ignoredWarningsFile) + .map(pFile -> readIgnoredWarnings(ignoredWarningsFile)); + } + else + { + List>> warningsItemsObs = new ArrayList<>(); + Project currentProj = pProject; + boolean breakLoop = false; + while (currentProj != null && !breakLoop) + { + breakLoop = (Boolean.TRUE.equals(currentProj.getLookup().lookup(IProjectVisibility.class).isVisible())); + File ignoredWarningsFile = getIgnoredWarningsFile(currentProj); + warningsItemsObs.add(FileObservable.createForPlainFile(ignoredWarningsFile) + .map(pFile -> readIgnoredWarnings(ignoredWarningsFile))); + currentProj = FileOwnerQuery.getOwner(currentProj.getProjectDirectory().getParent()); + } + warningsObs = Observable.combineLatest(warningsItemsObs, IgnoredWarningsProvider::combineSetArray); + } + } + catch (IOException pE) + { + INotificationFacade.INSTANCE.error(pE); + warningsObs = Observable.just(Set.of()); + } + } + return warningsObs; + } + + /** + * Combine an array containing sets of warningsItems to a single set + * + * @param setSet array of sets of warningsItems + * @return combined set + */ + @NotNull + private static Set combineSetArray(@NotNull Object[] setSet) + { + //noinspection unchecked array contains sets of WarningsItems, but has to be object array to satisfy signatures + return Arrays.stream(setSet) + .map(pX -> ((Set) pX)) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + } + + @SuppressWarnings("ResultOfMethodCallIgnored") // ignore for mkdirs and createNewFile + @NotNull + public static File getIgnoredWarningsFile(@NotNull Project pProject) throws IOException + { + File ignoredWarnings = new File(FileUtil.toFile(pProject.getProjectDirectory()), ".aditoprj/ignoredWarnings"); + if (!ignoredWarnings.exists()) + { + ignoredWarnings.getParentFile().mkdirs(); + ignoredWarnings.createNewFile(); + } + return ignoredWarnings; + } + + private Set readIgnoredWarnings(@Nullable File pIgnoreFile) throws FileNotFoundException + { + if (pIgnoreFile == null) + return Set.of(); + IgnoreWarningFix.FileContent fileContent = new Gson().fromJson(new FileReader(pIgnoreFile), IgnoreWarningFix.FileContent.class); + HashSet warningsSet = new HashSet<>(); + Set> entrySet = Optional.ofNullable(fileContent) + .map(pFileContent -> pFileContent.content) + .map(Map::entrySet) + .orElse(Set.of()); + for (Map.Entry warningItem : entrySet) + { + warningsSet.add(new IgnoredWarningsFacade.WarningsItem(Integer.parseInt(warningItem.getKey()), warningItem.getValue())); + } + return warningsSet; + } + +} diff --git a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/JSHintsFilter.java b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/JSHintsFilter.java index 909a2bb..90805ba 100644 --- a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/JSHintsFilter.java +++ b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/ls/JSHintsFilter.java @@ -2,7 +2,7 @@ import de.adito.aditoweb.nbm.nbide.nbaditointerface.lsp.ILSPHintsFilter; import org.jetbrains.annotations.*; -import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.*; import org.openide.filesystems.FileObject; import org.openide.text.PositionBounds; import org.openide.util.lookup.ServiceProvider; @@ -31,9 +31,10 @@ public boolean canFilter(@NotNull FileObject pFileObject) @Override public boolean filter(@NotNull FileObject pFileObject, @Nullable String pId, @NotNull String pDescription, @NotNull String pSeverity, @Nullable PositionBounds pRange) { + Project project = FileOwnerQuery.getOwner(pFileObject); // Filter hints that were set as ignored by the user - Set warningsItems = IgnoredWarningsCache.getInstance() - .get(FileOwnerQuery.getOwner(pFileObject)) + Set warningsItems = project.getLookup().lookup(IgnoredWarningsProvider.class) + .get() .blockingFirst(); if (pId != null && warningsItems.stream().anyMatch(pWarningsItem -> pWarningsItem.getId() == Integer.parseInt(pId))) return false; diff --git a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/options/IgnoredWarningsTablePanel.java b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/options/IgnoredWarningsTablePanel.java index d3546b0..4cdcd85 100644 --- a/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/options/IgnoredWarningsTablePanel.java +++ b/src/main/java/de/adito/aditoweb/nbm/nodejs/impl/options/IgnoredWarningsTablePanel.java @@ -58,9 +58,9 @@ private static class IgnoredWarningsTableModel implements TableModel public IgnoredWarningsTableModel(@NotNull Project pOpenProject, @NotNull JTable pTable) { - IgnoredWarningsCache cache = IgnoredWarningsCache.getInstance(); + IgnoredWarningsProvider provider = pOpenProject.getLookup().lookup(IgnoredWarningsProvider.class); IDisposerService disposerService = Lookup.getDefault().lookup(IDisposerService.class); - disposerService.register(pOpenProject, cache.get(pOpenProject).subscribe(pWarningsItems -> { + disposerService.register(pOpenProject, provider.get().subscribe(pWarningsItems -> { warningsItems = pWarningsItems.stream() .sorted(Comparator.comparing(IgnoredWarningsFacade.WarningsItem::getId)) .collect(Collectors.toList()); @@ -183,7 +183,7 @@ public void actionPerformed(ActionEvent e) try { IgnoredWarningsFacade.unIgnoreWarnings(project, itemsToRemove); - FileUtil.toFileObject(IgnoredWarningsCache.getIgnoredWarningsFile(project)).refresh(); + FileUtil.toFileObject(IgnoredWarningsProvider.getIgnoredWarningsFile(project)).refresh(); } catch (IOException pE) {