diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index d60883c52939..fc5d672873e1 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -302,7 +302,6 @@ def layoutFull(String home, String targetDirectory) { fileset(dir: "$home/plugins/groovy/resources/conf") - fileset(dir: "${home}/plugins/groovy/lib") } } diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java index 422378077c6d..ce8f7971d4f2 100644 --- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java +++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java @@ -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> myNotNullSet = - new HashSet>(); - private final HashSet> myNullableSet = - new HashSet>(); - private boolean myAnnotateLocalVariables; - private SmartPointerManager myPointerManager; + private final HashSet> myNotNullSet = new HashSet>(); + private final HashSet> myNullableSet = new HashSet>(); + 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() { diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java index f795a456d373..bccbd456a2ef 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java @@ -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; diff --git a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java index 915b95fe98af..d3597d29cf4b 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java @@ -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 { diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java index 363caf601ddf..c14dff95cc19 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java @@ -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) { diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java index 47f5c9e27cbe..d6eb064ae4bf 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -125,22 +125,21 @@ public class ExtensionPointImpl implements ExtensionPoint { 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 implements ExtensionPoint { result = myExtensionsCache; if (result == null) { processAdapters(); - List extensions = new ArrayList(myExtensions); - - List problemExtensions = new ArrayList(); - final Class extensionClass = getExtensionClass(); - for (Iterator 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; } } } diff --git a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java index c1666f866ab0..9460a5791b6b 100644 --- a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java @@ -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); diff --git a/platform/lang-api/src/com/intellij/psi/PsiManager.java b/platform/lang-api/src/com/intellij/psi/PsiManager.java index 0d68c4039e4c..2b15ca422656 100644 --- a/platform/lang-api/src/com/intellij/psi/PsiManager.java +++ b/platform/lang-api/src/com/intellij/psi/PsiManager.java @@ -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); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 095d0ab7fae2..731cc9c3faf9 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -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); + } } }); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index 9ce501903031..2e208934ee8c 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -373,6 +373,7 @@ public class RefManagerImpl extends RefManager { visitElement(viewProvider.getPsi(language)); } myPsiManager.dropResolveCaches(); + myPsiManager.dropFileCaches(file); } } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 914bc3ee467d..05fece7ba711 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -362,7 +362,7 @@ public class FindUsagesManager implements JDOMExternalizable { return processor.process(UsageInfoToUsageConverter.convert(descriptor, usageInfo)); } }); - List elements = + final List elements = ApplicationManager.getApplication().runReadAction(new Computable>() { public List 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() { + Project project = ApplicationManager.getApplication().runReadAction(new Computable() { + 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() { public boolean processInReadAction(final PsiReference ref) { TextRange rangeInElement = ref.getRangeInElement(); return usageInfoProcessor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 8d681e621ba4..9ddc24003f40 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -269,12 +269,7 @@ public class FindInProjectUtil { String message = ""; if (largeFiles.size() == 1) { final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile(); - message - += "File '" - + getPresentablePath(vFile) - + "' (" - + presentableSize(getFileLength(vFile)) - + ") is "; + message += "File " + presentableFileInfo(vFile) + " is "; } else { message += "Files
"; @@ -282,11 +277,7 @@ public class FindInProjectUtil { int counter = 0; for (PsiFile file : largeFiles) { final VirtualFile vFile = file.getVirtualFile(); - message += - getPresentablePath(vFile) - + " (" - + presentableSize(getFileLength(vFile)) - + ")
"; + message += presentableFileInfo(vFile) + "
"; if (counter++ > 10) break; } @@ -312,6 +303,13 @@ public class FindInProjectUtil { } } + private static String presentableFileInfo(VirtualFile vFile) { + return getPresentablePath(vFile) + + " (" + + presentableSize(getFileLength(vFile)) + + ")"; + } + private static int processUsagesInFile(final PsiFile psiFile, final FindModel findModel, final Processor consumer) { @@ -339,11 +337,11 @@ public class FindInProjectUtil { } private static String getPresentablePath(final VirtualFile virtualFile) { - return ApplicationManager.getApplication().runReadAction(new Computable() { + return "'" + ApplicationManager.getApplication().runReadAction(new Computable() { 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 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; diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java index 6b243e37e894..7759cb9fc15f 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java @@ -51,11 +51,15 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings { +public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable + implements LibraryTable.Listener, + Disposable { private final ScriptingLibraryMappings myScriptingLibraryMappings; private final LangScriptingContextConfigurable myParent; @@ -46,6 +52,8 @@ public class ScriptingContextsConfigurable extends LanguagePerFileConfigurablephysical or non-physical PSI change */ diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerImpl.java index 7d14cde8edea..5d15f66a5f82 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerImpl.java @@ -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 myTreeChangeListeners = ContainerUtil.createEmptyCOWList(); private boolean myTreeChangeEventIsFiring = false; - private final List myRunnablesOnChange = ContainerUtil.createEmptyCOWList(); - private final List> myWeakRunnablesOnChange = ContainerUtil.createEmptyCOWList(); - private final List myRunnablesOnAnyChange = ContainerUtil.createEmptyCOWList(); - private final List 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 CACHED_PSI_FILE_COPY_IN_FILECONTENT = Key.create("CACHED_PSI_FILE_COPY_IN_FILECONTENT"); + public static final Topic ANY_PSI_CHANGE_TOPIC = Topic.create("PSI_CHANGE_TOPIC",AnyPsiChangeListener.class, Topic.BroadcastDirection.TO_PARENT); private final List 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)); + 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 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 diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index b6290097e660..cbb3f482acce 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -288,12 +288,16 @@ public class InjectedLanguageUtil { private static final Key> INJECTED_REGIONS_KEY = Key.create("INJECTED_REGIONS_KEY"); @NotNull public static List getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) { + // modification of cachedInjectedDocuments must be under PsiLock only List injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY); if (injected == null) { injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.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 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 cachedInjectedDocuments = getCachedInjectedDocuments(hostFile); + for (int i = cachedInjectedDocuments.size() - 1; i >= 0; i--) { + DocumentWindow cachedInjectedDocument = cachedInjectedDocuments.get(i); + if (cachedInjectedDocument == documentWindow) { + cachedInjectedDocuments.remove(i); + } + } + } + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java index 88494a37acad..1af0f5b82ca5 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java @@ -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(); diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index 11968f74288a..ea7beabfed99 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -35,13 +35,13 @@ import java.util.Iterator; public class LazyRangeMarkerFactory extends AbstractProjectComponent { private final WeakList myMarkers = new WeakList(); - 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 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java index 948c5352a4b5..1e3e682e5154 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java @@ -203,6 +203,7 @@ public class ProgressIndicatorBase extends UserDataHolderBase implements Progres public void processFinish() { if (myOwnerTask != null) { finish(myOwnerTask); + myOwnerTask = null; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index ecec0eeb9d91..e92eac4c028e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -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 recursiveWatchRoots = new ArrayList(myRecursiveWatchRoots); + final List flatWatchRoots = new ArrayList(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; } diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java index efcfe5b3c918..1b04bb297082 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java @@ -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(); } diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/ModuleGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/ModuleGroupingRule.java index 0aec9f5bc2fc..0978ab0e03bb 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/ModuleGroupingRule.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/ModuleGroupingRule.java @@ -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() { } diff --git a/platform/util/src/com/intellij/util/EnvironmentUtil.java b/platform/util/src/com/intellij/util/EnvironmentUtil.java index 23a8e8bc7dd9..acbc58b580d4 100644 --- a/platform/util/src/com/intellij/util/EnvironmentUtil.java +++ b/platform/util/src/com/intellij/util/EnvironmentUtil.java @@ -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 getEnviromentProperties() { + @NonNls + public static Map 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; } diff --git a/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java new file mode 100644 index 000000000000..df8ee4893aab --- /dev/null +++ b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java @@ -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")); + } +} diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 8cf5d92150de..e1f27db01dae 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -21,6 +21,9 @@ bigfile bigint binlog bool +blog +blogger +blogging btree calc callee