mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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
|
||||
|
||||
+2
-1
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+8
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -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);
|
||||
|
||||
+29
-41
@@ -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
|
||||
|
||||
+7
-7
@@ -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");
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+22
-6
@@ -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() {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
One
|
||||
Two
|
||||
Three
|
||||
+7
@@ -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,2 @@
|
||||
uno
|
||||
dos
|
||||
+15
@@ -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) {}
|
||||
+13
@@ -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
|
||||
+16
@@ -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) {}
|
||||
}
|
||||
+15
@@ -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) {}
|
||||
+10
@@ -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
|
||||
+16
@@ -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) {}
|
||||
}
|
||||
+16
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+12
@@ -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
|
||||
+16
@@ -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
|
||||
+262
@@ -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>();
|
||||
}
|
||||
}
|
||||
+430
@@ -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
|
||||
-}
|
||||
+317
@@ -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
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
thidss
|
||||
file
|
||||
contains
|
||||
a
|
||||
number
|
||||
of
|
||||
unmodified
|
||||
linesds
|
||||
+15
@@ -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
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
thids
|
||||
file
|
||||
contains
|
||||
a
|
||||
number
|
||||
of
|
||||
unmodified
|
||||
linesd
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
thiss
|
||||
file
|
||||
contains
|
||||
a
|
||||
number
|
||||
of
|
||||
unmodified
|
||||
liness
|
||||
+14
@@ -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
|
||||
+8
@@ -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
Reference in New Issue
Block a user