Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Maxim Medvedev
2011-02-04 16:11:14 +03:00
31 changed files with 323 additions and 191 deletions
-1
View File
@@ -302,7 +302,6 @@ def layoutFull(String home, String targetDirectory) {
fileset(dir: "$home/plugins/groovy/resources/conf")
fileset(dir: "${home}/plugins/groovy/lib")
}
}
@@ -18,15 +18,8 @@ package com.intellij.codeInspection.inferNullity;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
@@ -43,16 +36,12 @@ import java.util.Collection;
import java.util.HashSet;
public class NullityInferrer {
private static final Logger LOG = Logger.getInstance("#" + NullityInferrer.class.getName());
private static final int MAX_PASSES = 10;
private int numAnnotationsAdded = 0;
private final HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>> myNotNullSet =
new HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>>();
private final HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>> myNullableSet =
new HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>>();
private boolean myAnnotateLocalVariables;
private SmartPointerManager myPointerManager;
private final HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>> myNotNullSet = new HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>>();
private final HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>> myNullableSet = new HashSet<SmartPsiElementPointer<? extends PsiModifierListOwner>>();
private final boolean myAnnotateLocalVariables;
private final SmartPointerManager myPointerManager;
public NullityInferrer(boolean annotateLocalVariables, Project project) {
@@ -260,11 +249,7 @@ public class NullityInferrer {
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
final PsiMethod method = expression.resolveMethod();
if (method == null) {
neverNull = false;
} else {
neverNull = isNotNull(method);
}
neverNull = method != null && isNotNull(method);
}
private boolean isNeverNull() {
@@ -154,7 +154,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
}
}
if (getConstructors().size() == 0 && !isInterface() && !isAnonymous()) {
if (getConstructors().isEmpty() && !isInterface() && !isAnonymous()) {
RefImplicitConstructorImpl refImplicitConstructor = new RefImplicitConstructorImpl(this);
setDefaultConstructor(refImplicitConstructor);
addConstructor(refImplicitConstructor);
@@ -173,7 +173,12 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
final PsiClass applet = getRefJavaManager().getApplet();
setApplet(applet != null && psiClass.isInheritor(applet, true));
getRefManager().fireNodeInitialized(this);
getRefManager().getPsiManager().dropResolveCaches();
PsiManager psiManager = getRefManager().getPsiManager();
psiManager.dropResolveCaches();
PsiFile file = psiClass.getContainingFile();
if (file != null) {
psiManager.dropFileCaches(file);
}
}
private void initializeSuperReferences(PsiClass psiClass) {
@@ -434,7 +439,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
if (super.isReferenced()) return true;
if (isInterface() || isAbstract()) {
if (getSubClasses().size() > 0) return true;
if (!getSubClasses().isEmpty()) return true;
}
return false;
@@ -444,7 +449,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
if (super.hasSuspiciousCallers()) return true;
if (isInterface() || isAbstract()) {
if (getSubClasses().size() > 0) return true;
if (!getSubClasses().isEmpty()) return true;
}
return false;
@@ -37,7 +37,7 @@ import com.intellij.psi.JavaDirectoryService;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PlatformTestUtil;
import javax.swing.*;
import java.io.IOException;
@@ -56,16 +56,16 @@ public class NavigateFromSourceTest extends BaseProjectViewTestCase {
checkNavigateFromSourceBehaviour(psiClass, virtualFile, pane);
IdeaTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
" -PsiDirectory: showClassMembers\n" +
" -PsiDirectory: src\n" +
" -PsiDirectory: com\n" +
" -PsiDirectory: package1\n" +
" [Class1]\n" +
" Class2\n" +
getRootFiles() +
" +External Libraries\n"
, true);
PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
" -PsiDirectory: showClassMembers\n" +
" -PsiDirectory: src\n" +
" -PsiDirectory: com\n" +
" -PsiDirectory: package1\n" +
" [Class1]\n" +
" Class2\n" +
getRootFiles() +
" +External Libraries\n"
, true);
changeClassTextAndTryToNavigate("class Class11 {}", (PsiJavaFile)containingFile, pane, "-Project\n" +
" -PsiDirectory: showClassMembers\n" +
@@ -102,19 +102,20 @@ public class NavigateFromSourceTest extends BaseProjectViewTestCase {
assertEquals(1, tree.getSelectionCount());
}
private void changeClassTextAndTryToNavigate(final String newClassString,
PsiJavaFile psiFile,
final AbstractProjectViewPSIPane pane,
final String expected) throws IOException, InterruptedException {
private static void changeClassTextAndTryToNavigate(final String newClassString,
PsiJavaFile psiFile,
final AbstractProjectViewPSIPane pane,
final String expected) throws IOException, InterruptedException {
PsiClass psiClass = psiFile.getClasses()[0];
final VirtualFile virtualFile = psiClass.getContainingFile().getVirtualFile();
final JTree tree = pane.getTree();
writeToFile(virtualFile, newClassString.getBytes());
IdeaTestUtil.waitForAlarm(600);
PlatformTestUtil.waitForAlarm(600);
psiClass = psiFile.getClasses()[0];
pane.select(psiClass, virtualFile, true);
IdeaTestUtil.assertTreeEqual(tree, expected, true);
PlatformTestUtil.assertTreeEqual(tree, expected, true);
}
private static void writeToFile(final VirtualFile virtualFile, final byte[] b) throws IOException {
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.search.ProjectScope;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
@@ -51,7 +52,7 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i
return psiClass;
}
private PsiClass addClass(@NonNls final String rootPath, @NotNull @NonNls final String classText) throws IOException {
private PsiClass addClass(@NonNls final String rootPath, @NotNull @NonNls final String classText) {
final PsiClass aClass = ((PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.java", classText)).getClasses()[0];
final String qName = aClass.getQualifiedName();
assert qName != null;
@@ -65,6 +66,13 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i
return ((PsiJavaFile)psiFile).getClasses()[0];
}
@Override
protected PsiFile addFileToProject(String rootPath, String relativePath, String fileText) {
PsiFile file = super.addFileToProject(rootPath, relativePath, fileText);
((PsiModificationTrackerImpl)PsiManager.getInstance(getProject()).getModificationTracker()).incCounter();
return file;
}
@Override
@NotNull
public PsiClass findClass(@NotNull @NonNls final String name) {
@@ -125,22 +125,21 @@ public class ExtensionPointImpl<T> implements ExtensionPoint<T> {
private void internalRegisterExtension(T extension, ExtensionComponentAdapter adapter, int index, boolean runNotifications) {
if (myExtensions.contains(extension)) {
myLogger.error("Extension was already added: " + extension);
return;
}
else {
myExtensions.add(index, extension);
myLoadedAdapters.add(index, adapter);
if (runNotifications) {
if (extension instanceof Extension) {
try {
((Extension)extension).extensionAdded(this);
}
catch (Throwable e) {
myLogger.error(e);
}
myExtensions.add(index, extension);
myLoadedAdapters.add(index, adapter);
if (runNotifications) {
if (extension instanceof Extension) {
try {
((Extension)extension).extensionAdded(this);
}
catch (Throwable e) {
myLogger.error(e);
}
notifyListenersOnAdd(extension, adapter.getPluginDescriptor());
}
notifyListenersOnAdd(extension, adapter.getPluginDescriptor());
}
}
@@ -163,31 +162,28 @@ public class ExtensionPointImpl<T> implements ExtensionPoint<T> {
result = myExtensionsCache;
if (result == null) {
processAdapters();
List<T> extensions = new ArrayList<T>(myExtensions);
List<T> problemExtensions = new ArrayList<T>();
final Class<T> extensionClass = getExtensionClass();
for (Iterator<T> iterator = extensions.iterator(); iterator.hasNext();) {
T t = iterator.next();
//noinspection unchecked
result = myExtensions.toArray((T[])Array.newInstance(extensionClass, myExtensions.size()));
for (int i = result.length - 1; i >= 0; i--) {
T t = result[i];
if (i > 0 && result[i] == result[i - 1]) {
LOG.error("Duplicate extension found: " + t + "; " +
" Result: "+ Arrays.asList(result)+";\n" +
" extensions: "+ myExtensions+";\n" +
" getExtensionClass(): "+ extensionClass +";\n" +
" size:"+myExtensions.size()+";"+result.length);
}
if (!extensionClass.isAssignableFrom(t.getClass())) {
problemExtensions.add(t);
iterator.remove();
LOG.error("Extension '" + t.getClass() + "' must be an instance of '" + extensionClass + "'",
new ExtensionException(t.getClass()));
result = ArrayUtil.remove(result, i); // we assume that usually all extensions are OK
}
}
for (T problemExtension : problemExtensions) {
LOG.error("Extension '" + problemExtension.getClass() + "' should be instance of '" + extensionClass + "'", new ExtensionException(problemExtension.getClass()));
}
//noinspection unchecked
myExtensionsCache = result = extensions.toArray((T[])Array.newInstance(extensionClass, extensions.size()));
for (int i = 1; i < result.length; i++) {
assert result[i] != result[i - 1] : "Result: "+ Arrays.asList(result)+";\n" +
" extensions: "+ extensions+";\n" +
" getExtensionClass(): "+ extensionClass +";\n" +
" size:"+extensions.size()+";"+result.length;
}
myExtensionsCache = result;
}
}
}
@@ -341,18 +341,23 @@ public class AnalysisScope {
if (needReadAction) {
PsiDocumentManager.getInstance(psiManager.getProject()).commitAndRunReadAction(new Runnable(){
public void run() {
file.accept(visitor);
psiManager.dropResolveCaches();
doProcessFile(visitor, psiManager, file);
}
});
} else {
file.accept(visitor);
psiManager.dropResolveCaches();
}
else {
doProcessFile(visitor, psiManager, file);
}
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
return indicator == null || !indicator.isCanceled();
}
private static void doProcessFile(PsiElementVisitor visitor, PsiManager psiManager, PsiFile file) {
file.accept(visitor);
psiManager.dropResolveCaches();
psiManager.dropFileCaches(file);
}
protected void accept(@NotNull final PsiDirectory dir, @NotNull final PsiElementVisitor visitor, final boolean needReadAction) {
final Project project = dir.getProject();
final PsiManager psiManager = PsiManager.getInstance(project);
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
* The main entry point for accessing the PSI services for a project.
*/
public abstract class PsiManager extends UserDataHolderBase {
/**
* Returns the PSI manager instance for the specified project.
*
@@ -239,4 +238,5 @@ public abstract class PsiManager extends UserDataHolderBase {
public abstract void unregisterLanguageInjector(@NotNull LanguageInjector injector);
public abstract void dropFileCaches(@NotNull PsiFile file);
}
@@ -82,7 +82,7 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext {
private ProgressIndicator myProgressIndicator;
public static final JobDescriptor BUILD_GRAPH = new JobDescriptor(InspectionsBundle.message("inspection.processing.job.descriptor"));
public static final JobDescriptor[] BUILD_GRAPH_ONLY = new JobDescriptor[]{BUILD_GRAPH};
public static final JobDescriptor[] BUILD_GRAPH_ONLY = {BUILD_GRAPH};
public static final JobDescriptor FIND_EXTERNAL_USAGES =
new JobDescriptor(InspectionsBundle.message("inspection.processing.job.descriptor1"));
@@ -557,6 +557,9 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext {
catch (Exception e) {
LOG.error(e);
}
finally {
psiManager.dropFileCaches(file);
}
}
});
}
@@ -373,6 +373,7 @@ public class RefManagerImpl extends RefManager {
visitElement(viewProvider.getPsi(language));
}
myPsiManager.dropResolveCaches();
myPsiManager.dropFileCaches(file);
}
}
@@ -362,7 +362,7 @@ public class FindUsagesManager implements JDOMExternalizable {
return processor.process(UsageInfoToUsageConverter.convert(descriptor, usageInfo));
}
});
List<? extends PsiElement> elements =
final List<? extends PsiElement> elements =
ApplicationManager.getApplication().runReadAction(new Computable<List<? extends PsiElement>>() {
public List<? extends PsiElement> compute() {
return descriptor.getAllElements();
@@ -381,7 +381,12 @@ public class FindUsagesManager implements JDOMExternalizable {
handler.processElementUsages(element, usageInfoProcessor, options);
}
PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequests(options.fastTrack, new ReadActionProcessor<PsiReference>() {
Project project = ApplicationManager.getApplication().runReadAction(new Computable<Project>() {
public Project compute() {
return scopeFile != null ? scopeFile.getProject() : !elements.isEmpty() ? elements.get(0).getProject() : handler.getProject();
}
});
PsiManager.getInstance(project).getSearchHelper().processRequests(options.fastTrack, new ReadActionProcessor<PsiReference>() {
public boolean processInReadAction(final PsiReference ref) {
TextRange rangeInElement = ref.getRangeInElement();
return usageInfoProcessor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
@@ -269,12 +269,7 @@ public class FindInProjectUtil {
String message = "<html><body>";
if (largeFiles.size() == 1) {
final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile();
message
+= "File '"
+ getPresentablePath(vFile)
+ "'&nbsp;("
+ presentableSize(getFileLength(vFile))
+ ") is ";
message += "File " + presentableFileInfo(vFile) + " is ";
}
else {
message += "Files<br> ";
@@ -282,11 +277,7 @@ public class FindInProjectUtil {
int counter = 0;
for (PsiFile file : largeFiles) {
final VirtualFile vFile = file.getVirtualFile();
message +=
getPresentablePath(vFile)
+ "&nbsp;("
+ presentableSize(getFileLength(vFile))
+ ")<br> ";
message += presentableFileInfo(vFile) + "<br> ";
if (counter++ > 10) break;
}
@@ -312,6 +303,13 @@ public class FindInProjectUtil {
}
}
private static String presentableFileInfo(VirtualFile vFile) {
return getPresentablePath(vFile)
+ "&nbsp;("
+ presentableSize(getFileLength(vFile))
+ ")";
}
private static int processUsagesInFile(final PsiFile psiFile,
final FindModel findModel,
final Processor<UsageInfo> consumer) {
@@ -339,11 +337,11 @@ public class FindInProjectUtil {
}
private static String getPresentablePath(final VirtualFile virtualFile) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
return "'" + ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return virtualFile.getPresentableUrl();
}
});
}) + "'";
}
private static String presentableSize(long bytes) {
@@ -434,9 +432,8 @@ public class FindInProjectUtil {
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
final VirtualFileFilter contentFilter = new VirtualFileFilter() {
public boolean accept(final VirtualFile file) {
if (file.isDirectory()) return true;
if (fileTypeManager.isFileIgnored(file) || fileTypeManager.getFileTypeByFile(file).isBinary()) return false;
return searchScope.contains(file);
return file.isDirectory() ||
!fileTypeManager.isFileIgnored(file) && !fileTypeManager.getFileTypeByFile(file).isBinary() && searchScope.contains(file);
}
};
for (VirtualFile file : files) {
@@ -567,8 +564,7 @@ public class FindInProjectUtil {
private static boolean canOptimizeForFastWordSearch(final FindModel findModel) {
return !findModel.isRegularExpressions()
&& (findModel.getCustomScope() == null || findModel.getCustomScope() instanceof GlobalSearchScope)
;
&& (findModel.getCustomScope() == null || findModel.getCustomScope() instanceof GlobalSearchScope);
}
private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
@@ -588,7 +584,7 @@ public class FindInProjectUtil {
if (!result.isStringFound()) break;
UsageInfo info = new UsageInfo(psiFile, result.getStartOffset(), result.getEndOffset());
consumer.process(info);
if (!consumer.process(info)) break;
count++;
final int prevOffset = offset;
@@ -51,11 +51,15 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
public ScriptingLibraryMappings(final Project project, final LibraryType libraryType) {
super(project);
myLibraryManager = new ScriptingLibraryManager(project, libraryType);
registerLibraryTableListener(this, this);
Disposer.register(project, this);
}
public void registerLibraryTableListener(LibraryTable.Listener listener, Disposable parentDisposable) {
if (myLibraryManager.ensureModel()) {
LibraryTable libTable = myLibraryManager.getLibraryTable();
if (libTable != null) libTable.addListener(this, this);
if (libTable != null) libTable.addListener(listener, parentDisposable);
}
Disposer.register(project, this);
}
protected String serialize(final ScriptingLibraryTable.LibraryModel library) {
@@ -91,7 +95,6 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
newContainer.addLibrary(libraryModel);
}
}
newContainer.applyChanges();
setMapping(file, newContainer.isEmpty() ? null : newContainer);
if (!newContainer.isEmpty()) {
if (file == null) {
@@ -182,7 +185,7 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
container = new CompoundLibrary();
}
if (!((CompoundLibrary)container).containsLibrary(libName)) {
((CompoundLibrary)container).toggleLibrary(libraryModel);
((CompoundLibrary)container).addLibrary(libraryModel);
setMapping(file, container);
}
updateDependencies(getMappings());
@@ -210,10 +213,9 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
for (String libName : libNames) {
ScriptingLibraryTable.LibraryModel libraryModel = myLibraryManager.getLibraryByName(libName.trim());
if (libraryModel != null) {
compoundLib.toggleLibrary(libraryModel);
compoundLib.addLibrary(libraryModel);
}
}
compoundLib.applyChanges();
if (file == null) {
myProjectLibs = compoundLib;
}
@@ -331,6 +333,7 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
private void addLibrary(@NotNull ScriptingLibraryTable.LibraryModel library) {
final String libName = library.getName();
myLibraries.put(libName, library);
applyChanges();
}
public boolean containsLibrary(String libName) {
@@ -18,9 +18,13 @@ package com.intellij.ide.scriptingContext.ui;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.scriptingContext.LangScriptingContextConfigurable;
import com.intellij.ide.scriptingContext.ScriptingLibraryMappings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.scripting.ScriptingLibraryTable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.tree.LanguagePerFileConfigurable;
@@ -33,7 +37,9 @@ import java.util.Map;
/**
* @author Rustam Vishnyakov
*/
public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<ScriptingLibraryTable.LibraryModel> {
public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<ScriptingLibraryTable.LibraryModel>
implements LibraryTable.Listener,
Disposable {
private final ScriptingLibraryMappings myScriptingLibraryMappings;
private final LangScriptingContextConfigurable myParent;
@@ -46,6 +52,8 @@ public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<S
IdeBundle.message("scripting.lib.usageScope.override.title"));
myScriptingLibraryMappings = mappings;
myParent = parent;
mappings.registerLibraryTableListener(this, this);
Disposer.register(project, this);
}
public void resetMappings() {
@@ -115,4 +123,26 @@ public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<S
return false;
}
@Override
public void dispose() {
}
@Override
public void afterLibraryAdded(Library newLibrary) {
reset();
}
@Override
public void afterLibraryRenamed(Library library) {
reset();
}
@Override
public void beforeLibraryRemoved(Library library) {
}
@Override
public void afterLibraryRemoved(Library library) {
reset();
}
}
@@ -109,20 +109,20 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
if (!editorWindow.isValid()/* || myDocumentWindow.intersects(editorWindow.myDocumentWindow)*/) {
editorWindow.dispose();
InjectedLanguageUtil.clearCaches(editorWindow.getInjectedFile());
InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
iterator.remove();
}
}
}
private boolean isValid() {
return !isDisposed() && myInjectedFile.isValid() && myDocumentWindow.isValid();
return !isDisposed() && !myInjectedFile.getProject().isDisposed() && myInjectedFile.isValid() && myDocumentWindow.isValid();
}
public PsiFile getInjectedFile() {
return myInjectedFile;
}
public LogicalPosition hostToInjected(LogicalPosition pos) {
public LogicalPosition hostToInjected(@NotNull LogicalPosition pos) {
assert isValid();
int offsetInInjected = myDocumentWindow.hostToInjected(myDelegate.logicalPositionToOffset(pos));
return offsetToLogicalPosition(offsetInInjected);
@@ -186,6 +186,10 @@ public class MockPsiManager extends PsiManagerEx {
}
@Override
public void dropFileCaches(@NotNull PsiFile file) {
}
public void postponeAutoFormattingInside(Runnable runnable) {
PostprocessReformattingAspect.getInstance(getProject()).postponeFormattingInside(runnable);
}
@@ -222,9 +226,6 @@ public class MockPsiManager extends PsiManagerEx {
public void registerRunnableToRunOnChange(@NotNull Runnable runnable) {
}
public void registerWeakRunnableToRunOnChange(@NotNull Runnable runnable) {
}
public void registerRunnableToRunOnAnyChange(@NotNull Runnable runnable) {
}
@@ -113,6 +113,7 @@ public class BackwardDependenciesBuilder extends DependenciesBuilder {
}
}
psiManager.dropResolveCaches();
psiManager.dropFileCaches(file);
}
});
}
@@ -138,6 +138,7 @@ public class ForwardDependenciesBuilder extends DependenciesBuilder {
collectedDeps.addAll(found);
psiManager.dropResolveCaches();
psiManager.dropFileCaches(file);
}
}
collectedDeps.removeAll(processed);
@@ -0,0 +1,21 @@
/*
* Copyright 2000-2011 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;
public interface AnyPsiChangeListener {
void beforePsiChanged(boolean isPhysical);
void afterPsiChanged(boolean isPhysical);
}
@@ -46,8 +46,6 @@ public abstract class PsiManagerEx extends PsiManager {
*/
public abstract void registerRunnableToRunOnChange(@NotNull Runnable runnable);
public abstract void registerWeakRunnableToRunOnChange(@NotNull Runnable runnable);
/**
* @param runnable to be run before <b>physical</b> or <b>non-physical</b> PSI change
*/
@@ -53,6 +53,7 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
@@ -61,12 +62,13 @@ import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -76,6 +78,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiManagerImpl");
private final Project myProject;
private final MessageBus myMessageBus;
private final FileManager myFileManager;
private final PsiSearchHelperImpl mySearchHelper;
@@ -94,11 +97,6 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
private final List<PsiTreeChangeListener> myTreeChangeListeners = ContainerUtil.createEmptyCOWList();
private boolean myTreeChangeEventIsFiring = false;
private final List<Runnable> myRunnablesOnChange = ContainerUtil.createEmptyCOWList();
private final List<WeakReference<Runnable>> myWeakRunnablesOnChange = ContainerUtil.createEmptyCOWList();
private final List<Runnable> myRunnablesOnAnyChange = ContainerUtil.createEmptyCOWList();
private final List<Runnable> myRunnablesAfterAnyChange = ContainerUtil.createEmptyCOWList();
private boolean myIsDisposed;
private VirtualFileFilter myAssertOnFileLoadingFilter = VirtualFileFilter.NONE;
@@ -106,6 +104,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
private final AtomicInteger myBatchFilesProcessingModeCount = new AtomicInteger(0);
private static final Key<PsiFile> CACHED_PSI_FILE_COPY_IN_FILECONTENT = Key.create("CACHED_PSI_FILE_COPY_IN_FILECONTENT");
public static final Topic<AnyPsiChangeListener> ANY_PSI_CHANGE_TOPIC = Topic.create("PSI_CHANGE_TOPIC",AnyPsiChangeListener.class, Topic.BroadcastDirection.TO_PARENT);
private final List<LanguageInjector> myLanguageInjectors = ContainerUtil.createEmptyCOWList();
@@ -114,8 +113,9 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
StartupManager startupManager,
FileTypeManager fileTypeManager,
FileDocumentManager fileDocumentManager,
PsiBuilderFactory psiBuilderFactory) {
PsiBuilderFactory psiBuilderFactory, MessageBus messageBus) {
myProject = project;
myMessageBus = messageBus;
//We need to initialize PsiBuilderFactory service so it won't initialize under PsiLock from ChameleonTransform
@SuppressWarnings({"UnusedDeclaration", "UnnecessaryLocalVariable"}) Object used = psiBuilderFactory;
@@ -175,6 +175,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
nonPhysicalChange();
}
@Override
public void dropFileCaches(@NotNull PsiFile file) {
InjectedLanguageUtil.clearCachedInjectedFragmentsForFile(file);
}
public boolean isInProject(@NotNull PsiElement element) {
PsiFile file = element.getContainingFile();
if (file instanceof PsiFileImpl && file.isPhysical() && file.getViewProvider().getVirtualFile() instanceof LightVirtualFile) return true;
@@ -368,7 +373,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
@TestOnly
public void cleanupForNextTest() {
//myFileManager.cleanupForNextTest();
myFileManager.cleanupForNextTest();
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode());
}
@@ -495,7 +500,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
}
public void childAdded(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(CHILD_ADDED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -504,11 +509,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void childRemoved(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(CHILD_REMOVED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -516,11 +521,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void childReplaced(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(CHILD_REPLACED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -530,11 +535,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void childMoved(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(CHILD_MOVED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -544,11 +549,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void childrenChanged(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(CHILDREN_CHANGED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -556,11 +561,11 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void propertyChanged(PsiTreeChangeEventImpl event) {
onChange(true);
beforeChange(true);
event.setCode(PROPERTY_CHANGED);
if (LOG.isDebugEnabled()) {
LOG.debug(
@@ -571,7 +576,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
);
}
fireEvent(event);
afterAnyChange();
afterAnyChange(true);
}
public void addTreeChangePreprocessor(PsiTreeChangePreprocessor preprocessor) {
@@ -658,57 +663,59 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
}
}
public void registerRunnableToRunOnChange(@NotNull Runnable runnable) {
myRunnablesOnChange.add(runnable);
public void registerRunnableToRunOnChange(@NotNull final Runnable runnable) {
myMessageBus.connect().subscribe(ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() {
@Override
public void beforePsiChanged(boolean isPhysical) {
if (isPhysical) runnable.run();
}
@Override
public void afterPsiChanged(boolean isPhysical) {
}
});
}
public void registerWeakRunnableToRunOnChange(@NotNull Runnable runnable) {
myWeakRunnablesOnChange.add(new WeakReference<Runnable>(runnable));
public void registerRunnableToRunOnAnyChange(@NotNull final Runnable runnable) { // includes non-physical changes
myMessageBus.connect().subscribe(ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() {
@Override
public void beforePsiChanged(boolean isPhysical) {
runnable.run();
}
@Override
public void afterPsiChanged(boolean isPhysical) {
}
});
}
public void registerRunnableToRunOnAnyChange(@NotNull Runnable runnable) { // includes non-physical changes
myRunnablesOnAnyChange.add(runnable);
}
public void registerRunnableToRunAfterAnyChange(@NotNull final Runnable runnable) { // includes non-physical changes
myMessageBus.connect().subscribe(ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() {
@Override
public void beforePsiChanged(boolean isPhysical) {
}
public void registerRunnableToRunAfterAnyChange(@NotNull Runnable runnable) { // includes non-physical changes
myRunnablesAfterAnyChange.add(runnable);
@Override
public void afterPsiChanged(boolean isPhysical) {
runnable.run();
}
});
}
public void nonPhysicalChange() {
onChange(false);
beforeChange(false);
}
public void physicalChange() {
onChange(true);
beforeChange(true);
}
private void onChange(boolean isPhysical) {
if (isPhysical) {
runRunnables(myRunnablesOnChange);
WeakReference[] refs = myWeakRunnablesOnChange.toArray(new WeakReference[myWeakRunnablesOnChange.size()]);
myWeakRunnablesOnChange.clear();
for (WeakReference ref : refs) {
Runnable runnable = ref != null ? (Runnable)ref.get() : null;
if (runnable != null) {
runnable.run();
}
}
}
runRunnables(myRunnablesOnAnyChange);
private void beforeChange(boolean isPhysical) {
myMessageBus.syncPublisher(ANY_PSI_CHANGE_TOPIC).beforePsiChanged(isPhysical);
}
private void afterAnyChange() {
runRunnables(myRunnablesAfterAnyChange);
}
private static void runRunnables(List<Runnable> runnables) {
if (runnables.isEmpty()) return;
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < runnables.size(); i++) {
runnables.get(i).run();
}
private void afterAnyChange(boolean isPhysical) {
myMessageBus.syncPublisher(ANY_PSI_CHANGE_TOPIC).afterPsiChanged(isPhysical);
}
@NotNull
@@ -288,12 +288,16 @@ public class InjectedLanguageUtil {
private static final Key<List<RangeMarker>> INJECTED_REGIONS_KEY = Key.create("INJECTED_REGIONS_KEY");
@NotNull
public static List<DocumentWindow> getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) {
// modification of cachedInjectedDocuments must be under PsiLock only
List<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
if (injected == null) {
injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createEmptyCOWList());
}
return injected;
}
public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
file.putUserData(INJECTED_DOCS_KEY, null);
}
public static void commitAllInjectedDocuments(Document hostDocument, Project project) {
List<RangeMarker> injected = getCachedInjectedRegions(hostDocument);
@@ -320,10 +324,32 @@ public class InjectedLanguageUtil {
PsiDocumentManagerImpl.checkConsistency(hostPsiFile, hostDocument);
}
public static void clearCaches(PsiFile injected) {
public static void clearCaches(@NotNull PsiFile injected, @NotNull DocumentWindowImpl documentWindow) {
VirtualFileWindow virtualFile = (VirtualFileWindow)injected.getVirtualFile();
PsiManagerEx psiManagerEx = (PsiManagerEx)injected.getManager();
if (psiManagerEx.isDisposed()) return;
psiManagerEx.getFileManager().setViewProvider((VirtualFile)virtualFile, null);
PsiElement context = injected.getContext();
PsiFile hostFile;
if (context != null) {
hostFile = context.getContainingFile();
}
else {
VirtualFile delegate = virtualFile.getDelegate();
hostFile = delegate.isValid() ? psiManagerEx.findFile(delegate) : null;
}
if (hostFile != null) {
// modification of cachedInjectedDocuments must be under PsiLock
synchronized (PsiLock.LOCK) {
List<DocumentWindow> cachedInjectedDocuments = getCachedInjectedDocuments(hostFile);
for (int i = cachedInjectedDocuments.size() - 1; i >= 0; i--) {
DocumentWindow cachedInjectedDocument = cachedInjectedDocuments.get(i);
if (cachedInjectedDocument == documentWindow) {
cachedInjectedDocuments.remove(i);
}
}
}
}
}
@@ -235,7 +235,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar {
PsiFile newFile = registerDocument(documentWindow, psiFile, place, myHostPsiFile, documentManager);
boolean mergeHappened = newFile != psiFile;
if (mergeHappened) {
InjectedLanguageUtil.clearCaches(psiFile);
InjectedLanguageUtil.clearCaches(psiFile, documentWindow);
psiFile = newFile;
viewProvider = (InjectedFileViewProvider)psiFile.getViewProvider();
documentWindow = (DocumentWindowImpl)viewProvider.getDocument();
@@ -35,13 +35,13 @@ import java.util.Iterator;
public class LazyRangeMarkerFactory extends AbstractProjectComponent {
private final WeakList<LazyMarker> myMarkers = new WeakList<LazyMarker>();
public LazyRangeMarkerFactory(Project project, final FileDocumentManager fdm) {
public LazyRangeMarkerFactory(Project project, final FileDocumentManager fileDocumentManager) {
super(project);
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
public void beforeDocumentChange(DocumentEvent e) {
for (Iterator<LazyMarker> it = myMarkers.iterator(); it.hasNext();) {
final LazyMarker marker = it.next();
final VirtualFile docFile = fdm.getFile(e.getDocument());
final VirtualFile docFile = fileDocumentManager.getFile(e.getDocument());
if (marker.getFile() == docFile) {
marker.ensureDelegate();
it.remove();
@@ -82,7 +82,7 @@ public class LazyRangeMarkerFactory extends AbstractProjectComponent {
return marker;
}
private static abstract class LazyMarker extends UserDataHolderBase implements RangeMarker{
private abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker{
private RangeMarker myDelegate = null;
private final VirtualFile myFile;
protected final int myInitialOffset;
@@ -203,6 +203,7 @@ public class ProgressIndicatorBase extends UserDataHolderBase implements Progres
public void processFinish() {
if (myOwnerTask != null) {
finish(myOwnerTask);
myOwnerTask = null;
}
}
@@ -93,7 +93,7 @@ public class FileWatcher {
myManagingFS = ManagingFS.getInstance();
try {
if (!"true".equals(System.getProperty(PROPERTY_WATCHER_DISABLED))) {
startupProcess();
startupProcess(false);
}
}
catch (IOException ignore) {
@@ -236,7 +236,7 @@ public class FileWatcher {
}
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
private void startupProcess() throws IOException {
private void startupProcess(final boolean restart) throws IOException {
if (isShuttingDown) return;
if (attemptCount++ > MAX_PROCESS_LAUNCH_ATTEMPT_COUNT) {
@@ -260,10 +260,22 @@ public class FileWatcher {
: PathManager.getBinPath() + File.separatorChar + executableName;
if (!new File(pathToExecutable).canExecute()) return;
LOG.info("Starting file watcher: " + pathToExecutable);
notifierProcess = Runtime.getRuntime().exec(new String[]{pathToExecutable});
notifierReader = new BufferedReader(new InputStreamReader(notifierProcess.getInputStream()));
notifierWriter = new BufferedWriter(new OutputStreamWriter(notifierProcess.getOutputStream()));
synchronized (LOCK) {
if (restart && myRecursiveWatchRoots.size() + myFlatWatchRoots.size() > 0) {
final List<String> recursiveWatchRoots = new ArrayList<String>(myRecursiveWatchRoots);
final List<String> flatWatchRoots = new ArrayList<String>(myFlatWatchRoots);
myRecursiveWatchRoots.clear();
myFlatWatchRoots.clear();
setWatchRoots(recursiveWatchRoots, flatWatchRoots);
}
}
}
private void shutdownProcess() {
@@ -301,7 +313,7 @@ public class FileWatcher {
final String command = readLine();
if (command == null) {
// Unexpected process exit, relaunch attempt
startupProcess();
startupProcess(true);
continue;
}
@@ -352,7 +364,7 @@ public class FileWatcher {
final String path = readLine();
if (path == null) {
// Unexpected process exit, relaunch attempt
startupProcess();
startupProcess(true);
continue;
}
@@ -323,8 +323,6 @@ public class UsageViewManagerImpl extends UsageViewManager {
if (usageView != null) {
usageView.appendUsageLater(usage);
}
if (usageCount % 100 == 0) System.out.println("usageCount = " + usageCount);
}
return indicator == null || !indicator.isCanceled();
}
@@ -57,7 +57,7 @@ public class ModuleGroupingRule implements UsageGroupingRule {
private static class LibraryUsageGroup implements UsageGroup {
public static final Icon LIBRARY_ICON = IconLoader.getIcon("/nodes/ppLibOpen.png");
OrderEntry myEntry;
private final OrderEntry myEntry;
public void update() {
}
@@ -18,7 +18,6 @@ package com.intellij.util;
import org.jetbrains.annotations.NonNls;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
public class EnvironmentUtil {
@@ -27,7 +26,8 @@ public class EnvironmentUtil {
private EnvironmentUtil() {
}
public static @NonNls Map<String, String> getEnviromentProperties() {
@NonNls
public static Map<String, String> getEnviromentProperties() {
return ourEnviromentProperties;
}
@@ -39,8 +39,8 @@ public class EnvironmentUtil {
Map enviroment = getEnviromentProperties();
String[] envp = new String[enviroment.size()];
int i = 0;
for (Iterator iterator = enviroment.keySet().iterator(); iterator.hasNext();) {
String name = (String)iterator.next();
for (Object o : enviroment.keySet()) {
String name = (String)o;
String value = (String)enviroment.get(name);
envp[i++] = name + "=" + value;
}
@@ -0,0 +1,26 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Sep 19, 2002
* Time: 3:27:12 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.util;
import com.intellij.util.EnvironmentUtil;
import com.intellij.openapi.util.SystemInfo;
import junit.framework.TestCase;
import java.util.Map;
public class EnvironmentUtilTest extends TestCase {
public void test1() {
Map enviromentProperties = EnvironmentUtil.getEnviromentProperties();
assertNotNull(enviromentProperties);
if(SystemInfo.isWindows)
assertNotNull(enviromentProperties.get("Path"));
else
assertNotNull(enviromentProperties.get("PATH"));
}
}
@@ -21,6 +21,9 @@ bigfile
bigint
binlog
bool
blog
blogger
blogging
btree
calc
callee