[java] module files change tracker

This commit is contained in:
Roman Shevchenko
2016-10-24 17:17:30 +02:00
parent c42ed9ae73
commit 7f0f232c83
4 changed files with 76 additions and 8 deletions
@@ -18,8 +18,10 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.JavaModuleFileChangeTracker;
import com.intellij.psi.impl.source.PsiJavaModuleReference;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.util.CachedValueProvider.Result;
@@ -36,7 +38,6 @@ import java.util.*;
import java.util.stream.Collectors;
import static com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE;
import static com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT;
public class JavaModuleGraphUtil {
private JavaModuleGraphUtil() { }
@@ -51,13 +52,13 @@ public class JavaModuleGraphUtil {
public static Collection<PsiJavaModule> findCycle(@NotNull PsiJavaModule module) {
Project project = module.getProject();
List<Set<PsiJavaModule>> cycles = CachedValuesManager.getManager(project).getCachedValue(project, () ->
Result.create(findCycles(project), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT));
Result.create(findCycles(project), dependencies(project)));
return ContainerUtil.find(cycles, set -> set.contains(module));
}
public static boolean exports(@NotNull PsiJavaModule source, @NotNull String packageName, @NotNull PsiJavaModule target) {
Map<String, Set<String>> exports = CachedValuesManager.getCachedValue(source, () ->
Result.create(exportsMap(source), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT));
Result.create(exportsMap(source), dependencies(source.getProject())));
Set<String> targets = exports.get(packageName);
return targets != null && (targets.isEmpty() || targets.contains(target.getModuleName()));
}
@@ -65,10 +66,14 @@ public class JavaModuleGraphUtil {
public static boolean reads(@NotNull PsiJavaModule source, @NotNull PsiJavaModule destination) {
Project project = source.getProject();
RequiresGraph graph = CachedValuesManager.getManager(project).getCachedValue(project, () ->
Result.create(buildRequiresGraph(project), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT));
Result.create(buildRequiresGraph(project), dependencies(project)));
return graph.reads(source, destination);
}
private static Object[] dependencies(Project project) {
return new Object[]{JavaModuleFileChangeTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project)};
}
// Looks for cycles between Java modules in the project sources.
// Library/JDK modules are excluded - in assumption there can't be any lib -> src dependencies.
// Module references are resolved "globally" (i.e., without taking project dependencies into account).
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.JavaModuleFileChangeTracker;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.CachedValueProvider.Result;
import com.intellij.psi.util.CachedValuesManager;
@@ -37,7 +38,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.intellij.openapi.util.Pair.pair;
import static com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT;
import static com.intellij.util.ObjectUtils.notNull;
public class LightJavaModule extends LightElement implements PsiJavaModule {
@@ -151,7 +151,8 @@ public class LightJavaModule extends LightElement implements PsiJavaModule {
@Override
public Result<LightJavaModule> compute(Pair<PsiManager, VirtualFile> p) {
LightJavaModule module = new LightJavaModule(p.first, p.second);
return Result.create(module, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, ProjectRootModificationTracker.getInstance(p.first.getProject()));
Project project = p.first.getProject();
return Result.create(module, JavaModuleFileChangeTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project));
}
}, false, pair(manager, jarRoot));
}
@@ -0,0 +1,61 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed 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 com.intellij.psi.impl.source;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.*;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaModuleFileChangeTracker implements ModificationTracker {
@NotNull
public static ModificationTracker getInstance(@NotNull final Project p) {
return CachedValuesManager.getManager(p).getCachedValue(p, new CachedValueProvider<JavaModuleFileChangeTracker>() {
@Nullable
@Override
public Result<JavaModuleFileChangeTracker> compute() {
return Result.create(new JavaModuleFileChangeTracker(p), NEVER_CHANGED);
}
});
}
private volatile long myCount = 0;
private JavaModuleFileChangeTracker(Project project) {
PsiManager.getInstance(project).addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
@Override public void childAdded(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
@Override public void childRemoved(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
@Override public void childReplaced(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
@Override public void childMoved(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
@Override public void childrenChanged(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
@Override public void propertyChanged(@NotNull PsiTreeChangeEvent event) { process(event.getFile()); }
private void process(PsiFile file) {
if (file != null && PsiJavaModule.MODULE_INFO_FILE.equals(file.getName())) {
myCount++;
}
}
}, project);
}
@Override
public long getModificationCount() {
return myCount;
}
}
@@ -19,6 +19,7 @@ import com.intellij.core.JavaCoreBundle;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
@@ -41,7 +42,6 @@ import java.util.Collection;
import java.util.Collections;
import static com.intellij.openapi.util.Pair.pair;
import static com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT;
public class PsiJavaModuleReference extends PsiReferenceBase.Poly<PsiJavaModuleReferenceElement> {
public PsiJavaModuleReference(@NotNull PsiJavaModuleReferenceElement element) {
@@ -138,7 +138,8 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly<PsiJavaModuleR
public Result<PsiJavaModule> compute(Pair<String, Boolean> p) {
Collection<PsiJavaModule> modules = Resolver.findModules(refOwner.getContainingFile(), p.first, p.second);
PsiJavaModule module = modules.size() == 1 ? modules.iterator().next() : null;
return Result.create(module, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
Project project = refOwner.getProject();
return Result.create(module, JavaModuleFileChangeTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project));
}
}, false, pair(refText, incompleteCode));
}