Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2017-03-30 18:35:12 +02:00
494 changed files with 164972 additions and 458 deletions
-5
View File
@@ -63,7 +63,6 @@ fi
# ---------------------------------------------------------------------
if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then
JDK="$@@product_uc@@_JDK"
echo "@@product_uc@@_JDK: $@@product_uc@@_JDK"
fi
if [ -z "$JDK" ] || [ ! -x "$JDK/bin/java" ] &&
@@ -72,25 +71,21 @@ if [ -z "$JDK" ] || [ ! -x "$JDK/bin/java" ] &&
if [ ! -d "$JDK" ]; then
JDK="$IDE_HOME/$JDK"
fi
echo "boot jdk: $JDK"
fi
if [ -z "$JDK" ] || [ ! -x "$JDK/bin/java" ] &&
[ "$OS_TYPE" = "Linux" ] && [ -x "$IDE_HOME/jre64/bin/java" ] && "$IDE_HOME/jre64/bin/java" -version > /dev/null 2>&1 ; then
JDK="$IDE_HOME/jre64"
echo "bundled jre: $JDK"
fi
if [ -z "$JDK" ] || [ ! -x "$JDK/bin/java" ] &&
[ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then
JDK="$JDK_HOME"
echo "JDK_HOME: $JDK"
fi
if [ -z "$JDK" ] || [ ! -x "$JDK/bin/java" ]; then
if [ -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
JDK="$JAVA_HOME"
echo "JAVA_HOME: $JDK"
else
JAVA_BIN_PATH=`which java`
if [ -n "$JAVA_BIN_PATH" ]; then
@@ -111,7 +111,8 @@ public class AddAnnotationPsiFix extends LocalQuickFixOnPsiElement {
final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement;
// e.g. PsiTypeParameterImpl doesn't have modifier list
return myModifierListOwner.getModifierList() != null
return myModifierListOwner.isWritable() &&
myModifierListOwner.getModifierList() != null
&& !AnnotationUtil.isAnnotated(myModifierListOwner, myAnnotation, false, false);
}
@@ -237,7 +237,7 @@ public class MarkerType {
PsiMethod[] overridings = processor.toArray(PsiMethod.EMPTY_ARRAY);
if (overridings.length == 0) {
final PsiClass aClass = method.getContainingClass();
if (aClass != null && FunctionalExpressionSearch.search(aClass).findFirst() != null) {
if (aClass != null && isAbstract && FunctionalExpressionSearch.search(aClass).findFirst() != null) {
return "Has functional implementations";
}
return null;
@@ -462,17 +462,19 @@ public class MarkerType {
return super.process(psiMethod);
}
});
PsiClass psiClass = ReadAction.compute(myMethod::getContainingClass);
FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() {
@Override
public boolean process(final PsiFunctionalExpression expr) {
if (!updateComponent(expr, myRenderer.getComparator())) {
indicator.cancel();
if (myMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
PsiClass psiClass = ReadAction.compute(myMethod::getContainingClass);
FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() {
@Override
public boolean process(final PsiFunctionalExpression expr) {
if (!updateComponent(expr, myRenderer.getComparator())) {
indicator.cancel();
}
indicator.checkCanceled();
return super.process(expr);
}
indicator.checkCanceled();
return super.process(expr);
}
});
});
}
}
}
}
@@ -43,7 +43,7 @@ public class MissingIfBranchesFixer implements Fixer {
}
private static void handleBranch(@NotNull Document doc, @NotNull PsiIfStatement ifStatement, @NotNull PsiElement beforeBranch, @Nullable PsiStatement branch) {
if (branch instanceof PsiBlockStatement) return;
if (branch instanceof PsiBlockStatement || beforeBranch.textMatches(PsiKeyword.ELSE) && branch instanceof PsiIfStatement) return;
boolean transformingOneLiner = branch != null && (startLine(doc, beforeBranch) == startLine(doc, branch) ||
startCol(doc, ifStatement) < startCol(doc, branch));
@@ -0,0 +1,7 @@
class Foo {
{
if (a) <caret>
else if (elsecond) {
}
}
}
@@ -0,0 +1,8 @@
class Foo {
{
if (a) {
<caret>
} else if (elsecond) {
}
}
}
@@ -123,6 +123,8 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testElseIf() throws Exception { doTest(); }
public void testBlockBeforeElseIf() { doTest(); }
public void testIncompleteElseIf() throws Exception { doTest(); }
public void testField() throws Exception { doTest(); }
@@ -40,9 +40,9 @@ import static org.junit.Assert.fail;
* @author Tagir Valeev
*/
public class ActionHint {
final String myExpectedText;
final boolean myShouldPresent;
final ProblemHighlightType myHighlightType;
private final String myExpectedText;
private final boolean myShouldPresent;
private final ProblemHighlightType myHighlightType;
private ActionHint(String expectedText, boolean shouldPresent, ProblemHighlightType severity) {
myExpectedText = expectedText;
@@ -67,7 +67,7 @@ public class ActionHint {
* @return true if this ActionHint checks that some action should be present
* or false if it checks that some action should be absent
*/
public boolean shouldPresent() {
boolean shouldPresent() {
return myShouldPresent;
}
@@ -22,12 +22,11 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.CustomLoadingExtensionPointBean;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
import java.util.ResourceBundle;
public class IntentionActionBean extends CustomLoadingExtensionPointBean {
@@ -67,6 +66,7 @@ public class IntentionActionBean extends CustomLoadingExtensionPointBean {
return descriptionDirectoryName;
}
@NotNull
public IntentionAction instantiate() throws ClassNotFoundException {
return (IntentionAction)instantiateExtension(className, ApplicationManager.getApplication().getPicoContainer());
}
@@ -75,6 +75,11 @@ public class DelegatingGlobalSearchScope extends GlobalSearchScope {
return myBaseScope.getDisplayName();
}
@Override
public String toString() {
return getClass().getName() + "[" + myBaseScope + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -24,7 +24,6 @@ import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectCoreUtil;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -367,7 +366,7 @@ public class StubBasedPsiElementBase<T extends StubElement> extends ASTDelegateP
@NotNull
public IStubElementType getElementType() {
if (!(myElementType instanceof IStubElementType)) {
throw new AssertionError("Not a stub type: " + myElementType + " in " + getClass());
throw new ClassCastException("Not a stub type: " + myElementType + " in " + getClass());
}
return (IStubElementType)myElementType;
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.CachedValueProvider;
@@ -49,7 +50,9 @@ class CachedValueLeakChecker {
if (!DO_CHECKS || ApplicationInfoImpl.isInStressTest()) return;
if (!ourCheckedKeys.add(key.toString())) return; // store strings because keys are created afresh in each (test) project
findReferencedPsi(provider, userDataHolder, 5);
if (!SystemInfo.isJavaVersionAtLeast("9")) {
findReferencedPsi(provider, userDataHolder, 5);
}
}
private static synchronized void findReferencedPsi(@NotNull final Object root,
@@ -15,10 +15,10 @@
*/
package com.intellij.util;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -13,8 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package git4idea.branch;
package com.intellij.dvcs.branch;
public enum GitBranchType {
LOCAL, REMOTE
import org.jetbrains.annotations.NotNull;
public interface BranchType {
@NotNull
String getName();
}
@@ -0,0 +1,85 @@
/*
* Copyright 2000-2017 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.dvcs.branch;
import com.intellij.dvcs.repo.AbstractRepositoryManager;
import com.intellij.dvcs.repo.Repository;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.intellij.util.containers.ContainerUtil.map2List;
import static com.intellij.util.containers.ContainerUtil.newArrayList;
public abstract class DvcsBranchManager<T extends Repository> {
@NotNull private final AbstractRepositoryManager<T> myRepositoryManager;
@NotNull private final DvcsBranchSettings myBranchSettings;
@NotNull public final BranchStorage myPredefinedFavoriteBranches = new BranchStorage();
protected DvcsBranchManager(@NotNull AbstractRepositoryManager<T> repositoryManager,
@NotNull DvcsBranchSettings settings,
@NotNull BranchType[] branchTypes) {
myRepositoryManager = repositoryManager;
myBranchSettings = settings;
for (BranchType type : branchTypes) {
String defaultBranchName = getDefaultBranchName(type);
if (!StringUtil.isEmptyOrSpaces(defaultBranchName)) {
myPredefinedFavoriteBranches.myBranches.put(type.getName(), constructDefaultBranchPredefinedList(defaultBranchName));
}
}
}
@NotNull
private List<DvcsBranchInfo> constructDefaultBranchPredefinedList(@NotNull String defaultBranchName) {
List<DvcsBranchInfo> branchInfos = newArrayList(new DvcsBranchInfo("", defaultBranchName));
branchInfos.addAll(map2List(myRepositoryManager.getRepositories(),
repository -> new DvcsBranchInfo(repository.getRoot().getPath(), defaultBranchName)));
return branchInfos;
}
@Nullable
protected String getDefaultBranchName(@NotNull BranchType type) {return null;}
public boolean isFavorite(@Nullable BranchType branchType, @Nullable Repository repository, @NotNull String branchName) {
if (branchType == null) return false;
String branchTypeName = branchType.getName();
if (myBranchSettings.getFavorites().contains(branchTypeName, repository, branchName)) return true;
if (myBranchSettings.getExcludedFavorites().contains(branchTypeName, repository, branchName)) return false;
return myPredefinedFavoriteBranches.contains(branchTypeName, repository, branchName);
}
public void setFavorite(@Nullable BranchType branchType,
@Nullable Repository repository,
@NotNull String branchName,
boolean shouldBeFavorite) {
if (branchType == null) return;
String branchTypeName = branchType.getName();
if (shouldBeFavorite) {
myBranchSettings.getFavorites().add(branchTypeName, repository, branchName);
myBranchSettings.getExcludedFavorites().remove(branchTypeName, repository, branchName);
}
else {
if (myBranchSettings.getFavorites().contains(branchTypeName, repository, branchName)) {
myBranchSettings.getFavorites().remove(branchTypeName, repository, branchName);
}
else if (myPredefinedFavoriteBranches.contains(branchTypeName, repository, branchName)) {
myBranchSettings.getExcludedFavorites().add(branchTypeName, repository, branchName);
}
}
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2017 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.dvcs.branch;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
public class DvcsBranchSettings {
@Tag("favorite-branches")
private BranchStorage myFavoriteBranches = new BranchStorage();
@Tag("excluded-from-favorite")
private BranchStorage myExcludedFavorites = new BranchStorage();
@NotNull
public BranchStorage getFavorites() {
return myFavoriteBranches;
}
@NotNull
public BranchStorage getExcludedFavorites() {
return myExcludedFavorites;
}
}
@@ -51,7 +51,7 @@ public class PsiSearchRequest {
this.caseSensitive = caseSensitive;
this.processor = processor;
if (searchScope instanceof GlobalSearchScope && ((GlobalSearchScope)searchScope).getProject() == null) {
throw new AssertionError("Every search scope must be associated with a project");
throw new AssertionError("Every search scope must be associated with a project: " + searchScope);
}
}
@@ -18,11 +18,14 @@ package com.intellij.application.options.codeStyle;
import com.intellij.application.options.CodeStyleAbstractPanel;
import com.intellij.application.options.TabbedLanguageCodeStylePanel;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.ex.Settings;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.codeStyle.CodeStyleSchemes;
import com.intellij.ui.components.labels.SwingActionLink;
@@ -103,7 +106,12 @@ public class CodeStyleMainPanel extends JPanel implements TabbedLanguageCodeStyl
@Override
public void afterCurrentSettingsChanged() {
mySchemesPanel.updateOnCurrentSettingsChange();
mySchemesPanel.updateOnCurrentSettingsChange();
DataContext context = DataManager.getInstance().getDataContext(mySettingsPanel);
Settings settings = Settings.KEY.getData(context);
if (settings != null) {
settings.revalidate();
}
}
@Override
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.ReferenceImporter;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.HintAction;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
@@ -80,7 +81,9 @@ public class ShowAutoImportPass extends TextEditorHighlightingPass {
Application application = ApplicationManager.getApplication();
application.assertIsDispatchThread();
if (!application.isUnitTestMode() && !myEditor.getContentComponent().hasFocus()) return;
if (DumbService.isDumb(myProject)) return;
if (DumbService.isDumb(myProject) || !myFile.isValid()) return;
if (myEditor.isDisposed() || myEditor instanceof EditorWindow && !((EditorWindow)myEditor).isValid()) return;
int caretOffset = myEditor.getCaretModel().getOffset();
importUnambiguousImports(caretOffset);
List<HighlightInfo> visibleHighlights = getVisibleHighlights(myStartOffset, myEndOffset, myProject, myEditor);
@@ -66,8 +66,6 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
@@ -142,12 +140,12 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
}
@NotNull
public static IntentionHintComponent showIntentionHint(@NotNull final Project project,
@NotNull PsiFile file,
@NotNull final Editor editor,
@NotNull ShowIntentionsPass.IntentionsInfo intentions,
boolean showExpanded,
@NotNull Point position) {
private static IntentionHintComponent showIntentionHint(@NotNull final Project project,
@NotNull PsiFile file,
@NotNull final Editor editor,
@NotNull ShowIntentionsPass.IntentionsInfo intentions,
boolean showExpanded,
@NotNull Point position) {
ApplicationManager.getApplication().assertIsDispatchThread();
final IntentionHintComponent component = new IntentionHintComponent(project, file, editor, intentions);
@@ -466,31 +464,28 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
myPopupShown = false;
}
});
myPopup.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(@NotNull ListSelectionEvent e) {
final Object source = e.getSource();
highlighter.dropHighlight();
injectionHighlighter.dropHighlight();
if (source instanceof DataProvider) {
final Object selectedItem = PlatformDataKeys.SELECTED_ITEM.getData((DataProvider)source);
if (selectedItem instanceof IntentionActionWithTextCaching) {
final IntentionAction action = ((IntentionActionWithTextCaching)selectedItem).getAction();
if (action instanceof SuppressIntentionActionFromFix) {
if (injectedFile != null && ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost() == ThreeState.NO) {
final PsiElement at = injectedFile.findElementAt(injectedEditor.getCaretModel().getOffset());
final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
if (container != null) {
injectionHighlighter.highlight(container, Collections.singletonList(container));
}
myPopup.addListSelectionListener(e -> {
final Object source = e.getSource();
highlighter.dropHighlight();
injectionHighlighter.dropHighlight();
if (source instanceof DataProvider) {
final Object selectedItem = PlatformDataKeys.SELECTED_ITEM.getData((DataProvider)source);
if (selectedItem instanceof IntentionActionWithTextCaching) {
final IntentionAction action = ((IntentionActionWithTextCaching)selectedItem).getAction();
if (action instanceof SuppressIntentionActionFromFix) {
if (injectedFile != null && ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost() == ThreeState.NO) {
final PsiElement at = injectedFile.findElementAt(injectedEditor.getCaretModel().getOffset());
final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
if (container != null) {
injectionHighlighter.highlight(container, Collections.singletonList(container));
}
else {
final PsiElement at = myFile.findElementAt(myEditor.getCaretModel().getOffset());
final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
if (container != null) {
highlighter.highlight(container, Collections.singletonList(container));
}
}
else {
final PsiElement at = myFile.findElementAt(myEditor.getCaretModel().getOffset());
final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
if (container != null) {
highlighter.highlight(container, Collections.singletonList(container));
}
}
}
@@ -515,12 +510,7 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
}
Disposer.register(this, myPopup);
Disposer.register(myPopup, new Disposable() {
@Override
public void dispose() {
ApplicationManager.getApplication().assertIsDispatchThread();
}
});
Disposer.register(myPopup, ApplicationManager.getApplication()::assertIsDispatchThread);
}
void canceled(@NotNull ListPopupStep intentionListStep) {
@@ -592,9 +582,7 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
@Override
@NotNull
public String getText() {
return mySettings.isEnabled(myAction) ?
CodeInsightBundle.message("disable.intention.action", myFamilyName) :
CodeInsightBundle.message("enable.intention.action", myFamilyName);
return CodeInsightBundle.message(mySettings.isEnabled(myAction) ? "disable.intention.action" : "enable.intention.action", myFamilyName);
}
@Override
@@ -100,12 +100,12 @@ public class IntentionListStep implements ListPopupStep<IntentionActionWithTextC
}
//true if something changed
boolean wrapAndUpdateActions(@NotNull ShowIntentionsPass.IntentionsInfo intentions, boolean callUpdate) {
boolean changed = wrapActionsTo(intentions.errorFixesToShow, myCachedErrorFixes, callUpdate);
changed |= wrapActionsTo(intentions.inspectionFixesToShow, myCachedInspectionFixes, callUpdate);
changed |= wrapActionsTo(intentions.intentionsToShow, myCachedIntentions, callUpdate);
changed |= wrapActionsTo(intentions.guttersToShow, myCachedGutters, callUpdate);
changed |= wrapActionsTo(intentions.notificationActionsToShow, myCachedNotifications, callUpdate);
boolean wrapAndUpdateActions(@NotNull ShowIntentionsPass.IntentionsInfo newInfo, boolean callUpdate) {
boolean changed = wrapActionsTo(newInfo.errorFixesToShow, myCachedErrorFixes, callUpdate);
changed |= wrapActionsTo(newInfo.inspectionFixesToShow, myCachedInspectionFixes, callUpdate);
changed |= wrapActionsTo(newInfo.intentionsToShow, myCachedIntentions, callUpdate);
changed |= wrapActionsTo(newInfo.guttersToShow, myCachedGutters, callUpdate);
changed |= wrapActionsTo(newInfo.notificationActionsToShow, myCachedNotifications, callUpdate);
return changed;
}
@@ -254,7 +254,7 @@ public class IntentionListStep implements ListPopupStep<IntentionActionWithTextC
return myFinalRunnable;
}
private void applyAction(final IntentionActionWithTextCaching cachedAction) {
private void applyAction(@NotNull IntentionActionWithTextCaching cachedAction) {
myFinalRunnable = () -> {
HintManager.getInstance().hideAllHints();
if (myProject.isDisposed() || myEditor != null && myEditor.isDisposed()) return;
@@ -27,6 +27,7 @@ import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -303,8 +304,9 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L
else {
try {
final BufferedReader reader = readerThread.myReader;
while (reader != null && reader.ready()) {
addMessage(reader.readLine());
while (reader.ready()) {
//ensure have read lock before requiring for sync, otherwise dispose() under write action would lead to deadlock
ReadAction.run(() -> addMessage(reader.readLine()));
}
}
catch (IOException ignore) {}
@@ -314,6 +316,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L
}
protected synchronized void addMessage(final String text) {
if (myDisposed) return;
if (text == null) return;
if (myContentPreprocessor != null) {
final List<LogFragment> fragments = myContentPreprocessor.parseLogLine(text + "\n");
@@ -51,6 +51,7 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.List;
import static com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
@@ -108,8 +109,7 @@ class DiffPreviewPanel implements PreviewPanel {
private final List<DiffContent> myContents;
public SampleRequest() {
com.intellij.openapi.diff.DiffContent[] contents = DiffPreviewProvider.getContents();
myContents = ContainerUtil.list(convert(contents[0]), convert(contents[1]), convert(contents[2]));
myContents = Arrays.asList(DiffPreviewProvider.getContents());
}
private static DiffContent convert(@NotNull com.intellij.openapi.diff.DiffContent content) {
@@ -16,12 +16,14 @@
package com.intellij.openapi.diff.impl.settings;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.SimpleContent;
import com.intellij.diff.DiffContentFactory;
import com.intellij.diff.contents.DiffContent;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* @author oleg
@@ -30,19 +32,33 @@ import org.jetbrains.annotations.NonNls;
public abstract class DiffPreviewProvider {
public static final ExtensionPointName<DiffPreviewProvider> EP_NAME = ExtensionPointName.create("com.intellij.diffPreviewProvider");
@NotNull
public abstract DiffContent[] createContents();
@NotNull
public static DiffContent[] getContents() {
// Assuming that standalone IDE should provide one provider
final DiffPreviewProvider[] providers = Extensions.getExtensions(EP_NAME);
if (providers.length != 0){
if (providers.length != 0) {
return providers[0].createContents();
}
return new DiffContent[]{createContent(LEFT_TEXT), createContent(CENTER_TEXT), createContent(RIGHT_TEXT)};
return createContent(LEFT_TEXT, CENTER_TEXT, RIGHT_TEXT, StdFileTypes.JAVA);
}
private static SimpleContent createContent(String text) {
return new SimpleContent(text, StdFileTypes.JAVA);
@NotNull
public static DiffContent[] createContent(@NotNull String left,
@NotNull String center,
@NotNull String right,
@NotNull FileType fileType) {
return new DiffContent[]{
createContent(left, StdFileTypes.JAVA),
createContent(center, StdFileTypes.JAVA),
createContent(right, StdFileTypes.JAVA)};
}
@NotNull
private static DiffContent createContent(@NotNull String text, @NotNull FileType fileType) {
return DiffContentFactory.getInstance().create(text, fileType);
}
@NonNls private static final String LEFT_TEXT = "class MyClass {\n" +
@@ -69,4 +69,9 @@ public abstract class Settings {
private static Configurable choose(Configurable configurable, Configurable variant) {
return variant != null ? variant : configurable;
}
/**
* Used to handle programmatic settings changes when no UI events are sent.
*/
public void revalidate() {}
}
@@ -187,7 +187,7 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
}
}
private void requestUpdate() {
void requestUpdate() {
final Configurable configurable = myConfigurable;
myQueue.queue(new Update(this) {
@Override
@@ -76,6 +76,11 @@ final class SettingsEditor extends AbstractEditor implements DataProvider {
myFilter.update(null, false, true);
return myTreeView.select(configurable);
}
@Override
public void revalidate() {
myEditor.requestUpdate();
}
};
mySearch = new SettingsSearch() {
@Override
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
class abc {
public void f() {
<<<<<<< abc.txt
def
=======
abc
>>>>>>> 1.14
int F() {
asdfklasdfl
asdgfsagdfhasfdhg
sdafjklklas
sdafjkllksadf
}
}
@@ -0,0 +1,3 @@
One
Two
Three
@@ -0,0 +1,6 @@
--- after/1.txt after
+++ after/1.txt after
@@ -0,0 +1,3 @@
+One
+Two
+Three
@@ -0,0 +1,3 @@
One
Two
Three
@@ -0,0 +1,8 @@
--- after/1.txt after
+++ after/1.txt after
@@ -0,0 +1,3 @@
+One
+Two
+Three
--
1.7.9.5
@@ -0,0 +1,7 @@
--- after/1.txt after
+++ after/1.txt after
@@ -0,0 +1,3 @@
+One
+Two
+Three
\ No newline at end of file
@@ -0,0 +1,3 @@
first
third
last
@@ -0,0 +1,6 @@
--- before/1.txt before
+++ after/1.txt after
@@ -1,2 +1,3 @@
first
third
+last
@@ -0,0 +1,2 @@
first
third
@@ -0,0 +1,3 @@
first
second
third
@@ -0,0 +1,6 @@
--- before/1.txt before
+++ after/1.txt after
@@ -1,2 +1,3 @@
first
+second
third
@@ -0,0 +1,2 @@
first
third
@@ -0,0 +1,7 @@
uno
dos
cuatro
cinco
seis
siete
ocho
@@ -0,0 +1,13 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Tue Nov 21 14:20:19 2006
+++ after/1.txt Tue Nov 21 14:20:15 2006
@@ -1,7 +1,7 @@
uno
dos
-tres
cuatro
+cinco
seis
siete
-octo
+ocho
@@ -0,0 +1,7 @@
uno
dos
cuatro
cinco
seis
siete
ocho
@@ -0,0 +1,6 @@
one
two
three
cuatro
five
seven
@@ -0,0 +1,18 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Fri Nov 17 16:41:09 2006
--- after/1.txt Fri Nov 17 16:40:58 2006
***************
*** 1,6 ****
one
three
! four
five
- six
seven
--- 1,6 ----
one
+ two
three
! cuatro
five
seven
@@ -0,0 +1,6 @@
one
three
four
five
six
seven
@@ -0,0 +1,7 @@
first
second
third
fourth
fifth
sixth
seventh
@@ -0,0 +1,13 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Fri Nov 17 15:30:30 2006
--- after/1.txt Fri Nov 17 15:30:38 2006
***************
*** 1,6 ****
--- 1,7 ----
first
second
third
+ fourth
fifth
sixth
seventh
@@ -0,0 +1,6 @@
first
second
third
fifth
sixth
seventh
@@ -0,0 +1,3 @@
first
second
third
@@ -0,0 +1,3 @@
uno
dos
tres
@@ -0,0 +1,19 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Tue Nov 07 13:32:58 2006
--- after/1.txt Tue Nov 07 13:32:58 2006
***************
*** 1,2 ****
--- 1,3 ----
first
+ second
third
diff -r -c before/2.txt after/2.txt
*** before/2.txt Fri Nov 17 18:26:49 2006
--- after/2.txt Fri Nov 17 18:26:38 2006
***************
*** 1,4 ****
uno
dos
tres
- cuatro
--- 1,3 ----
@@ -0,0 +1,2 @@
first
third
@@ -0,0 +1,4 @@
uno
dos
tres
cuatro
@@ -0,0 +1,6 @@
first
second
third
fifth
sixth
seventh
@@ -0,0 +1,13 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Fri Nov 17 16:29:29 2006
--- after/1.txt Fri Nov 17 16:29:26 2006
***************
*** 1,7 ****
first
second
third
- fourth
fifth
sixth
seventh
--- 1,6 ----
@@ -0,0 +1,7 @@
first
second
third
fourth
fifth
sixth
seventh
@@ -0,0 +1,11 @@
uno
dos
tres
cuatro
cinco
@@ -0,0 +1,13 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Tue Nov 21 18:10:18 2006
--- after/1.txt Tue Nov 21 18:10:26 2006
***************
*** 2,7 ****
--- 2,8 ----
dos
+ tres
cuatro
@@ -0,0 +1,10 @@
uno
dos
cuatro
cinco
@@ -0,0 +1,3 @@
uno
dos
tres
@@ -0,0 +1,13 @@
diff -r -c before/1.txt after/1.txt
*** before/1.txt Fri Nov 24 13:06:16 2006
--- after/1.txt Fri Nov 24 13:06:20 2006
***************
*** 1,2 ****
uno
! dos
\ No newline at end of file
--- 1,3 ----
uno
! dos
! tres
\ No newline at end of file
@@ -0,0 +1,15 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
@@ -0,0 +1,13 @@
diff --git a/before/1.txt b/after/1.txt
index fad3998..5880be4 100644
--- a/before/1.txt
+++ b/after/1.txt
@@ -12,5 +12,4 @@ class Test {
};
}
- void b(Supplier s) {}
-}
\ No newline at end of file
+ void b(Supplier s) {}
\ No newline at end of file
@@ -0,0 +1,16 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
}
@@ -0,0 +1,15 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
@@ -0,0 +1,10 @@
diff --git a/before/1.txt b/after/1.txt
index fad3998..5880be4 100644
--- a/before/1.txt
+++ b/after/1.txt
@@ -13,4 +13,3 @@
}
void b(Supplier s) {}
-}
\ No newline at end of file
@@ -0,0 +1,16 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
}
@@ -0,0 +1,16 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
}
@@ -0,0 +1,12 @@
diff --git a/before/1.txt b/after/1.txt
index fad3998..5880be4 100644
--- a/before/1.txt
+++ b/after/1.txt
@@ -12,5 +12,5 @@
};
}
- void b(Supplier s) {}
+
}
\ No newline at end of file
@@ -0,0 +1,16 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
}
@@ -0,0 +1,9 @@
uno
dos
tres
cuarto
cinco
seis
@@ -0,0 +1,11 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Mon Nov 20 14:37:58 2006
+++ after/1.txt Mon Nov 20 14:38:07 2006
@@ -3,6 +3,7 @@
dos
tres
+cuarto
cinco
seis
@@ -0,0 +1,8 @@
uno
dos
tres
cinco
seis
@@ -0,0 +1,262 @@
package com.intellij.psi.impl.source.resolve;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.reference.SoftReference;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
public class ResolveCache {
private static final Key<MapPair<PsiPolyVariantReference, Reference<ResolveResult[]>>> JAVA_RESOLVE_MAP = Key.create("ResolveCache.JAVA_RESOLVE_MAP");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP = Key.create("ResolveCache.RESOLVE_MAP");
private static final Key<MapPair<PsiPolyVariantReference, Reference<ResolveResult[]>>> JAVA_RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.JAVA_RESOLVE_MAP_INCOMPLETE");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.RESOLVE_MAP_INCOMPLETE");
private static final Key<List<Thread>> IS_BEING_RESOLVED_KEY = Key.create("ResolveCache.IS_BEING_RESOLVED_KEY");
private static final Key<MapPair<PsiVariable, Object>> VAR_TO_CONST_VALUE_MAP_KEY = Key.create("ResolveCache.VAR_TO_CONST_VALUE_MAP_KEY");
//store types for method call expressions, NB: this caching is semantical, without this captured wildcards won't work
private final ConcurrentWeakHashMap<PsiExpression, WeakReference<PsiType>> myCaclulatedlTypes = new ConcurrentWeakHashMap<PsiExpression, WeakReference<PsiType>>();
private static final Object NULL = Key.create("NULL");
private final PsiManagerImpl myManager;
private final Map<PsiVariable,Object> myVarToConstValueMap1;
private final Map<PsiVariable,Object> myVarToConstValueMap2;
private final Map<PsiPolyVariantReference,Reference<ResolveResult[]>>[] myPolyVariantResolveMaps = new Map[4];
private final Map<PsiReference,Reference<PsiElement>>[] myResolveMaps = new Map[4];
private final AtomicInteger myClearCount = new AtomicInteger(0);
public static interface AbstractResolver<Ref,Result> {
Result resolve(Ref ref, boolean incompleteCode);
}
public static interface PolyVariantResolver extends AbstractResolver<PsiPolyVariantReference,ResolveResult[]> {
}
public static interface Resolver extends AbstractResolver<PsiReference,PsiElement>{
}
public ResolveCache(PsiManagerImpl manager) {
myManager = manager;
myVarToConstValueMap1 = getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, true);
myVarToConstValueMap2 = getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, false);
myPolyVariantResolveMaps[0] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true);
myPolyVariantResolveMaps[1] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true);
myResolveMaps[0] = getOrCreateWeakMap(myManager, RESOLVE_MAP, true);
myResolveMaps[1] = getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true);
myPolyVariantResolveMaps[2] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false);
myPolyVariantResolveMaps[3] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false);
myResolveMaps[2] = getOrCreateWeakMap(myManager, RESOLVE_MAP, false);
myResolveMaps[3] = getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false);
myManager.registerRunnableToRunOnAnyChange(new Runnable() {
public void run() {
myCaclulatedlTypes.clear();
}
});
}
public PsiType getType(PsiExpression expr, Function<PsiExpression, PsiType> f) {
WeakReference<PsiType> ref = myCaclulatedlTypes.get(expr);
PsiType type = ref == null ? null : ref.get();
if (type == null) {
type = f.fun(expr);
WeakReference<PsiType> existingRef = ConcurrencyUtil.cacheOrGet(myCaclulatedlTypes, expr, new WeakReference<PsiType>(type));
PsiType existing = existingRef.get();
if (existing != null) type = existing;
}
assert type == null || type.isValid();
return type;
}
public void clearCache() {
myClearCount.incrementAndGet();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP, true).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP, false).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false).clear();
}
private <Ref extends PsiReference, Result> Result resolve(Ref ref,
AbstractResolver<Ref, Result> resolver,
Map<Ref,Reference<Result>>[] maps,
boolean needToPreventRecursion,
boolean incompleteCode) {
ProgressManager.getInstance().checkCanceled();
int clearCountOnStart = myClearCount.intValue();
boolean physical = ref.getElement().isPhysical();
Result result = getCached(ref, maps, physical, incompleteCode);
if (result != null) {
return result;
}
if (incompleteCode) {
result = resolve(ref, resolver, maps, needToPreventRecursion, false);
if (result != null && !(result instanceof Object[] && ((Object[])result).length == 0)) {
cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
return result;
}
}
if (needToPreventRecursion && !lockElement(ref)) return null;
try {
result = resolver.resolve(ref, incompleteCode);
}
finally {
if (needToPreventRecursion) {
unlockElement(ref);
}
}
cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
return result;
}
public ResolveResult[] resolveWithCaching(PsiPolyVariantReference ref,
PolyVariantResolver resolver,
boolean needToPreventRecursion,
boolean incompleteCode) {
ResolveResult[] result = resolve(ref, resolver, myPolyVariantResolveMaps, needToPreventRecursion, incompleteCode);
return result == null ? JavaResolveResult.EMPTY_ARRAY : result;
}
public PsiElement resolveWithCaching(PsiReference ref,
Resolver resolver,
boolean needToPreventRecursion,
boolean incompleteCode) {
return resolve(ref, resolver, myResolveMaps, needToPreventRecursion, incompleteCode);
}
private static boolean lockElement(PsiReference ref) {
synchronized (IS_BEING_RESOLVED_KEY) {
PsiElement elt = ref.getElement();
List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
final Thread currentThread = Thread.currentThread();
if (lockingThreads == null) {
lockingThreads = new ArrayList<Thread>(1);
elt.putUserData(IS_BEING_RESOLVED_KEY, lockingThreads);
}
else {
if (lockingThreads.contains(currentThread)) return false;
}
lockingThreads.add(currentThread);
}
return true;
}
private static void unlockElement(PsiReference ref) {
synchronized (IS_BEING_RESOLVED_KEY) {
PsiElement elt = ref.getElement();
List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
if (lockingThreads == null) return;
final Thread currentThread = Thread.currentThread();
lockingThreads.remove(currentThread);
if (lockingThreads.isEmpty()) {
elt.putUserData(IS_BEING_RESOLVED_KEY, null);
}
}
}
//for Visual Fabrique
public void clearResolveCaches(PsiReference ref) {
myClearCount.incrementAndGet();
final boolean physical = ref.getElement().isPhysical();
if (ref instanceof PsiPolyVariantReference) {
cache((PsiPolyVariantReference)ref, null, myPolyVariantResolveMaps, physical, false, myClearCount.intValue());
cache((PsiPolyVariantReference)ref, null, myPolyVariantResolveMaps, physical, true, myClearCount.intValue());
}
}
private static int getIndex(boolean physical, boolean ic){
return (physical ? 0 : 1) << 1 | (ic ? 1 : 0);
}
private static <Ref,Result>Result getCached(Ref ref, Map<Ref,Reference<Result>>[] maps, boolean physical, boolean ic){
int index = getIndex(physical, ic);
Reference<Result> reference = maps[index].get(ref);
if(reference == null) return null;
return reference.get();
}
private <Ref,Result> void cache(Ref ref, Result result, Map<Ref,Reference<Result>>[] maps, boolean physical, boolean incompleteCode, final int clearCountOnStart) {
if (clearCountOnStart != myClearCount.intValue() && result != null) return;
int index = getIndex(physical, incompleteCode);
maps[index].put(ref, new SoftReference<Result>(result));
}
public static interface ConstValueComputer{
Object execute(PsiVariable variable, Set<PsiVariable> visitedVars);
}
public Object computeConstantValueWithCaching(PsiVariable variable, ConstValueComputer computer, Set<PsiVariable> visitedVars){
boolean physical = variable.isPhysical();
Object cached = (physical ? myVarToConstValueMap1 : myVarToConstValueMap2).get(variable);
if (cached == NULL) return null;
if (cached != null) return cached;
Object result = computer.execute(variable, visitedVars);
(physical ? myVarToConstValueMap1 : myVarToConstValueMap2).put(variable, result != null ? result : NULL);
return result;
}
public <K,V> ConcurrentMap<K,V> getOrCreateWeakMap(final PsiManagerImpl manager, final Key<MapPair<K, V>> key, boolean forPhysical) {
MapPair<K, V> pair = manager.getUserData(key);
if (pair == null){
pair = new MapPair<K,V>();
pair = manager.putUserDataIfAbsent(key, pair);
final MapPair<K, V> _pair = pair;
manager.registerRunnableToRunOnChange(
new Runnable() {
public void run() {
myClearCount.incrementAndGet();
_pair.physicalMap.clear();
}
}
);
manager.registerRunnableToRunOnAnyChange(
new Runnable() {
public void run() {
myClearCount.incrementAndGet();
_pair.nonPhysicalMap.clear();
}
}
);
}
return forPhysical ? pair.physicalMap : pair.nonPhysicalMap;
}
public static class MapPair<K,V>{
public final ConcurrentMap<K,V> physicalMap = new ConcurrentWeakHashMap<K, V>();
public final ConcurrentMap<K,V> nonPhysicalMap = new ConcurrentWeakHashMap<K, V>();
}
}
@@ -0,0 +1,430 @@
--- before/ResolveCache.java (revision 1)
+++ after/ResolveCache.java Thu Feb 01 20:27:02 MSK 2007
@@ -5,23 +5,29 @@
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.reference.SoftReference;
+import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
-import com.intellij.util.containers.WeakHashMap;
+import com.intellij.util.containers.ConcurrentWeakHashMap;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
public class ResolveCache {
- private static final Key<MapPair<PsiReference, SoftReference<ResolveResult[]>>> JAVA_RESOLVE_MAP = Key.create("ResolveCache.JAVA_RESOLVE_MAP");
+ private static final Key<MapPair<PsiPolyVariantReference, Reference<ResolveResult[]>>> JAVA_RESOLVE_MAP = Key.create("ResolveCache.JAVA_RESOLVE_MAP");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP = Key.create("ResolveCache.RESOLVE_MAP");
- private static final Key<MapPair<PsiReference, SoftReference<ResolveResult[]>>> JAVA_RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.JAVA_RESOLVE_MAP_INCOMPLETE");
+ private static final Key<MapPair<PsiPolyVariantReference, Reference<ResolveResult[]>>> JAVA_RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.JAVA_RESOLVE_MAP_INCOMPLETE");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.RESOLVE_MAP_INCOMPLETE");
private static final Key<List<Thread>> IS_BEING_RESOLVED_KEY = Key.create("ResolveCache.IS_BEING_RESOLVED_KEY");
private static final Key<MapPair<PsiVariable, Object>> VAR_TO_CONST_VALUE_MAP_KEY = Key.create("ResolveCache.VAR_TO_CONST_VALUE_MAP_KEY");
//store types for method call expressions, NB: this caching is semantical, without this captured wildcards won't work
- private Map<PsiExpression, WeakReference<PsiType>> myCaclulatedlTypes;
+ private final ConcurrentWeakHashMap<PsiExpression, WeakReference<PsiType>> myCaclulatedlTypes = new ConcurrentWeakHashMap<PsiExpression, WeakReference<PsiType>>();
private static final Object NULL = Key.create("NULL");
@@ -30,24 +36,25 @@
private final Map<PsiVariable,Object> myVarToConstValueMap1;
private final Map<PsiVariable,Object> myVarToConstValueMap2;
- private final WeakHashMap[] myPolyVariantResolveMaps = new WeakHashMap[4];
- private final WeakHashMap[] myResolveMaps = new WeakHashMap[4];
- private int myClearCount = 0;
+ private final Map<PsiPolyVariantReference,Reference<ResolveResult[]>>[] myPolyVariantResolveMaps = new Map[4];
+ private final Map<PsiReference,Reference<PsiElement>>[] myResolveMaps = new Map[4];
+ private final AtomicInteger myClearCount = new AtomicInteger(0);
- public static interface PolyVariantResolver {
- ResolveResult[] resolve(PsiPolyVariantReference ref, boolean incompleteCode);
+ public static interface AbstractResolver<Ref,Result> {
+ Result resolve(Ref ref, boolean incompleteCode);
}
+ public static interface PolyVariantResolver extends AbstractResolver<PsiPolyVariantReference,ResolveResult[]> {
+ }
- public static interface Resolver{
- PsiElement resolve(PsiReference ref, boolean incompleteCode);
+ public static interface Resolver extends AbstractResolver<PsiReference,PsiElement>{
}
public ResolveCache(PsiManagerImpl manager) {
myManager = manager;
- myVarToConstValueMap1 = Collections.synchronizedMap(getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, true));
- myVarToConstValueMap2 = Collections.synchronizedMap(getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, false));
+ myVarToConstValueMap1 = getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, true);
+ myVarToConstValueMap2 = getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, false);
myPolyVariantResolveMaps[0] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true);
myPolyVariantResolveMaps[1] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true);
@@ -60,200 +67,147 @@
myResolveMaps[2] = getOrCreateWeakMap(myManager, RESOLVE_MAP, false);
myResolveMaps[3] = getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false);
- myCaclulatedlTypes = new WeakHashMap<PsiExpression, WeakReference<PsiType>>();
myManager.registerRunnableToRunOnAnyChange(new Runnable() {
public void run() {
- synchronized (PsiLock.LOCK) {
- myCaclulatedlTypes.clear();
- }
+ myCaclulatedlTypes.clear();
+ }
- }
});
}
public PsiType getType(PsiExpression expr, Function<PsiExpression, PsiType> f) {
- WeakReference<PsiType> ref;
- synchronized (PsiLock.LOCK) {
- ref = myCaclulatedlTypes.get(expr);
- }
+ WeakReference<PsiType> ref = myCaclulatedlTypes.get(expr);
PsiType type = ref == null ? null : ref.get();
if (type == null) {
type = f.fun(expr);
- synchronized (PsiLock.LOCK) {
- myCaclulatedlTypes.put(expr, new WeakReference<PsiType>(type));
+ WeakReference<PsiType> existingRef = ConcurrencyUtil.cacheOrGet(myCaclulatedlTypes, expr, new WeakReference<PsiType>(type));
+ PsiType existing = existingRef.get();
+ if (existing != null) type = existing;
- }
+ }
- }
-
+ assert type == null || type.isValid();
return type;
}
public void clearCache() {
- synchronized (PsiLock.LOCK) {
- myClearCount++;
+ myClearCount.incrementAndGet();
- getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true).clear();
- getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true).clear();
- getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false).clear();
- getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false).clear();
- getOrCreateWeakMap(myManager, RESOLVE_MAP, true).clear();
- getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true).clear();
- getOrCreateWeakMap(myManager, RESOLVE_MAP, false).clear();
- getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false).clear();
- }
+ getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true).clear();
+ getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true).clear();
+ getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false).clear();
+ getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false).clear();
+ getOrCreateWeakMap(myManager, RESOLVE_MAP, true).clear();
+ getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true).clear();
+ getOrCreateWeakMap(myManager, RESOLVE_MAP, false).clear();
+ getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false).clear();
+ }
- }
- public PsiElement resolveWithCaching(PsiReference ref,
- Resolver resolver,
+ private <Ref extends PsiReference, Result> Result resolve(Ref ref,
+ AbstractResolver<Ref, Result> resolver,
+ Map<Ref,Reference<Result>>[] maps,
- boolean needToPreventRecursion,
- boolean incompleteCode) {
+ boolean needToPreventRecursion,
+ boolean incompleteCode) {
ProgressManager.getInstance().checkCanceled();
- int clearCountOnStart;
- synchronized (PsiLock.LOCK) {
- clearCountOnStart = myClearCount;
- }
+ int clearCountOnStart = myClearCount.intValue();
boolean physical = ref.getElement().isPhysical();
- final Reference<PsiElement> cached = getCachedResolve(ref, physical, incompleteCode);
- if (cached != null) return cached.get();
+ Result result = getCached(ref, maps, physical, incompleteCode);
+ if (result != null) {
+ return result;
+ }
-
+
if (incompleteCode) {
- final PsiElement results = resolveWithCaching(ref, resolver, needToPreventRecursion, false);
- if (results != null) {
- setCachedResolve(ref, results, physical, true, clearCountOnStart);
- return results;
+ result = resolve(ref, resolver, maps, needToPreventRecursion, false);
+ if (result != null && !(result instanceof Object[] && ((Object[])result).length == 0)) {
+ cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
+ return result;
}
}
- if (!lockElement(ref, needToPreventRecursion)) return null;
- PsiElement result = null;
+ if (needToPreventRecursion && !lockElement(ref)) return null;
try {
result = resolver.resolve(ref, incompleteCode);
}
- finally{
+ finally {
- unlockElement(ref, needToPreventRecursion);
+ if (needToPreventRecursion) {
+ unlockElement(ref);
- }
+ }
-
- setCachedResolve(ref, result, physical, incompleteCode, clearCountOnStart);
+ }
+ cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
return result;
}
- private static boolean lockElement(PsiReference ref, boolean doLock) {
- if (doLock) {
+ public ResolveResult[] resolveWithCaching(PsiPolyVariantReference ref,
+ PolyVariantResolver resolver,
+ boolean needToPreventRecursion,
+ boolean incompleteCode) {
+ ResolveResult[] result = resolve(ref, resolver, myPolyVariantResolveMaps, needToPreventRecursion, incompleteCode);
+ return result == null ? JavaResolveResult.EMPTY_ARRAY : result;
+ }
+
+ public PsiElement resolveWithCaching(PsiReference ref,
+ Resolver resolver,
+ boolean needToPreventRecursion,
+ boolean incompleteCode) {
+ return resolve(ref, resolver, myResolveMaps, needToPreventRecursion, incompleteCode);
+ }
+
+ private static boolean lockElement(PsiReference ref) {
- synchronized (IS_BEING_RESOLVED_KEY) {
- PsiElement elt = ref.getElement();
+ synchronized (IS_BEING_RESOLVED_KEY) {
+ PsiElement elt = ref.getElement();
- List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
- final Thread currentThread = Thread.currentThread();
- if (lockingThreads == null) {
- lockingThreads = new ArrayList<Thread>(1);
- elt.putUserData(IS_BEING_RESOLVED_KEY, lockingThreads);
- }
- else {
- if (lockingThreads.contains(currentThread)) return false;
- }
- lockingThreads.add(currentThread);
- }
+ List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
+ final Thread currentThread = Thread.currentThread();
+ if (lockingThreads == null) {
+ lockingThreads = new ArrayList<Thread>(1);
+ elt.putUserData(IS_BEING_RESOLVED_KEY, lockingThreads);
+ }
+ else {
+ if (lockingThreads.contains(currentThread)) return false;
+ }
+ lockingThreads.add(currentThread);
+ }
- }
return true;
}
- private static void unlockElement(PsiReference ref, boolean doLock) {
- if (doLock) {
+ private static void unlockElement(PsiReference ref) {
- synchronized (IS_BEING_RESOLVED_KEY) {
- PsiElement elt = ref.getElement();
+ synchronized (IS_BEING_RESOLVED_KEY) {
+ PsiElement elt = ref.getElement();
- List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
- if (lockingThreads == null) return;
- final Thread currentThread = Thread.currentThread();
- lockingThreads.remove(currentThread);
- if (lockingThreads.isEmpty()) {
- elt.putUserData(IS_BEING_RESOLVED_KEY, null);
- }
- }
- }
+ List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
+ if (lockingThreads == null) return;
+ final Thread currentThread = Thread.currentThread();
+ lockingThreads.remove(currentThread);
+ if (lockingThreads.isEmpty()) {
+ elt.putUserData(IS_BEING_RESOLVED_KEY, null);
+ }
+ }
+ }
- }
- private void setCachedResolve(PsiReference ref, PsiElement results, boolean physical, boolean incompleteCode, final int clearCountOnStart) {
- synchronized (PsiLock.LOCK) {
- if (clearCountOnStart != myClearCount && results != null) return;
-
- int index = getIndex(physical, incompleteCode);
- myResolveMaps[index].put(ref, new SoftReference<PsiElement>(results));
- }
- }
-
//for Visual Fabrique
public void clearResolveCaches(PsiReference ref) {
- synchronized (PsiLock.LOCK) {
- myClearCount++;
+ myClearCount.incrementAndGet();
- final boolean physical = ref.getElement().isPhysical();
+ final boolean physical = ref.getElement().isPhysical();
- setCachedPolyVariantResolve(ref, null, physical, false, myClearCount);
- setCachedPolyVariantResolve(ref, null, physical, true, myClearCount);
+ if (ref instanceof PsiPolyVariantReference) {
+ cache((PsiPolyVariantReference)ref, null, myPolyVariantResolveMaps, physical, false, myClearCount.intValue());
+ cache((PsiPolyVariantReference)ref, null, myPolyVariantResolveMaps, physical, true, myClearCount.intValue());
}
}
- private Reference<PsiElement> getCachedResolve(PsiReference ref, boolean physical, boolean incompleteCode) {
- synchronized (PsiLock.LOCK) {
- int index = getIndex(physical, incompleteCode);
- final Reference<PsiElement> reference = (Reference<PsiElement>)myResolveMaps[index].get(ref);
- if(reference == null) return null;
- return reference;
- }
- }
- public ResolveResult[] resolveWithCaching(PsiPolyVariantReference ref,
- PolyVariantResolver resolver,
- boolean needToPreventRecursion,
- boolean incompleteCode) {
- ProgressManager.getInstance().checkCanceled();
-
- int clearCountOnStart;
- synchronized (PsiLock.LOCK) {
- clearCountOnStart = myClearCount;
- }
-
- boolean physical = ref.getElement().isPhysical();
- final ResolveResult[] cached = getCachedPolyVariantResolve(ref, physical, incompleteCode);
- if (cached != null) return cached;
-
- if (incompleteCode) {
- final ResolveResult[] results = resolveWithCaching(ref, resolver, needToPreventRecursion, false);
- if (results != null && results.length > 0) {
- setCachedPolyVariantResolve(ref, results, physical, true, clearCountOnStart);
- return results;
- }
- }
-
- if (!lockElement(ref, needToPreventRecursion)) return JavaResolveResult.EMPTY_ARRAY;
- ResolveResult[] result;
- try {
- result = resolver.resolve(ref, incompleteCode);
- } finally {
- unlockElement(ref, needToPreventRecursion);
- }
-
- setCachedPolyVariantResolve(ref, result, physical, incompleteCode, clearCountOnStart);
- return result;
- }
-
private static int getIndex(boolean physical, boolean ic){
return (physical ? 0 : 1) << 1 | (ic ? 1 : 0);
}
- private void setCachedPolyVariantResolve(PsiReference ref, ResolveResult[] result, boolean physical, boolean incomplete, int clearCountOnStart){
- synchronized (PsiLock.LOCK) {
- if (clearCountOnStart != myClearCount && result != null) return;
- int index = getIndex(physical, incomplete);
- myPolyVariantResolveMaps[index].put(ref, new SoftReference<ResolveResult[]>(result));
- }
- }
-
- private ResolveResult[] getCachedPolyVariantResolve(PsiReference ref, boolean physical, boolean ic){
- synchronized (PsiLock.LOCK) {
+ private static <Ref,Result>Result getCached(Ref ref, Map<Ref,Reference<Result>>[] maps, boolean physical, boolean ic){
- int index = getIndex(physical, ic);
+ int index = getIndex(physical, ic);
- final Reference<ResolveResult[]> reference = (Reference<ResolveResult[]>)myPolyVariantResolveMaps[index].get(ref);
+ Reference<Result> reference = maps[index].get(ref);
- if(reference == null) return null;
- return reference.get();
- }
+ if(reference == null) return null;
+ return reference.get();
+ }
+ private <Ref,Result> void cache(Ref ref, Result result, Map<Ref,Reference<Result>>[] maps, boolean physical, boolean incompleteCode, final int clearCountOnStart) {
+ if (clearCountOnStart != myClearCount.intValue() && result != null) return;
+
+ int index = getIndex(physical, incompleteCode);
+ maps[index].put(ref, new SoftReference<Result>(result));
}
public static interface ConstValueComputer{
@@ -274,44 +228,35 @@
return result;
}
- public <K,V> WeakHashMap<K,V> getOrCreateWeakMap(final PsiManagerImpl manager, final Key<MapPair<K, V>> key, boolean forPhysical) {
+ public <K,V> ConcurrentMap<K,V> getOrCreateWeakMap(final PsiManagerImpl manager, final Key<MapPair<K, V>> key, boolean forPhysical) {
MapPair<K, V> pair = manager.getUserData(key);
if (pair == null){
pair = new MapPair<K,V>();
- manager.putUserData(key, pair);
+ pair = manager.putUserDataIfAbsent(key, pair);
final MapPair<K, V> _pair = pair;
manager.registerRunnableToRunOnChange(
new Runnable() {
public void run() {
- synchronized (PsiLock.LOCK) {
- myClearCount++;
+ myClearCount.incrementAndGet();
- _pair.physicalMap.clear();
- }
- }
+ _pair.physicalMap.clear();
+ }
+ }
- }
);
manager.registerRunnableToRunOnAnyChange(
new Runnable() {
public void run() {
- synchronized (PsiLock.LOCK) {
- myClearCount++;
+ myClearCount.incrementAndGet();
- _pair.nonPhysicalMap.clear();
- }
- }
+ _pair.nonPhysicalMap.clear();
+ }
+ }
- }
);
}
return forPhysical ? pair.physicalMap : pair.nonPhysicalMap;
}
public static class MapPair<K,V>{
- public WeakHashMap<K,V> physicalMap;
- public WeakHashMap<K,V> nonPhysicalMap;
-
- public MapPair() {
- physicalMap = new WeakHashMap<K, V>();
- nonPhysicalMap = new WeakHashMap<K, V>();
+ public final ConcurrentMap<K,V> physicalMap = new ConcurrentWeakHashMap<K, V>();
+ public final ConcurrentMap<K,V> nonPhysicalMap = new ConcurrentWeakHashMap<K, V>();
- }
- }
+ }
+}
\ No newline at end of file
-}
@@ -0,0 +1,317 @@
package com.intellij.psi.impl.source.resolve;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import com.intellij.util.containers.WeakHashMap;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.*;
public class ResolveCache {
private static final Key<MapPair<PsiReference, SoftReference<ResolveResult[]>>> JAVA_RESOLVE_MAP = Key.create("ResolveCache.JAVA_RESOLVE_MAP");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP = Key.create("ResolveCache.RESOLVE_MAP");
private static final Key<MapPair<PsiReference, SoftReference<ResolveResult[]>>> JAVA_RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.JAVA_RESOLVE_MAP_INCOMPLETE");
private static final Key<MapPair<PsiReference, Reference<PsiElement>>> RESOLVE_MAP_INCOMPLETE = Key.create("ResolveCache.RESOLVE_MAP_INCOMPLETE");
private static final Key<List<Thread>> IS_BEING_RESOLVED_KEY = Key.create("ResolveCache.IS_BEING_RESOLVED_KEY");
private static final Key<MapPair<PsiVariable, Object>> VAR_TO_CONST_VALUE_MAP_KEY = Key.create("ResolveCache.VAR_TO_CONST_VALUE_MAP_KEY");
//store types for method call expressions, NB: this caching is semantical, without this captured wildcards won't work
private Map<PsiExpression, WeakReference<PsiType>> myCaclulatedlTypes;
private static final Object NULL = Key.create("NULL");
private final PsiManagerImpl myManager;
private final Map<PsiVariable,Object> myVarToConstValueMap1;
private final Map<PsiVariable,Object> myVarToConstValueMap2;
private final WeakHashMap[] myPolyVariantResolveMaps = new WeakHashMap[4];
private final WeakHashMap[] myResolveMaps = new WeakHashMap[4];
private int myClearCount = 0;
public static interface PolyVariantResolver {
ResolveResult[] resolve(PsiPolyVariantReference ref, boolean incompleteCode);
}
public static interface Resolver{
PsiElement resolve(PsiReference ref, boolean incompleteCode);
}
public ResolveCache(PsiManagerImpl manager) {
myManager = manager;
myVarToConstValueMap1 = Collections.synchronizedMap(getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, true));
myVarToConstValueMap2 = Collections.synchronizedMap(getOrCreateWeakMap(myManager, VAR_TO_CONST_VALUE_MAP_KEY, false));
myPolyVariantResolveMaps[0] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true);
myPolyVariantResolveMaps[1] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true);
myResolveMaps[0] = getOrCreateWeakMap(myManager, RESOLVE_MAP, true);
myResolveMaps[1] = getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true);
myPolyVariantResolveMaps[2] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false);
myPolyVariantResolveMaps[3] = getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false);
myResolveMaps[2] = getOrCreateWeakMap(myManager, RESOLVE_MAP, false);
myResolveMaps[3] = getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false);
myCaclulatedlTypes = new WeakHashMap<PsiExpression, WeakReference<PsiType>>();
myManager.registerRunnableToRunOnAnyChange(new Runnable() {
public void run() {
synchronized (PsiLock.LOCK) {
myCaclulatedlTypes.clear();
}
}
});
}
public PsiType getType(PsiExpression expr, Function<PsiExpression, PsiType> f) {
WeakReference<PsiType> ref;
synchronized (PsiLock.LOCK) {
ref = myCaclulatedlTypes.get(expr);
}
PsiType type = ref == null ? null : ref.get();
if (type == null) {
type = f.fun(expr);
synchronized (PsiLock.LOCK) {
myCaclulatedlTypes.put(expr, new WeakReference<PsiType>(type));
}
}
return type;
}
public void clearCache() {
synchronized (PsiLock.LOCK) {
myClearCount++;
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, true).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, true).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP, false).clear();
getOrCreateWeakMap(myManager, JAVA_RESOLVE_MAP_INCOMPLETE, false).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP, true).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, true).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP, false).clear();
getOrCreateWeakMap(myManager, RESOLVE_MAP_INCOMPLETE, false).clear();
}
}
public PsiElement resolveWithCaching(PsiReference ref,
Resolver resolver,
boolean needToPreventRecursion,
boolean incompleteCode) {
ProgressManager.getInstance().checkCanceled();
int clearCountOnStart;
synchronized (PsiLock.LOCK) {
clearCountOnStart = myClearCount;
}
boolean physical = ref.getElement().isPhysical();
final Reference<PsiElement> cached = getCachedResolve(ref, physical, incompleteCode);
if (cached != null) return cached.get();
if (incompleteCode) {
final PsiElement results = resolveWithCaching(ref, resolver, needToPreventRecursion, false);
if (results != null) {
setCachedResolve(ref, results, physical, true, clearCountOnStart);
return results;
}
}
if (!lockElement(ref, needToPreventRecursion)) return null;
PsiElement result = null;
try {
result = resolver.resolve(ref, incompleteCode);
}
finally{
unlockElement(ref, needToPreventRecursion);
}
setCachedResolve(ref, result, physical, incompleteCode, clearCountOnStart);
return result;
}
private static boolean lockElement(PsiReference ref, boolean doLock) {
if (doLock) {
synchronized (IS_BEING_RESOLVED_KEY) {
PsiElement elt = ref.getElement();
List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
final Thread currentThread = Thread.currentThread();
if (lockingThreads == null) {
lockingThreads = new ArrayList<Thread>(1);
elt.putUserData(IS_BEING_RESOLVED_KEY, lockingThreads);
}
else {
if (lockingThreads.contains(currentThread)) return false;
}
lockingThreads.add(currentThread);
}
}
return true;
}
private static void unlockElement(PsiReference ref, boolean doLock) {
if (doLock) {
synchronized (IS_BEING_RESOLVED_KEY) {
PsiElement elt = ref.getElement();
List<Thread> lockingThreads = elt.getUserData(IS_BEING_RESOLVED_KEY);
if (lockingThreads == null) return;
final Thread currentThread = Thread.currentThread();
lockingThreads.remove(currentThread);
if (lockingThreads.isEmpty()) {
elt.putUserData(IS_BEING_RESOLVED_KEY, null);
}
}
}
}
private void setCachedResolve(PsiReference ref, PsiElement results, boolean physical, boolean incompleteCode, final int clearCountOnStart) {
synchronized (PsiLock.LOCK) {
if (clearCountOnStart != myClearCount && results != null) return;
int index = getIndex(physical, incompleteCode);
myResolveMaps[index].put(ref, new SoftReference<PsiElement>(results));
}
}
//for Visual Fabrique
public void clearResolveCaches(PsiReference ref) {
synchronized (PsiLock.LOCK) {
myClearCount++;
final boolean physical = ref.getElement().isPhysical();
setCachedPolyVariantResolve(ref, null, physical, false, myClearCount);
setCachedPolyVariantResolve(ref, null, physical, true, myClearCount);
}
}
private Reference<PsiElement> getCachedResolve(PsiReference ref, boolean physical, boolean incompleteCode) {
synchronized (PsiLock.LOCK) {
int index = getIndex(physical, incompleteCode);
final Reference<PsiElement> reference = (Reference<PsiElement>)myResolveMaps[index].get(ref);
if(reference == null) return null;
return reference;
}
}
public ResolveResult[] resolveWithCaching(PsiPolyVariantReference ref,
PolyVariantResolver resolver,
boolean needToPreventRecursion,
boolean incompleteCode) {
ProgressManager.getInstance().checkCanceled();
int clearCountOnStart;
synchronized (PsiLock.LOCK) {
clearCountOnStart = myClearCount;
}
boolean physical = ref.getElement().isPhysical();
final ResolveResult[] cached = getCachedPolyVariantResolve(ref, physical, incompleteCode);
if (cached != null) return cached;
if (incompleteCode) {
final ResolveResult[] results = resolveWithCaching(ref, resolver, needToPreventRecursion, false);
if (results != null && results.length > 0) {
setCachedPolyVariantResolve(ref, results, physical, true, clearCountOnStart);
return results;
}
}
if (!lockElement(ref, needToPreventRecursion)) return JavaResolveResult.EMPTY_ARRAY;
ResolveResult[] result;
try {
result = resolver.resolve(ref, incompleteCode);
} finally {
unlockElement(ref, needToPreventRecursion);
}
setCachedPolyVariantResolve(ref, result, physical, incompleteCode, clearCountOnStart);
return result;
}
private static int getIndex(boolean physical, boolean ic){
return (physical ? 0 : 1) << 1 | (ic ? 1 : 0);
}
private void setCachedPolyVariantResolve(PsiReference ref, ResolveResult[] result, boolean physical, boolean incomplete, int clearCountOnStart){
synchronized (PsiLock.LOCK) {
if (clearCountOnStart != myClearCount && result != null) return;
int index = getIndex(physical, incomplete);
myPolyVariantResolveMaps[index].put(ref, new SoftReference<ResolveResult[]>(result));
}
}
private ResolveResult[] getCachedPolyVariantResolve(PsiReference ref, boolean physical, boolean ic){
synchronized (PsiLock.LOCK) {
int index = getIndex(physical, ic);
final Reference<ResolveResult[]> reference = (Reference<ResolveResult[]>)myPolyVariantResolveMaps[index].get(ref);
if(reference == null) return null;
return reference.get();
}
}
public static interface ConstValueComputer{
Object execute(PsiVariable variable, Set<PsiVariable> visitedVars);
}
public Object computeConstantValueWithCaching(PsiVariable variable, ConstValueComputer computer, Set<PsiVariable> visitedVars){
boolean physical = variable.isPhysical();
Object cached = (physical ? myVarToConstValueMap1 : myVarToConstValueMap2).get(variable);
if (cached == NULL) return null;
if (cached != null) return cached;
Object result = computer.execute(variable, visitedVars);
(physical ? myVarToConstValueMap1 : myVarToConstValueMap2).put(variable, result != null ? result : NULL);
return result;
}
public <K,V> WeakHashMap<K,V> getOrCreateWeakMap(final PsiManagerImpl manager, final Key<MapPair<K, V>> key, boolean forPhysical) {
MapPair<K, V> pair = manager.getUserData(key);
if (pair == null){
pair = new MapPair<K,V>();
manager.putUserData(key, pair);
final MapPair<K, V> _pair = pair;
manager.registerRunnableToRunOnChange(
new Runnable() {
public void run() {
synchronized (PsiLock.LOCK) {
myClearCount++;
_pair.physicalMap.clear();
}
}
}
);
manager.registerRunnableToRunOnAnyChange(
new Runnable() {
public void run() {
synchronized (PsiLock.LOCK) {
myClearCount++;
_pair.nonPhysicalMap.clear();
}
}
}
);
}
return forPhysical ? pair.physicalMap : pair.nonPhysicalMap;
}
public static class MapPair<K,V>{
public WeakHashMap<K,V> physicalMap;
public WeakHashMap<K,V> nonPhysicalMap;
public MapPair() {
physicalMap = new WeakHashMap<K, V>();
nonPhysicalMap = new WeakHashMap<K, V>();
}
}
}
@@ -0,0 +1,8 @@
this
file
contains
a
number
of
modified
lines
@@ -0,0 +1,10 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Thu Nov 16 15:03:12 2006
+++ after/1.txt Thu Nov 16 15:03:15 2006
@@ -3,5 +3,5 @@
a
number
of
-unmodified
+modified
lines
@@ -0,0 +1,8 @@
this
file
contains
a
number
of
unmodified
lines
@@ -0,0 +1,8 @@
thidss
file
contains
a
number
of
unmodified
linesds
@@ -0,0 +1,15 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Thu Nov 16 15:03:12 2006
+++ after/1.txt Thu Nov 16 15:03:15 2006
@@ -1,8 +1,8 @@
-thids
+thidss
file
contains
a
number
of
unmodified
-linesd
\ No newline at end of file
+linesds
@@ -0,0 +1,8 @@
thids
file
contains
a
number
of
unmodified
linesd
@@ -0,0 +1,8 @@
thiss
file
contains
a
number
of
unmodified
liness
@@ -0,0 +1,14 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Thu Nov 16 15:03:12 2006
+++ after/1.txt Thu Nov 16 15:03:15 2006
@@ -1,8 +1,8 @@
-this
+thiss
file
contains
a
number
of
unmodified
-lines
+liness
@@ -0,0 +1,8 @@
this
file
contains
a
number
of
unmodified
lines
@@ -0,0 +1,8 @@
thidss
file
contains
a
number
of
unmodified
linesds
@@ -0,0 +1,16 @@
diff -r -u before/1.txt after/1.txt
--- before/1.txt Thu Nov 16 15:03:12 2006
+++ after/1.txt Thu Nov 16 15:03:15 2006
@@ -1,8 +1,8 @@
-thids
+thidss
file
contains
a
number
of
unmodified
-linesd
\ No newline at end of file
+linesds
\ No newline at end of file
@@ -0,0 +1,8 @@
thids
file
contains
a
number
of
unmodified
linesd
@@ -0,0 +1,19 @@
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
@NotNull
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
}
@@ -0,0 +1,20 @@
diff --git a/before/1.txt b/after/1.txt
index fad3998..5880be4 100644
--- a/before/1.txt
+++ b/after/1.txt
@@ -1,3 +1,5 @@
+import org.jetbrains.annotations.NotNull;
+
import java.util.function.Supplier;
class Test {
@@ -6,6 +8,7 @@ class Test {
b(newMethod());
}
+ @NotNull
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
--
2.6.3.windows.1
@@ -0,0 +1,16 @@
import java.util.function.Supplier;
class Test {
private void a()
{
b(newMethod());
}
private Supplier newMethod() {
return (s) -> {
System.out.println(s);
};
}
void b(Supplier s) {}
}

Some files were not shown because too many files have changed in this diff Show More