Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ivan Chirkov
2016-03-03 11:48:47 +01:00
457 changed files with 5921 additions and 3084 deletions
-11
View File
@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="asm4">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/asm4-all.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/asm4-src.zip!/" />
</SOURCES>
</library>
</component>
+1 -1
View File
@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2000-2016 JetBrains s.r.o.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+2
View File
@@ -0,0 +1,2 @@
src/
out/
+13
View File
@@ -0,0 +1,13 @@
Index: org/objectweb/asm/ClassReader.java
===================================================================
--- org/objectweb/asm/ClassReader.java
+++ org/objectweb/asm/ClassReader.java
@@ -167,7 +167,7 @@
this.b = b;
// checks the class version
if (readShort(off + 6) > Opcodes.V1_8) {
- throw new IllegalArgumentException();
+ //[JB: accept any version] throw new IllegalArgumentException();
}
// parses the constant pool
items = new int[readUnsignedShort(off + 8)];
+13
View File
@@ -0,0 +1,13 @@
Index: org/objectweb/asm/tree/MethodNode.java
===================================================================
--- org/objectweb/asm/tree/MethodNode.java
+++ org/objectweb/asm/tree/MethodNode.java
@@ -623,7 +623,7 @@
*/
protected LabelNode getLabelNode(final Label l) {
if (!(l.info instanceof LabelNode)) {
- l.info = new LabelNode();
+ l.info = new LabelNode(l); //[JB: passing a reference to avoid exceptions in coverage]
}
return (LabelNode) l.info;
}
+61
View File
@@ -0,0 +1,61 @@
<!--
~ Copyright 2000-2016 JetBrains s.r.o.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project name="Patches and repackages ASM library" default="package">
<!-- set this property to the path to a downloaded ASM source .jar file -->
<property name="asm.src" value=""/>
<property name="src.dir" value="${basedir}/src"/>
<property name="out.dir" value="${basedir}/out"/>
<property name="src.zip" value="${basedir}/asm5-src.zip"/>
<property name="out.jar" value="${basedir}/asm-all.jar"/>
<target name="check">
<available file="${asm.src}" type="file" property="asm.src.present"/>
<fail message="Please edit the file ${ant.file} and fill in the 'asm.src' property" unless="asm.src.present"/>
</target>
<target name="clean" depends="check">
<delete dir="${src.dir}" quiet="true"/>
<delete dir="${out.dir}" quiet="true"/>
<delete file="${src.zip}" quiet="true"/>
<delete file="${out.jar}" quiet="true"/>
</target>
<target name="unpack" depends="clean">
<unzip src="${asm.src}" dest="${src.dir}"/>
</target>
<target name="patch" depends="unpack">
<patch dir="${src.dir}" strip="0" patchfile="1_version_check.patch" failonerror="true"/>
<patch dir="${src.dir}" strip="0" patchfile="2_coverage_fix.patch" failonerror="true"/>
</target>
<target name="repackage" depends="patch">
<replace dir="${src.dir}" token="org.objectweb.asm" value="org.jetbrains.org.objectweb.asm"/>
<mkdir dir="${src.dir}/org/jetbrains/org"/>
<move file="${src.dir}/org/objectweb" todir="${src.dir}/org/jetbrains/org"/>
</target>
<target name="compile" depends="repackage">
<mkdir dir="${out.dir}"/>
<javac srcdir="${src.dir}" destdir="${out.dir}" source="1.5" target="1.5" debug="true"/>
</target>
<target name="package" depends="compile">
<zip destfile="${src.zip}" basedir="${src.dir}" duplicate="fail"/>
<jar destfile="${out.jar}" basedir="${out.dir}" duplicate="fail"/>
</target>
</project>
+6
View File
@@ -49,6 +49,12 @@
1.6 => plugins/gradle/lib/gradle-tooling-extension-api.jar
1.6 => plugins/gradle/lib/gradle-tooling-extension-impl.jar
1.6 => plugins/maven/lib/maven-server-api.jar
1.6 => plugins/maven/lib/maven2-server-impl.jar
1.6 => plugins/maven/lib/maven3-server-common.jar
1.6 => plugins/maven/lib/maven30-server-impl.jar
1.6 => plugins/maven/lib/maven32-server-impl.jar
1.4 => plugins/xpath/lib/rt/xslt-rt.jar
1.5 => plugins/xslt-debugger/lib/xslt-debugger-engine.jar
1.5 => plugins/xslt-debugger/lib/rt/xslt-debugger-engine-impl.jar
+3 -3
View File
@@ -12,15 +12,15 @@ Text=Create Desktop shortcut
[Field 2]
Type=checkbox
Left=5
Right=105
Right=70
Top=25
Bottom=35
State=0
[Field 3]
Type=Label
Left=115
Right=215
Left=75
Right=140
Top=25
Bottom=35
Text=""
+1 -1
View File
@@ -706,7 +706,7 @@ binding.setVariable("patchPropertiesFile", { String target, Map args = [:] ->
}
String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
String settings_dir = args.system_selector.replaceFirst("\\d+", "")
String settings_dir = args.system_selector.replaceFirst("\\d+(\\.\\d+)?", "")
ant.replace(file: file) {
replacefilter(token: "@@product_uc@@", value: product_uc)
replacefilter(token: "@@settings_dir@@", value: settings_dir)
@@ -35,7 +35,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListSeparator;
@@ -305,7 +305,7 @@ public class AttachSourcesNotificationProvider extends EditorNotifications.Provi
Library firstLibrary = libraries.get(0).getLibrary();
VirtualFile[] roots = firstLibrary != null ? firstLibrary.getFiles(OrderRootType.CLASSES) : VirtualFile.EMPTY_ARRAY;
VirtualFile[] candidates = FileChooser.chooseFiles(descriptor, myProject, roots.length == 0 ? null : PathUtil.getLocalFile(roots[0]));
final VirtualFile[] files = PathUIUtils.scanAndSelectDetectedJavaSourceRoots(myParentComponent, candidates);
final VirtualFile[] files = LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(myParentComponent, candidates);
if (files.length == 0) {
return ActionCallback.REJECTED;
}
@@ -26,7 +26,7 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.JarFileSystem;
@@ -215,7 +215,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider {
VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(srcFile);
if (jarRoot == null) return;
VirtualFile[] roots = PathUIUtils.scanAndSelectDetectedJavaSourceRoots(null, new VirtualFile[]{jarRoot});
VirtualFile[] roots = LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(null, new VirtualFile[]{jarRoot});
if (roots.length == 0) {
roots = new VirtualFile[]{jarRoot};
}
@@ -34,7 +34,7 @@ import javax.swing.*;
*/
@SuppressWarnings("unchecked")
public abstract class LanguageLevelCombo extends ComboBox {
private boolean myDefaultWasSelectedBeforeRemoving;
private final String myDefaultItem;
public LanguageLevelCombo(String defaultItem) {
@@ -91,18 +91,28 @@ public abstract class LanguageLevelCombo extends ComboBox {
private void updateDefaultLevel(LanguageLevel newLevel, boolean isDefaultProject) {
if (newLevel == null && !isDefaultProject) {
if (getSelectedItem() == myDefaultItem) {
setSelectedItem(getDefaultLevel());
if (isDefaultItemAdded()) {
boolean defaultSelected = getSelectedItem() == myDefaultItem;
if (defaultSelected) {
setSelectedItem(getDefaultLevel());
}
myDefaultWasSelectedBeforeRemoving = defaultSelected;
removeItem(myDefaultItem);
}
removeItem(myDefaultItem);
}
else if (!(getItemAt(0) instanceof String)) {
else if (!(isDefaultItemAdded())) {
addDefaultItem();
setSelectedIndex(0);
if (myDefaultWasSelectedBeforeRemoving) {
setSelectedIndex(0);
}
}
repaint();
}
private boolean isDefaultItemAdded() {
return getItemAt(0) instanceof String;
}
void addDefaultItem() {
insertItemAt(myDefaultItem, 0);
}
@@ -23,8 +23,8 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public class JavaSourceRootDetector extends RootDetector {
public JavaSourceRootDetector() {
public class LibraryJavaSourceRootDetector extends RootDetector {
public LibraryJavaSourceRootDetector() {
super(OrderRootType.SOURCES, false, "sources");
}
@@ -0,0 +1,61 @@
/*
* Copyright 2000-2009 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.openapi.roots.ui.configuration;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.OrderRoot;
import com.intellij.openapi.roots.libraries.ui.RootDetector;
import com.intellij.openapi.roots.libraries.ui.impl.LibraryRootsDetectorImpl;
import com.intellij.openapi.roots.libraries.ui.impl.RootDetectionUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* This utility class contains utility methods for selecting paths.
*
* @author Constantine.Plotnikov
*/
public class LibrarySourceRootDetectorUtil {
public static ExtensionPointName<RootDetector> JAVA_SOURCE_ROOT_DETECTOR = ExtensionPointName.create("com.intellij.library.javaSourceRootDetector");
protected LibrarySourceRootDetectorUtil() {
}
/**
* This method takes a candidates for the project root, then scans the candidates and
* if multiple candidates or non root source directories are found within some
* directories, it shows a dialog that allows selecting or deselecting them.
* @param parent a parent parent or project
* @param rootCandidates a candidates for roots
* @return a array of source folders or empty array if non was selected or dialog was canceled.
*/
public static VirtualFile[] scanAndSelectDetectedJavaSourceRoots(Component parentComponent, final VirtualFile[] rootCandidates) {
final List<OrderRoot> orderRoots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, null,
new LibraryRootsDetectorImpl(Arrays.asList(Extensions.getExtensions(JAVA_SOURCE_ROOT_DETECTOR))),
new OrderRootType[] {OrderRootType.SOURCES});
final List<VirtualFile> result = new ArrayList<VirtualFile>();
for (OrderRoot root : orderRoots) {
result.add(root.getFile());
}
return VfsUtil.toVirtualFileArray(result);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,46 +15,12 @@
*/
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.OrderRoot;
import com.intellij.openapi.roots.libraries.ui.RootDetector;
import com.intellij.openapi.roots.libraries.ui.impl.LibraryRootsDetectorImpl;
import com.intellij.openapi.roots.libraries.ui.impl.RootDetectionUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* This utility class contains utility methods for selecting paths.
*
* @author Constantine.Plotnikov
* @deprecated please use {@link LibrarySourceRootDetectorUtil} directly
*/
public class PathUIUtils {
public static final RootDetector JAVA_SOURCE_ROOT_DETECTOR = new JavaSourceRootDetector();
public class PathUIUtils extends LibrarySourceRootDetectorUtil {
public static final RootDetector JAVA_SOURCE_ROOT_DETECTOR = new LibraryJavaSourceRootDetector();
private PathUIUtils() {
}
/**
* This method takes a candidates for the project root, then scans the candidates and
* if multiple candidates or non root source directories are found within some
* directories, it shows a dialog that allows selecting or deselecting them.
* @param parent a parent parent or project
* @param rootCandidates a candidates for roots
* @return a array of source folders or empty array if non was selected or dialog was canceled.
*/
public static VirtualFile[] scanAndSelectDetectedJavaSourceRoots(Component parentComponent, final VirtualFile[] rootCandidates) {
final List<OrderRoot> orderRoots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, null,
new LibraryRootsDetectorImpl(Arrays.asList(Extensions.getExtensions(RootDetector.JAVA_SOURCE_ROOT_DETECTOR))),
new OrderRootType[] {OrderRootType.SOURCES});
final List<VirtualFile> result = new ArrayList<VirtualFile>();
for (OrderRoot root : orderRoots) {
result.add(root.getFile());
}
return VfsUtil.toVirtualFileArray(result);
}
}
@@ -30,6 +30,7 @@ import com.intellij.openapi.roots.NativeLibraryOrderRootType;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.*;
import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory;
import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -73,7 +74,7 @@ public class DefaultLibraryRootsComponentDescriptor extends LibraryRootsComponen
List<RootDetector> results = new ArrayList<>();
results.add(new FileTypeBasedRootFilter(OrderRootType.CLASSES, false, StdFileTypes.CLASS, "classes"));
results.add(new FileTypeBasedRootFilter(OrderRootType.CLASSES, true, StdFileTypes.CLASS, "jar directory"));
results.addAll(Arrays.asList(Extensions.getExtensions(RootDetector.JAVA_SOURCE_ROOT_DETECTOR)));
results.addAll(Arrays.asList(Extensions.getExtensions(LibrarySourceRootDetectorUtil.JAVA_SOURCE_ROOT_DETECTOR)));
Collections.addAll(results,
new FileTypeBasedRootFilter(OrderRootType.SOURCES, true, StdFileTypes.JAVA, "source archive directory"),
new JavadocRootDetector(),
@@ -23,7 +23,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.ui.SdkPathEditor;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil;
import com.intellij.openapi.vfs.VirtualFile;
import javax.swing.*;
@@ -61,7 +61,7 @@ public class SourcesOrderRootTypeUIFactory implements OrderRootTypeUIFactory {
@Override
protected VirtualFile[] adjustAddedFileSet(final Component component, final VirtualFile[] files) {
if (mySdk.getSdkType() instanceof JavaSdkType) {
return PathUIUtils.scanAndSelectDetectedJavaSourceRoots(component, files);
return LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(component, files);
}
return super.adjustAddedFileSet(component, files);
}
@@ -244,6 +244,16 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
myDefaultConstructor = defaultConstructor;
}
@NotNull
@Override
public String getQualifiedName() {
final PsiClass psiClass = getElement();
if (psiClass == null) return super.getQualifiedName();
final String qName = psiClass.getQualifiedName();
if (qName == null) return super.getQualifiedName();
return qName;
}
@Override
public void buildReferences() {
PsiClass psiClass = getElement();
@@ -53,9 +53,13 @@ import java.util.Map;
import java.util.Set;
public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
private final DaemonCodeAnalyzerSettings myDaemonSettings;
private final EditorColorsManager myColorsManager;
protected final DaemonCodeAnalyzerSettings myDaemonSettings;
protected final EditorColorsManager myColorsManager;
private final Option myLambdaOption = new Option("java.lambda", "Lambda", AllIcons.Gutter.ImplementingFunctionalInterface);
private final Option myOverriddenOption = new Option("java.overridden", "Overridden method", AllIcons.Gutter.OverridenMethod);
private final Option myImplementedOption = new Option("java.implemented", "Implemented method", AllIcons.Gutter.ImplementedMethod);
private final Option myOverridingOption = new Option("java.overriding", "Overriding method", AllIcons.Gutter.OverridingMethod);
private final Option myImplementingOption = new Option("java.implementing", "Implementing method", AllIcons.Gutter.ImplementingMethod);
public JavaLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) {
myDaemonSettings = daemonSettings;
@@ -67,20 +71,29 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) {
PsiElement parent;
if (element instanceof PsiIdentifier && (parent = element.getParent()) instanceof PsiMethod) {
if (!myOverridingOption.isEnabled() && !myImplementingOption.isEnabled()) return null;
PsiMethod method = (PsiMethod)parent;
MethodSignatureBackedByPsiMethod superSignature = SuperMethodsSearch.search(method, null, true, false).findFirst();
if (superSignature != null) {
boolean overrides =
method.hasModifierProperty(PsiModifier.ABSTRACT) == superSignature.getMethod().hasModifierProperty(PsiModifier.ABSTRACT);
final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod;
final Icon icon;
if (overrides) {
if (!myOverridingOption.isEnabled()) return null;
icon = AllIcons.Gutter.OverridingMethod;
}
else {
if (!myImplementingOption.isEnabled()) return null;
icon = AllIcons.Gutter.ImplementingMethod;
}
return createSuperMethodLineMarkerInfo(element, icon, Pass.UPDATE_ALL);
}
}
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element);
final PsiElement firstChild = element.getFirstChild();
if (interfaceMethod != null && firstChild != null && LineMarkerSettings.getSettings().isEnabled(myLambdaOption)) {
if (interfaceMethod != null && firstChild != null && myLambdaOption.isEnabled()) {
return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingFunctionalInterface, Pass.UPDATE_ALL);
}
@@ -216,7 +229,7 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
return range;
}
public static void collectInheritingClasses(@NotNull PsiClass aClass,
protected void collectInheritingClasses(@NotNull PsiClass aClass,
@NotNull Collection<LineMarkerInfo> result,
@NotNull Map<PsiClass, PsiClass> subClassCache) {
if (aClass.hasModifierProperty(PsiModifier.FINAL)) {
@@ -226,7 +239,15 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
PsiClass subClass = subClassCache.get(aClass);
if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) {
final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod;
final Icon icon;
if (aClass.isInterface()) {
if (!myImplementedOption.isEnabled()) return;
icon = AllIcons.Gutter.ImplementedMethod;
}
else {
if (!myOverriddenOption.isEnabled()) return;
icon = AllIcons.Gutter.OverridenMethod;
}
PsiElement range = aClass.getNameIdentifier();
if (range == null) {
range = aClass;
@@ -241,7 +262,8 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
}
}
private static void collectOverridingMethods(@NotNull final Collection<PsiMethod> methods, @NotNull Collection<LineMarkerInfo> result) {
private void collectOverridingMethods(@NotNull final Collection<PsiMethod> methods, @NotNull Collection<LineMarkerInfo> result) {
if (!myOverriddenOption.isEnabled() && !myImplementedOption.isEnabled()) return;
final Set<PsiMethod> overridden = new HashSet<PsiMethod>();
Set<PsiClass> classes = new THashSet<PsiClass>();
for (PsiMethod method : methods) {
@@ -281,7 +303,12 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
for (PsiMethod method : overridden) {
ProgressManager.checkCanceled();
boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT);
if (overrides) {
if (!myOverriddenOption.isEnabled()) return;
}
else {
if (!myImplementedOption.isEnabled()) return;
}
PsiElement range = getMethodRange(method);
final MarkerType type = MarkerType.OVERRIDDEN_METHOD;
final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod;
@@ -301,7 +328,7 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
@Override
public Option[] getOptions() {
return new Option[] {myLambdaOption};
return new Option[] {myLambdaOption, myOverriddenOption, myImplementedOption, myOverridingOption, myImplementingOption};
}
private static class ArrowUpLineMarkerInfo extends MergeableLineMarkerInfo<PsiElement> {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,12 @@
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.*;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -29,12 +33,16 @@ import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.stream.Stream;
public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
@Override
@@ -42,16 +50,20 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
if (!PsiUtil.getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_1_7)) return false;
final PsiLocalVariable variable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
if (variable == null) return false;
final PsiExpression initializer = variable.getInitializer();
if (initializer == null) return false;
final PsiElement declaration = variable.getParent();
if (!(declaration instanceof PsiDeclarationStatement)) return false;
final PsiElement codeBlock = declaration.getParent();
if (!(codeBlock instanceof PsiCodeBlock)) return false;
PsiType type = null;
return InheritanceUtil.isInheritor(variable.getType(), CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE);
PsiLocalVariable variable = findVariable(element);
if (variable != null) {
type = variable.getType();
}
else {
PsiExpression expression = findExpression(element);
if (expression != null) {
type = expression.getType();
}
}
return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE);
}
@Override
@@ -60,35 +72,85 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
return;
}
final PsiLocalVariable variable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
if (variable == null) return;
final PsiExpression initializer = variable.getInitializer();
if (initializer == null) return;
final PsiElement declaration = variable.getParent();
if (!(declaration instanceof PsiDeclarationStatement)) return;
final PsiElement codeBlock = declaration.getParent();
if (!(codeBlock instanceof PsiCodeBlock)) return;
PsiLocalVariable variable = findVariable(element);
if (variable != null) {
processVariable(project, editor, variable);
}
else {
PsiExpression expression = findExpression(element);
if (expression != null) {
processExpression(project, editor, expression);
}
}
}
final LocalSearchScope scope = new LocalSearchScope(codeBlock);
private static PsiLocalVariable findVariable(PsiElement element) {
PsiLocalVariable variable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
if (variable != null &&
variable.getInitializer() != null &&
variable.getParent() instanceof PsiDeclarationStatement &&
variable.getParent().getParent() instanceof PsiCodeBlock) {
return variable;
}
if (variable == null && element instanceof PsiWhiteSpace) {
PsiElement sibling = element.getPrevSibling();
if (sibling instanceof PsiDeclarationStatement) {
PsiElement lastVar = ArrayUtil.getLastElement(((PsiDeclarationStatement)sibling).getDeclaredElements());
if (lastVar instanceof PsiLocalVariable) {
return (PsiLocalVariable)lastVar;
}
}
}
return null;
}
private static PsiExpression findExpression(PsiElement element) {
PsiExpression expression = PsiTreeUtil.getParentOfType(element, PsiExpression.class);
if (expression != null &&
expression.getParent() instanceof PsiExpressionStatement &&
expression.getParent().getParent() instanceof PsiCodeBlock) {
return expression;
}
if (expression == null && element instanceof PsiWhiteSpace) {
PsiElement sibling = element.getPrevSibling();
if (sibling instanceof PsiExpressionStatement) {
return ((PsiExpressionStatement)sibling).getExpression();
}
}
return null;
}
private static void processVariable(Project project, Editor editor, PsiLocalVariable variable) {
PsiExpression initializer = ObjectUtils.assertNotNull(variable.getInitializer());
PsiElement declaration = variable.getParent();
PsiElement codeBlock = declaration.getParent();
LocalSearchScope scope = new LocalSearchScope(codeBlock);
PsiElement last = null;
for (PsiReference reference : ReferencesSearch.search(variable, scope).findAll()) {
final PsiElement usage = PsiTreeUtil.findPrevParent(codeBlock, reference.getElement());
PsiElement usage = PsiTreeUtil.findPrevParent(codeBlock, reference.getElement());
if ((last == null || usage.getTextOffset() > last.getTextOffset())) {
last = usage;
}
}
final String text = "try (" + variable.getTypeElement().getText() + " " + variable.getName() + " = " + initializer.getText() + ") {}";
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiTryStatement armStatement = (PsiTryStatement)declaration.replace(factory.createStatementFromText(text, codeBlock));
String text = "try (" + variable.getTypeElement().getText() + " " + variable.getName() + " = " + initializer.getText() + ") {}";
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiTryStatement armStatement = (PsiTryStatement)declaration.replace(factory.createStatementFromText(text, codeBlock));
List<PsiElement> toFormat = null;
if (last != null) {
toFormat = moveStatements(last, armStatement);
}
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
final PsiElement formattedElement = codeStyleManager.reformat(armStatement);
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
PsiElement formattedElement = codeStyleManager.reformat(armStatement);
if (toFormat != null) {
for (PsiElement psiElement : toFormat) {
codeStyleManager.reformat(psiElement);
@@ -96,9 +158,9 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
}
if (last == null) {
final PsiCodeBlock tryBlock = ((PsiTryStatement)formattedElement).getTryBlock();
PsiCodeBlock tryBlock = ((PsiTryStatement)formattedElement).getTryBlock();
if (tryBlock != null) {
final PsiJavaToken brace = tryBlock.getLBrace();
PsiJavaToken brace = tryBlock.getLBrace();
if (brace != null) {
editor.getCaretModel().moveToOffset(brace.getTextOffset() + 1);
}
@@ -110,8 +172,9 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
PsiCodeBlock tryBlock = statement.getTryBlock();
assert tryBlock != null : statement.getText();
PsiElement parent = statement.getParent();
LocalSearchScope scope = new LocalSearchScope(parent);
List<PsiElement> toFormat = new SmartList<PsiElement>();
List<PsiElement> toFormat = new SmartList<>();
PsiElement stopAt = last.getNextSibling();
PsiElement i = statement.getNextSibling();
@@ -125,13 +188,8 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
for (PsiElement declared : ((PsiDeclarationStatement)child).getDeclaredElements()) {
if (!(declared instanceof PsiLocalVariable)) continue;
final int endOffset = last.getTextRange().getEndOffset();
boolean contained = ReferencesSearch.search(declared, new LocalSearchScope(parent)).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference ref) {
return ref.getElement().getTextOffset() <= endOffset;
}
});
int endOffset = last.getTextRange().getEndOffset();
boolean contained = ReferencesSearch.search(declared, scope).forEach(ref -> ref.getElement().getTextOffset() <= endOffset);
if (!contained) {
PsiLocalVariable var = (PsiLocalVariable)declared;
@@ -163,6 +221,38 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
return toFormat;
}
private static void processExpression(Project project, Editor editor, PsiExpression expression) {
PsiType type = ObjectUtils.assertNotNull(expression.getType());
PsiElement statement = expression.getParent();
PsiElement codeBlock = statement.getParent();
String text = "try (" + type.getCanonicalText(true) + " r = " + expression.getText() + ") {}";
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiTryStatement tryStatement = (PsiTryStatement)statement.replace(factory.createStatementFromText(text, codeBlock));
tryStatement = (PsiTryStatement)CodeStyleManager.getInstance(project).reformat(tryStatement);
tryStatement = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(tryStatement);
PsiResourceList resourceList = tryStatement.getResourceList();
if (resourceList != null) {
PsiResourceVariable var = (PsiResourceVariable)resourceList.iterator().next();
PsiIdentifier id = var.getNameIdentifier();
PsiExpression initializer = var.getInitializer();
if (id != null && initializer != null) {
type = initializer.getType();
String[] names = IntroduceVariableBase.getSuggestedName(type, initializer).names;
PsiType[] types = Stream.of(new TypeSelectorManagerImpl(project, type, initializer, PsiExpression.EMPTY_ARRAY).getTypesForAll())
.filter(t -> InheritanceUtil.isInheritor(t, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE))
.toArray(PsiType[]::new);
TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(var);
builder.replaceElement(id, new NamesExpression(names));
builder.replaceElement(var.getTypeElement(), new TypeExpression(project, types));
builder.run(editor, true);
}
}
}
@NotNull
@Override
public String getFamilyName() {
@@ -174,4 +264,27 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
public String getText() {
return getFamilyName();
}
}
private static class NamesExpression extends Expression {
private final String[] myNames;
public NamesExpression(String[] names) {
myNames = names;
}
@Override
public Result calculateResult(ExpressionContext context) {
return calculateQuickResult(context);
}
@Override
public Result calculateQuickResult(ExpressionContext context) {
return new TextResult(myNames[0]);
}
@Override
public LookupElement[] calculateLookupItems(ExpressionContext context) {
return Stream.of(myNames).map(LookupElementBuilder::create).toArray(LookupElement[]::new);
}
}
}
@@ -1728,6 +1728,22 @@ public class ExtractMethodProcessor implements MatchProvider {
myExtractedMethod = suggester.getExtractedMethod();
myMethodCall = suggester.getMethodCall();
myVariableDatum = suggester.getVariableData();
final List<PsiVariable> outputVariables = new ArrayList<>();
for (PsiReturnStatement statement : PsiUtil.findReturnStatements(myExtractedMethod)) {
final PsiExpression returnValue = statement.getReturnValue();
if (returnValue instanceof PsiReferenceExpression) {
final PsiElement resolve = ((PsiReferenceExpression)returnValue).resolve();
if (resolve instanceof PsiLocalVariable) {
outputVariables.add((PsiVariable)resolve);
}
}
}
if (outputVariables.size() == 1) {
myOutputVariable = outputVariables.get(0);
}
return null;
}
}
@@ -334,6 +334,12 @@ public class ExtractMethodSignatureSuggester {
for (PsiParameter parameter : parameters) {
uniqueNameGenerator.addExistingName(parameter.getName());
}
SyntaxTraverser.psiTraverser().withRoot(myExtractedMethod.getBody())
.filter(element -> element instanceof PsiVariable)
.forEach(element -> uniqueNameGenerator.addExistingName(((PsiVariable)element).getName()));
final THashMap<PsiExpression, String> unique = new THashMap<PsiExpression, String>(ourEquivalenceStrategy);
final Map<PsiExpression, String> replacement = new HashMap<PsiExpression, String>();
for (PsiExpression expr : exprs) {
@@ -256,6 +256,27 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
return null;
}
@Override
public Collection<String> findConflicts(PsiElement element, PsiElement[] elements, UsageInfo[] usages) {
String methodRefFound = null;
if (!ApplicationManager.getApplication().isUnitTestMode() && (element instanceof PsiMethod || element instanceof PsiParameter)) {
for (UsageInfo usage : usages) {
final PsiElement refElement = usage.getElement();
if (refElement instanceof PsiMethodReferenceExpression) {
methodRefFound = RefactoringBundle.message("expand.method.reference.warning");
break;
}
}
}
if (methodRefFound != null) {
Collection<String> result = new ArrayList<>();
result.add(methodRefFound);
result.addAll(super.findConflicts(element, elements, usages));
return result;
}
return super.findConflicts(element, elements, usages);
}
public Collection<String> findConflicts(@NotNull final PsiElement element, @NotNull final PsiElement[] allElementsToDelete) {
if (element instanceof PsiMethod) {
final PsiClass containingClass = ((PsiMethod)element).getContainingClass();
@@ -17,6 +17,8 @@ package com.intellij.psi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.infos.MethodCandidateInfo;
@@ -35,6 +37,7 @@ import java.util.*;
* Date: 7/17/12
*/
public class LambdaUtil {
public static final RecursionGuard ourParameterGuard = RecursionManager.createGuard("lambdaParameterGuard");
public static ThreadLocal<Map<PsiElement, PsiType>> ourFunctionTypes = new ThreadLocal<Map<PsiElement, PsiType>>();
private static final Logger LOG = Logger.getInstance("#" + LambdaUtil.class.getName());
@@ -667,6 +670,10 @@ public class LambdaUtil {
return null;
}
public static boolean isLambdaParameterCheck() {
return !ourParameterGuard.currentStack().isEmpty();
}
public static class TypeParamsChecker extends PsiTypeVisitor<Boolean> {
private PsiMethod myMethod;
private final PsiClass myClass;
@@ -294,7 +294,9 @@ public class MethodCandidateInfo extends CandidateInfo{
if (!stackStamp.mayCacheNow() ||
isOverloadCheck() ||
!includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) ||
getMarkerList() != null && PsiResolveHelper.ourGraphGuard.currentStack().contains(getMarkerList().getParent())) {
getMarkerList() != null && PsiResolveHelper.ourGraphGuard.currentStack().contains(getMarkerList().getParent()) ||
LambdaUtil.isLambdaParameterCheck()
) {
return inferredSubstitutor;
}
@@ -435,7 +435,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
public PsiType[] getArgumentTypes() {
if (myExpressionTypes == null) {
final PsiType[] expressionTypes = argumentList.getExpressionTypes();
if (MethodCandidateInfo.isOverloadCheck()) {
if (MethodCandidateInfo.isOverloadCheck() || LambdaUtil.isLambdaParameterCheck()) {
return expressionTypes;
}
myExpressionTypes = expressionTypes;
@@ -19,6 +19,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.ElementPresentationUtil;
@@ -67,8 +68,14 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
if (parameterIndex > -1) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class);
if (lambdaExpression != null) {
PsiType type = FunctionalInterfaceParameterizationUtil.getGroundTargetType(LambdaUtil.getFunctionalInterfaceType(lambdaExpression, true), lambdaExpression);
final PsiType functionalInterfaceType = LambdaUtil.ourParameterGuard.doPreventingRecursion(param, false,
new Computable<PsiType>() {
@Override
public PsiType compute() {
return LambdaUtil.getFunctionalInterfaceType(lambdaExpression, true);
}
});
PsiType type = FunctionalInterfaceParameterizationUtil.getGroundTargetType(functionalInterfaceType, lambdaExpression);
if (type instanceof PsiIntersectionType) {
final PsiType[] conjuncts = ((PsiIntersectionType)type).getConjuncts();
for (PsiType conjunct : conjuncts) {
@@ -90,7 +90,7 @@ public class JavaResolveCache {
}
//cache standalone expression types as they do not depend on the context
final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck();
final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck() || LambdaUtil.isLambdaParameterCheck();
if (isOverloadCheck && PsiPolyExpressionUtil.isPolyExpression(expr)) {
return type;
}
@@ -361,11 +361,13 @@ public class InferenceSession {
if (parameters != null && args != null && !isOverloadCheck()) {
final Set<ConstraintFormula> additionalConstraints = new LinkedHashSet<ConstraintFormula>();
final HashSet<ConstraintFormula> ignoredConstraints = new HashSet<ConstraintFormula>();
if (parameters.length > 0) {
collectAdditionalConstraints(parameters, args, properties.getMethod(), mySiteSubstitutor, additionalConstraints, properties.isVarargs(), initialSubstitutor);
collectAdditionalConstraints(parameters, args, properties.getMethod(), mySiteSubstitutor, additionalConstraints,
ignoredConstraints, properties.isVarargs(), initialSubstitutor);
}
if (!additionalConstraints.isEmpty() && !proceedWithAdditionalConstraints(additionalConstraints)) {
if (!additionalConstraints.isEmpty() && !proceedWithAdditionalConstraints(additionalConstraints, ignoredConstraints)) {
return;
}
}
@@ -416,21 +418,29 @@ public class InferenceSession {
PsiMethod parentMethod,
PsiSubstitutor siteSubstitutor,
Set<ConstraintFormula> additionalConstraints,
Set<ConstraintFormula> ignoredConstraints,
boolean varargs,
PsiSubstitutor initialSubstitutor) {
for (int i = 0; i < args.length; i++) {
final PsiExpression arg = PsiUtil.skipParenthesizedExprDown(args[i]);
if (arg != null) {
if (MethodCandidateInfo.isOverloadCheck() && arg instanceof PsiLambdaExpression) {
for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) {
if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) {
return;
}
}
}
final PsiSubstitutor nestedSubstitutor = myInferenceSessionContainer.findNestedSubstitutor(arg, myInferenceSubstitution);
final PsiType parameterType = nestedSubstitutor.substitute(getParameterType(parameters, i, siteSubstitutor, varargs));
if (!isPertinentToApplicability(arg, parentMethod)) {
if (arg instanceof PsiLambdaExpression) {
for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) {
if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) {
return;
}
}
for (Object expr : LambdaUtil.ourParameterGuard.currentStack()) {
if (expr instanceof PsiParameter && ((PsiParameter)expr).getDeclarationScope() == arg) {
ignoredConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType));
return;
}
}
}
additionalConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType));
}
additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(arg, parameterType));
@@ -439,12 +449,12 @@ public class InferenceSession {
//the set contains all constraint formulas that would appear in the set C when determining the poly expression's invocation type.
final PsiMethod calledMethod = getCalledMethod((PsiCall)arg);
if (calledMethod != null && PsiPolyExpressionUtil.isMethodCallPolyExpression(arg, calledMethod)) {
collectAdditionalConstraints(additionalConstraints, (PsiCall)arg, initialSubstitutor);
collectAdditionalConstraints(additionalConstraints, ignoredConstraints, (PsiCall)arg, initialSubstitutor);
}
}
else if (arg instanceof PsiLambdaExpression &&
isPertinentToApplicability(arg, parentMethod)) {
collectLambdaReturnExpression(additionalConstraints, (PsiLambdaExpression)arg, parameterType,
collectLambdaReturnExpression(additionalConstraints, ignoredConstraints, (PsiLambdaExpression)arg, parameterType,
!isProperType(initialSubstitutor.substitute(parameterType)),
initialSubstitutor);
}
@@ -472,19 +482,22 @@ public class InferenceSession {
}
private void collectLambdaReturnExpression(Set<ConstraintFormula> additionalConstraints,
Set<ConstraintFormula> ignoredConstraints,
PsiLambdaExpression lambdaExpression,
PsiType parameterType,
boolean addConstraint, PsiSubstitutor initialSubstitutor) {
boolean addConstraint,
PsiSubstitutor initialSubstitutor) {
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(parameterType);
if (interfaceReturnType != null) {
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(lambdaExpression);
for (PsiExpression returnExpression : returnExpressions) {
processReturnExpression(additionalConstraints, returnExpression, interfaceReturnType, addConstraint, initialSubstitutor);
processReturnExpression(additionalConstraints, ignoredConstraints, returnExpression, interfaceReturnType, addConstraint, initialSubstitutor);
}
}
}
private void processReturnExpression(Set<ConstraintFormula> additionalConstraints,
Set<ConstraintFormula> ignoredConstraints,
PsiExpression returnExpression,
PsiType functionalType,
boolean addConstraint,
@@ -493,7 +506,7 @@ public class InferenceSession {
if (addConstraint) {
final PsiMethod calledMethod = getCalledMethod((PsiCallExpression)returnExpression);
if (calledMethod != null && PsiPolyExpressionUtil.isMethodCallPolyExpression(returnExpression, calledMethod)) {
collectAdditionalConstraints(additionalConstraints, (PsiCallExpression)returnExpression, initialSubstitutor);
collectAdditionalConstraints(additionalConstraints, ignoredConstraints, (PsiCallExpression)returnExpression, initialSubstitutor);
}
}
else {
@@ -501,19 +514,20 @@ public class InferenceSession {
}
}
else if (returnExpression instanceof PsiParenthesizedExpression) {
processReturnExpression(additionalConstraints, ((PsiParenthesizedExpression)returnExpression).getExpression(), functionalType, addConstraint, initialSubstitutor);
processReturnExpression(additionalConstraints, ignoredConstraints, ((PsiParenthesizedExpression)returnExpression).getExpression(), functionalType, addConstraint, initialSubstitutor);
}
else if (returnExpression instanceof PsiConditionalExpression) {
processReturnExpression(additionalConstraints, ((PsiConditionalExpression)returnExpression).getThenExpression(), functionalType, addConstraint, initialSubstitutor);
processReturnExpression(additionalConstraints, ((PsiConditionalExpression)returnExpression).getElseExpression(), functionalType, addConstraint, initialSubstitutor);
processReturnExpression(additionalConstraints, ignoredConstraints, ((PsiConditionalExpression)returnExpression).getThenExpression(), functionalType, addConstraint, initialSubstitutor);
processReturnExpression(additionalConstraints, ignoredConstraints, ((PsiConditionalExpression)returnExpression).getElseExpression(), functionalType, addConstraint, initialSubstitutor);
}
else if (returnExpression instanceof PsiLambdaExpression) {
collectLambdaReturnExpression(additionalConstraints, (PsiLambdaExpression)returnExpression, functionalType, myErased, initialSubstitutor);
collectLambdaReturnExpression(additionalConstraints, ignoredConstraints, (PsiLambdaExpression)returnExpression, functionalType, myErased, initialSubstitutor);
}
}
private void collectAdditionalConstraints(final Set<ConstraintFormula> additionalConstraints,
final PsiCall callExpression,
final Set<ConstraintFormula> ignoredConstraints,
final PsiCall callExpression,
PsiSubstitutor initialSubstitutor) {
PsiExpressionList argumentList = callExpression.getArgumentList();
if (argumentList != null) {
@@ -524,7 +538,8 @@ public class InferenceSession {
final PsiExpression[] newArgs = argumentList.getExpressions();
final PsiParameter[] newParams = method.getParameterList().getParameters();
if (newParams.length > 0) {
collectAdditionalConstraints(newParams, newArgs, method, chooseSiteSubstitutor(properties, result, method), additionalConstraints, chooseVarargsMode(properties, result), initialSubstitutor);
collectAdditionalConstraints(newParams, newArgs, method, chooseSiteSubstitutor(properties, result, method), additionalConstraints,
ignoredConstraints, chooseVarargsMode(properties, result), initialSubstitutor);
}
}
}
@@ -1290,7 +1305,7 @@ public class InferenceSession {
}
}
private boolean proceedWithAdditionalConstraints(Set<ConstraintFormula> additionalConstraints) {
private boolean proceedWithAdditionalConstraints(Set<ConstraintFormula> additionalConstraints, Set<ConstraintFormula> ignoredConstraints) {
//empty substitutor should be used to resolve input variables:
//all types in additional constraints are already substituted during collecting phase,
//recursive site substitutors (T -> List<T>) would make additional constraints work with multiple times substituted types, which is incorrect.
@@ -1300,7 +1315,7 @@ public class InferenceSession {
while (!additionalConstraints.isEmpty()) {
//extract subset of constraints
final Set<ConstraintFormula> subset = buildSubset(additionalConstraints);
final Set<ConstraintFormula> subset = buildSubset(additionalConstraints, ignoredConstraints);
//collect all input variables of selection
final Set<InferenceVariable> varsToResolve = new LinkedHashSet<InferenceVariable>();
@@ -1312,7 +1327,7 @@ public class InferenceSession {
final PsiSubstitutor substitutor = resolveSubsetOrdered(varsToResolve, siteSubstitutor);
for (ConstraintFormula formula : subset) {
if (!processOneConstraint(formula, additionalConstraints, substitutor)) return false;
if (!processOneConstraint(formula, additionalConstraints, substitutor, ignoredConstraints)) return false;
}
}
return true;
@@ -1329,8 +1344,9 @@ public class InferenceSession {
}
private boolean processOneConstraint(ConstraintFormula formula,
Set<ConstraintFormula> additionalConstraints,
PsiSubstitutor substitutor) {
Set<ConstraintFormula> additionalConstraints,
PsiSubstitutor substitutor,
Set<ConstraintFormula> ignoredConstraints) {
if (myContext instanceof PsiCall) {
PsiExpressionList argumentList = ((PsiCall)myContext).getArgumentList();
@@ -1348,27 +1364,20 @@ public class InferenceSession {
if (formula instanceof ExpressionCompatibilityConstraint) {
PsiExpression expression = ((ExpressionCompatibilityConstraint)formula).getExpression();
if (expression instanceof PsiLambdaExpression) {
PsiType parameterType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(((ExpressionCompatibilityConstraint)formula).getT(),
(PsiLambdaExpression)expression);
collectLambdaReturnExpression(additionalConstraints, (PsiLambdaExpression)expression, parameterType, !isProperType(parameterType), substitutor);
PsiType parameterType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(((ExpressionCompatibilityConstraint)formula).getT(), (PsiLambdaExpression)expression);
collectLambdaReturnExpression(additionalConstraints, ignoredConstraints, (PsiLambdaExpression)expression, parameterType, !isProperType(parameterType), substitutor);
}
}
return true;
}
private Set<ConstraintFormula> buildSubset(final Set<ConstraintFormula> additionalConstraints) {
private Set<ConstraintFormula> buildSubset(final Set<ConstraintFormula> additionalConstraints,
final Set<ConstraintFormula> ignoredConstraints) {
final Set<InferenceVariable> outputVariables = getOutputVariables(additionalConstraints);
final Set<InferenceVariable> ignoredOutputVariables = getOutputVariables(ignoredConstraints);
Set<ConstraintFormula> subset = new LinkedHashSet<ConstraintFormula>();
final Set<InferenceVariable> outputVariables = new HashSet<InferenceVariable>();
for (ConstraintFormula constraint : additionalConstraints) {
if (constraint instanceof InputOutputConstraintFormula) {
final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
final Set<InferenceVariable> outputVars = ((InputOutputConstraintFormula)constraint).getOutputVariables(inputVariables, this);
if (outputVars != null) {
outputVariables.addAll(outputVars);
}
}
}
Set<ConstraintFormula> noInputVariables = new LinkedHashSet<ConstraintFormula>();
for (ConstraintFormula constraint : additionalConstraints) {
@@ -1382,11 +1391,13 @@ public class InferenceSession {
final Set<InferenceVariable> dependencies = inputVariable.getDependencies(this);
dependencies.add(inputVariable);
if (!hasCapture(inputVariable)) {
for (InferenceVariable outputVariable : outputVariables) {
if (ContainerUtil.intersects(outputVariable.getDependencies(this), dependencies)) {
dependsOnOutput = true;
break;
}
if (dependsOnOutput(ignoredOutputVariables, dependencies)) {
dependsOnOutput = true;
ignoredConstraints.add(constraint);
break;
}
else {
dependsOnOutput = dependsOnOutput(outputVariables, dependencies);
}
}
@@ -1414,7 +1425,10 @@ public class InferenceSession {
}
}
if (subset.isEmpty()) {
subset.add(additionalConstraints.iterator().next()); //todo choose one constraint
additionalConstraints.removeAll(ignoredConstraints);
if (!additionalConstraints.isEmpty()) {
subset.add(additionalConstraints.iterator().next()); //todo choose one constraint
}
}
if (!noInputVariables.isEmpty()) {
@@ -1425,6 +1439,30 @@ public class InferenceSession {
return subset;
}
private boolean dependsOnOutput(Set<InferenceVariable> outputVariables, Set<InferenceVariable> dependencies) {
for (InferenceVariable outputVariable : outputVariables) {
if (ContainerUtil.intersects(outputVariable.getDependencies(this), dependencies)) {
return true;
}
}
return false;
}
@NotNull
private Set<InferenceVariable> getOutputVariables(Set<ConstraintFormula> constraintFormulas) {
final Set<InferenceVariable> outputVariables = new HashSet<InferenceVariable>();
for (ConstraintFormula constraint : constraintFormulas) {
if (constraint instanceof InputOutputConstraintFormula) {
final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
final Set<InferenceVariable> outputVars = ((InputOutputConstraintFormula)constraint).getOutputVariables(inputVariables, this);
if (outputVars != null) {
outputVariables.addAll(outputVars);
}
}
}
return outputVariables;
}
public PsiSubstitutor collectApplicabilityConstraints(final PsiMethodReferenceExpression reference,
final MethodCandidateInfo candidateInfo,
final PsiType functionalInterfaceType) {
@@ -81,7 +81,7 @@ public class InferenceSessionContainer {
if (topLevelCall != null) {
final InferenceSession session;
if (MethodCandidateInfo.isOverloadCheck() || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty()) {
if (MethodCandidateInfo.isOverloadCheck() || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty() || LambdaUtil.isLambdaParameterCheck()) {
session = startTopLevelInference(topLevelCall);
}
else {
@@ -134,9 +134,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (method != null && !method.isConstructor()) {
returnType = method.getReturnType();
if (returnType != null) {
typeParams = method.getTypeParameters();
}
typeParams = method.getTypeParameters();
}
else if (resolveResult != null) {
final PsiClass psiClass = method != null ? method.getContainingClass() : (PsiClass)resolveResult.getElement();
@@ -162,7 +160,9 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
return callSession;
}
callSession.registerReturnTypeConstraints(siteSubstitutor.substitute(returnType), targetType);
if (returnType != null) {
callSession.registerReturnTypeConstraints(siteSubstitutor.substitute(returnType), targetType);
}
if (callSession.repeatInferencePhases()) {
return callSession;
}
@@ -175,8 +175,8 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
session.registerIncompatibleErrorMessage(message);
}
}
return null;
}
return null;
}
return session;
}
@@ -80,7 +80,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
myArgumentsList.getText() + "; " +
"file=" + (method == null ? "<unknown>" : method.getContainingFile()));
}
return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, true, new Computable<CandidateInfo>() {
return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, false, new Computable<CandidateInfo>() {
@Override
public CandidateInfo compute() {
return guardedOverloadResolution(conflicts);
@@ -104,7 +104,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
public PsiType[] getArgumentTypes() {
if (myExpressionTypes == null && argumentList != null) {
final PsiType[] expressionTypes = getExpressionTypes(argumentList);
if (MethodCandidateInfo.isOverloadCheck()) {
if (MethodCandidateInfo.isOverloadCheck() || LambdaUtil.isLambdaParameterCheck()) {
return expressionTypes;
}
myExpressionTypes = expressionTypes;
@@ -0,0 +1,14 @@
import java.util.function.Function;
import java.util.stream.Stream;
class Test {
<K> void foo(Function<String, K> f1) {}
<T> Stream<T> bar(T ts) {
return null;
}
void f(){
foo(y -> bar(y.to<caret>String()).map(a -> a.length()));
}
}
@@ -0,0 +1,10 @@
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
class StreamMainSimplified {
public static void main(Optional<Map.Entry<Integer, String>> first) {
String s1 = first.map((e) -> e.getV<caret>alue()).orElse("").substring(9);
}
}
@@ -3,8 +3,8 @@ import java.util.*;
class Main {
void foo(List<Integer> list) {
bar(list, i -> i.intValue(), i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
bar1(list, i -> i.intValue(), i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
bar(list, i -> <error descr="Bad return type in lambda expression: int cannot be converted to S_OUT">i.intValue()</error>, i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
bar1(list, i -> <error descr="Bad return type in lambda expression: int cannot be converted to S_OUT">i.intValue()</error>, i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
}
<U, S_IN, S_OUT, R> R bar(List<S_IN> list,
@@ -36,3 +36,12 @@ final class Collectors {
downstream.characteristics().toArray(new Collector.Characteristics[downstream.characteristics().size()]));
}
}
class SimplifiedTest {
public static void a(Stream<Integer> classifier) {
flatMapping(classifier.map(k -> new AbstractMap.SimpleEntry<Integer, String>(k,k.toString())), Map.Entry::getKey);
}
public static <U, R> void flatMapping(Stream<U> stream, Function<U, R> downstream) {}
}
@@ -0,0 +1,7 @@
import java.io.*;
class C {
void m(File file) throws IOException {
<caret>new FileInputStream(file);
}
}
@@ -0,0 +1,7 @@
import java.io.*;
class C {
void m(File file) throws IOException {
new FileInputStream(file)<caret>
}
}
@@ -0,0 +1,8 @@
import java.io.*;
class C {
void m(File file) throws IOException {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
}
}
}
@@ -0,0 +1,8 @@
import java.io.*;
class C {
void m(File file) throws IOException {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
}
}
}
@@ -0,0 +1,8 @@
import java.io.*;
import java.net.*;
class C {
public void read(URLConnection connection) {
InputStream stream = connection.getInputStream();<caret>
}
}
@@ -0,0 +1,9 @@
import java.io.*;
import java.net.*;
class C {
public void read(URLConnection connection) {
try (InputStream stream = connection.getInputStream()) {<caret>
}
}
}
@@ -0,0 +1,25 @@
class Test {
private BigDecimal getRevenue() {
<selection>final String query = createNamedQuery("revenues");
String revenues = "";
final String revenue;
revenue = "a";
</selection>
return revenue;
}
public BigDecimal getExpense() {
final String query = createNamedQuery("expenses");
String expenses = "";
final String expense;
expense = "a";
return expense;
}
private String createNamedQuery(String expenses) {
return null;
}
}
@@ -0,0 +1,29 @@
import org.jetbrains.annotations.NotNull;
class Test {
private BigDecimal getRevenue() {
final String revenue = newMethod("revenues");
return revenue;
}
@NotNull
private String newMethod(String revenues2) {
final String query = createNamedQuery(revenues2);
String revenues = "";
final String revenue;
revenue = "a";
return revenue;
}
public BigDecimal getExpense() {
final String expense = newMethod("expenses");
return expense;
}
private String createNamedQuery(String expenses) {
return null;
}
}
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
@@ -419,18 +420,17 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
}
}
assertTrue(tooltips.contains("<html><body><table border=0><tr><td>" +
"<b>identity(&nbsp;)&nbsp;</b></td><td colspan=1>in <b>Function</b>&nbsp;cannot be applied</td></tr><tr><td>to</td><td><b>()</b>&nbsp;" +
"</td></tr></table><br/>" +
"reason: no instance(s) of type variable(s) K, U exist so that Map&lt;K, U&gt; conforms to Function&lt;U, V&gt;" +
"</body></html>"));
assertTrue(tooltips.contains(
"<html><body><table border=0><tr><td>" +
"<b>identity(&nbsp;)&nbsp;</b></td><td colspan=1>in <b>Function</b>&nbsp;cannot be applied</td></tr><tr><td>to</td><td><b>()</b>&nbsp;" +
"</td></tr></table><br/>" +
"reason: no instance(s) of type variable(s) K, U exist so that Map&lt;K, U&gt; conforms to Function&lt;U, V&gt;" +
"</body></html>"));
boolean found = false;
for (String tooltip : tooltips) {
if (tooltip.contains("reason: no instance(s) of type variable(s) K, U exist so that Map&lt;K, U&gt; conforms to Function&lt;U, V&gt;")) {
found = true;
break;
}
}
if (!found) {
fail(StringUtil.join(tooltips, ", "));
}
}
private void doTest() throws Exception {
@@ -63,6 +63,14 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
doTestCachedUnresolved();
}
public void testCacheUnresolvedMethods4() throws Exception {
doTestCachedUnresolved();
}
public void testCacheUnresolvedMethods5() throws Exception {
doTestCachedUnresolved();
}
public void testMethodOverloadsInsideLambdaHierarchy() throws Exception {
doTestAllMethodCallExpressions();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,14 +27,17 @@ public class SurroundAutoCloseableActionTest extends LightCodeInsightFixtureTest
}
public void testSimple() { doTest(); }
public void testSimplePast() { doTest(); }
public void testUsage() { doTest(); }
public void testMixedUsages() { doTest(); }
public void testLastDeclaration() { doTest(); }
public void testSplitVar() { doTest(); }
public void testExpression() { doTest(); }
public void testExpressionIncomplete() { doTest(); }
private void doTest() {
String name = getTestName(false);
String intention = CodeInsightBundle.message("intention.surround.resource.with.ARM.block");
CodeInsightTestUtil.doIntentionTest(myFixture, intention, name + ".java", name + "_after.java");
}
}
}
@@ -15,15 +15,19 @@
*/
package com.intellij.codeInsight.navigation;
import com.intellij.application.options.editor.GutterIconsConfigurable;
import com.intellij.codeInsight.daemon.GutterIconDescriptor;
import com.intellij.codeInsight.daemon.GutterMark;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.testFramework.TestActionEvent;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import java.util.List;
import java.util.Set;
/**
* @author Dmitry Avdeev
@@ -68,4 +72,17 @@ public class RunLineMarkerTest extends LightCodeInsightFixtureTestCase {
list.get(1).update(event);
assertEquals("Run 'MainTest'", event.getPresentation().getText());
}
public void testConfigurable() throws Exception {
GutterIconsConfigurable configurable = new GutterIconsConfigurable();
configurable.createComponent();
List<GutterIconDescriptor> descriptors = configurable.getDescriptors();
Set<String> strings = ContainerUtil.map2Set(descriptors, new Function<GutterIconDescriptor, String>() {
@Override
public String fun(GutterIconDescriptor descriptor) {
return descriptor.getId();
}
});
assertEquals(descriptors.size(), strings.size());
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2000-2015 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.codeInsight.template
import com.intellij.codeInsight.template.impl.InvokeTemplateAction
import com.intellij.codeInsight.template.impl.SurroundWithTemplateHandler
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
class SurroundWithTemplateTest extends LightCodeInsightFixtureTestCase {
public void testSurroundWithTryWithResources() {
myFixture.configureByText "C.java", """\
import java.io.*;
class C {
void m() {
new FileReader("/dev/null")<caret>
}
}""".stripIndent()
invokeTemplate("TR")
myFixture.checkResult """\
import java.io.*;
class C {
void m() {
try (FileReader fileReader = new FileReader("/dev/null")) {
<caret>
}
}
}""".stripIndent()
}
private void invokeTemplate(String template) {
DefaultActionGroup group = SurroundWithTemplateHandler.createActionGroup(project, editor, file)
assertNotNull(group)
InvokeTemplateAction action = group.childActionsOrStubs.find {
it instanceof InvokeTemplateAction && (it as InvokeTemplateAction).template.key == template
} as InvokeTemplateAction
assertNotNull(action)
action.perform()
}
}
@@ -675,6 +675,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doDuplicatesTest();
}
public void testSuggestChangeSignatureWithOutputVariables() throws Exception {
doDuplicatesTest();
}
public void testSuggestChangeSignatureWithChangedParameterName() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, false, "p");
@@ -68,6 +68,7 @@ public abstract class JspManager implements IBaseJspManager {
public abstract String[] getPossibleTldUris(@NotNull Module module);
@NotNull
public abstract Collection<XmlFile> getPossibleTldFiles(@NotNull Module module);
@Nullable
@@ -25,6 +25,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScopes;
import com.intellij.psi.search.GlobalSearchScopesCore;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
@@ -218,7 +220,8 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
return false;
}
PsiClass aClass = method.getContainingClass();
return aClass != null && GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(aClass.getQualifiedName());
return aClass != null && (GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(aClass.getQualifiedName()) ||
GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(aClass.getQualifiedName()));
}
private PsiMethodCallExpression findGuavaMethodChain(PsiMethodCallExpression expression) {
@@ -352,7 +355,6 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
private static boolean performTypeMigration(List<PsiElement> elements, List<PsiType> types) {
PsiFile containingFile = null;
SearchScope typeMigrationScope = GlobalSearchScope.EMPTY_SCOPE;
for (PsiElement element : elements) {
final PsiFile currentContainingFile = element.getContainingFile();
if (containingFile == null) {
@@ -361,13 +363,13 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
else {
LOG.assertTrue(containingFile.isEquivalentTo(currentContainingFile));
}
typeMigrationScope = typeMigrationScope.union(element.getUseScope());
}
LOG.assertTrue(containingFile != null);
if (!FileModificationService.getInstance().prepareFileForWrite(containingFile)) return false;
try {
final TypeMigrationRules rules = new TypeMigrationRules();
rules.setBoundScope(typeMigrationScope);
rules.setBoundScope(GlobalSearchScopesCore.projectProductionScope(containingFile.getProject())
.union(GlobalSearchScopesCore.projectTestScope(containingFile.getProject())));
TypeMigrationProcessor.runHighlightingTypeMigration(containingFile.getProject(),
null,
rules,
@@ -98,8 +98,17 @@ public class GuavaConversionUtil {
}
else {
final GuavaLambda lambda = GuavaLambda.findFor(evaluator.evaluateType(expression));
return lambda == null ? expression
: addMethodReference(expression, lambda);
if (lambda == null) {
return expression;
}
else {
final PsiExpression expressionWithMethodReference = addMethodReference(expression, lambda);
if (insertTypeCase) {
return adjustLambdaContainingExpression(expressionWithMethodReference, true, targetType, evaluator);
} else {
return expressionWithMethodReference;
}
}
}
}
if (expression instanceof PsiMethodReferenceExpression) {
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-1
View File
@@ -1,6 +1,5 @@
asm-commons.jar
asm.jar
asm4-all.jar
asm-all.jar
automaton.jar
cglib-2.2.2.jar
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
class MockDocumentCommitProcessor extends DocumentCommitProcessor {
class MockDocumentCommitProcessor implements DocumentCommitProcessor {
@Override
public void commitSynchronously(@NotNull Document document, @NotNull Project project, @NotNull PsiFile psiFile) {
}
@@ -26,6 +26,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.util.SystemProperties;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.concurrency.AppScheduledExecutorService;
import com.intellij.util.containers.ContainerUtil;
@@ -69,8 +70,8 @@ public class PerformanceWatcher implements ApplicationComponent {
private volatile ApdexData myGeneralApdex = ApdexData.EMPTY;
private volatile long myLastSampling = System.currentTimeMillis();
private volatile long myLastAliveEdt = System.currentTimeMillis();
private long myLastDumpTime = 0;
private long myFreezeStart = 0;
private long myLastDumpTime;
private long myFreezeStart;
/**
* If the product is unresponsive for UNRESPONSIVE_THRESHOLD_SECONDS, dump threads every UNRESPONSIVE_INTERVAL_SECONDS
@@ -104,55 +105,36 @@ public class PerformanceWatcher implements ApplicationComponent {
@Override
public void initComponent() {
if (!shouldWatch()) return;
UNRESPONSIVE_THRESHOLD_SECONDS = SystemProperties.getIntProperty("performance.watcher.threshold", 5);
UNRESPONSIVE_INTERVAL_SECONDS = SystemProperties.getIntProperty("performance.watcher.interval", 5);
final AppScheduledExecutorService service = (AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService();
service.setNewThreadListener(new Consumer<Thread>() {
private final int ourReasonableThreadPoolSize = Registry.intValue("core.pooled.threads");
if (shouldWatch()) {
final AppScheduledExecutorService service = (AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService();
service.setNewThreadListener(new Consumer<Thread>() {
private final int ourReasonableThreadPoolSize = Registry.intValue("core.pooled.threads");
@Override
public void consume(Thread thread) {
if (service.getBackendPoolExecutorSize() > ourReasonableThreadPoolSize
&& ApplicationInfoImpl.getShadowInstance().isEAP()) {
File file = dumpThreads("newPooledThread/", true);
LOG.info("Not enough pooled threads" + (file != null ? "; dumped threads into file '" + file.getPath() + "'" : ""));
@Override
public void consume(Thread thread) {
if (service.getBackendPoolExecutorSize() > ourReasonableThreadPoolSize
&& ApplicationInfoImpl.getShadowInstance().isEAP()) {
File file = dumpThreads("newPooledThread/", true);
LOG.info("Not enough pooled threads" + (file != null ? "; dumped threads into file '" + file.getPath() + "'" : ""));
}
}
}
});
});
final String threshold = System.getProperty("performance.watcher.threshold");
if (threshold != null) {
try {
UNRESPONSIVE_THRESHOLD_SECONDS = Integer.parseInt(threshold);
}
catch (NumberFormatException e) {
// ignore
}
}
final String interval = System.getProperty("performance.watcher.interval");
if (interval != null) {
try {
UNRESPONSIVE_INTERVAL_SECONDS = Integer.parseInt(interval);
}
catch (NumberFormatException e) {
// ignore
}
}
if (UNRESPONSIVE_THRESHOLD_SECONDS == 0 || UNRESPONSIVE_INTERVAL_SECONDS == 0) {
return;
}
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
deleteOldThreadDumps();
}
});
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
deleteOldThreadDumps();
}
});
for (MemoryPoolMXBean bean : ManagementFactory.getMemoryPoolMXBeans()) {
if ("Code Cache".equals(bean.getName())) {
watchCodeCache(bean);
return;
for (MemoryPoolMXBean bean : ManagementFactory.getMemoryPoolMXBeans()) {
if ("Code Cache".equals(bean.getName())) {
watchCodeCache(bean);
break;
}
}
}
}
@@ -206,8 +188,7 @@ public class PerformanceWatcher implements ApplicationComponent {
}
private boolean shouldWatch() {
return !ApplicationManager.getApplication().isUnitTestMode() &&
!ApplicationManager.getApplication().isHeadlessEnvironment() &&
return !ApplicationManager.getApplication().isHeadlessEnvironment() &&
UNRESPONSIVE_INTERVAL_SECONDS != 0 &&
UNRESPONSIVE_THRESHOLD_SECONDS != 0;
}
@@ -30,12 +30,14 @@ import com.intellij.util.containers.DoubleArrayList;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class AbstractProgressIndicatorBase extends UserDataHolderBase implements ProgressIndicatorStacked {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.util.ProgressIndicatorBase");
private static final CoreProgressManager ourProgressManager = (CoreProgressManager)ProgressManager.getInstance();
@Nullable private final CoreProgressManager myProgressManager =
ApplicationManager.getApplication() == null ? null : (CoreProgressManager)ProgressManager.getInstance();
private volatile String myText;
private volatile double myFraction;
@@ -128,7 +130,7 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements
if (isCanceled() && isCancelable()) {
throw new ProcessCanceledException();
}
if (ourProgressManager.sleepIfNeeded()) {
if (myProgressManager != null && myProgressManager.sleepIfNeeded()) {
if (isCanceled() && isCancelable()) {
throw new ProcessCanceledException();
}
@@ -282,7 +282,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
private void reparseFile(@NotNull final PsiFile file, @NotNull FileElement treeElement, @NotNull CharSequence newText) {
PsiToDocumentSynchronizer synchronizer =((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject)).getSynchronizer();
TextRange changedPsiRange = DocumentCommitProcessor.getChangedPsiRange(file, treeElement, newText);
TextRange changedPsiRange = DocumentCommitThread.getChangedPsiRange(file, treeElement, newText);
if (changedPsiRange == null) return;
final DiffLog log = BlockSupport.getInstance(myProject).reparseRange(file, treeElement, changedPsiRange, newText, new EmptyProgressIndicator(),
@@ -15,300 +15,17 @@
*/
package com.intellij.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.PomManager;
import com.intellij.pom.PomModel;
import com.intellij.pom.event.PomModelEvent;
import com.intellij.pom.impl.PomTransactionBase;
import com.intellij.pom.tree.TreeAspect;
import com.intellij.pom.tree.TreeAspectEvent;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLock;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.text.DiffLog;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.ForeignLeafPsiElement;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.text.BlockSupport;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class DocumentCommitProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread");
public abstract void commitSynchronously(@NotNull Document document, @NotNull Project project, @NotNull PsiFile psiFile);
public abstract void commitAsynchronously(@NotNull final Project project,
@NotNull final Document document,
@NonNls @NotNull Object reason,
@NotNull ModalityState currentModalityState);
protected static class CommitTask {
static final Key<Object> CANCEL_REASON = Key.create("CANCEL_REASON");
@NotNull final Document document;
@NotNull final Project project;
private final int modificationSequence; // store initial document modification sequence here to check if it changed later before commit in EDT
// when queued it's not started
// when dequeued it's started
// when failed it's canceled
@NotNull final ProgressIndicator indicator; // progress to commit this doc under.
@NotNull final Object reason;
@NotNull final ModalityState myCreationModalityState;
private final CharSequence myLastCommittedText;
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> myOldFileNodes;
protected CommitTask(@NotNull final Project project,
@NotNull final Document document,
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
@NotNull ProgressIndicator indicator,
@NotNull Object reason,
@NotNull ModalityState currentModalityState) {
this.document = document;
this.project = project;
this.indicator = indicator;
this.reason = reason;
myCreationModalityState = currentModalityState;
myLastCommittedText = PsiDocumentManager.getInstance(project).getLastCommittedText(document);
myOldFileNodes = oldFileNodes;
modificationSequence = ((DocumentEx)document).getModificationSequence();
}
@NonNls
@Override
public String toString() {
return "Doc: " + document + " (\"" + StringUtil.first(document.getImmutableCharSequence(), 40, true).toString().replaceAll("\n", " ") + "\")"
+ (indicator.isCanceled() ? " (Canceled: " + ((UserDataHolder)indicator).getUserData(CANCEL_REASON) + ")":"")
+" Reason: " + reason
+ (isStillValid() ? "" : "; changed: old seq="+modificationSequence+", new seq="+ ((DocumentEx)document).getModificationSequence())
;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommitTask)) return false;
CommitTask task = (CommitTask)o;
return document.equals(task.document) && project.equals(task.project);
}
@Override
public int hashCode() {
int result = document.hashCode();
result = 31 * result + project.hashCode();
return result;
}
public boolean isStillValid() {
return ((DocumentEx)document).getModificationSequence() == modificationSequence;
}
public void cancel(@NotNull Object reason, @NotNull DocumentCommitProcessor commitProcessor) {
if (!indicator.isCanceled()) {
commitProcessor.log(project, "indicator cancel", this);
indicator.cancel();
((UserDataHolder)indicator).putUserData(CANCEL_REASON, reason);
}
}
}
// public for Upsource
@Nullable("returns runnable to execute under write action in AWT to finish the commit")
public Processor<Document> doCommit(@NotNull final CommitTask task,
@NotNull final PsiFile file,
@NotNull final FileASTNode oldFileNode) {
Document document = task.document;
final CharSequence newDocumentText = document.getImmutableCharSequence();
final TextRange changedPsiRange = getChangedPsiRange(file, task.myLastCommittedText, newDocumentText);
if (changedPsiRange == null) {
return null;
}
final Boolean data = document.getUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY);
if (data != null) {
document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null);
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, data);
}
BlockSupport blockSupport = BlockSupport.getInstance(file.getProject());
final DiffLog diffLog = blockSupport.reparseRange(file, oldFileNode, changedPsiRange, newDocumentText, task.indicator, task.myLastCommittedText);
return new Processor<Document>() {
@Override
public boolean process(Document document) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
if (!task.isStillValid() ||
((PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject())).getCachedViewProvider(document) != file.getViewProvider()) {
return false; // optimistic locking failed
}
doActualPsiChange(file, diffLog);
assertAfterCommit(document, file, (FileElement)oldFileNode);
return true;
}
};
}
private static int getLeafMatchingLength(CharSequence leafText, CharSequence pattern, int patternIndex, int finalPatternIndex, int direction) {
int leafIndex = direction == 1 ? 0 : leafText.length() - 1;
int finalLeafIndex = direction == 1 ? leafText.length() - 1 : 0;
int result = 0;
while (leafText.charAt(leafIndex) == pattern.charAt(patternIndex)) {
result++;
if (leafIndex == finalLeafIndex || patternIndex == finalPatternIndex) {
break;
}
leafIndex += direction;
patternIndex += direction;
}
return result;
}
private static int getMatchingLength(@NotNull FileElement treeElement, @NotNull CharSequence text, boolean fromStart) {
int patternIndex = fromStart ? 0 : text.length() - 1;
int finalPatternIndex = fromStart ? text.length() - 1 : 0;
int direction = fromStart ? 1 : -1;
ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false);
int result = 0;
while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) {
if (!(leaf instanceof ForeignLeafPsiElement)) {
CharSequence chars = leaf.getChars();
if (chars.length() > 0) {
int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction);
result += matchingLength;
if (matchingLength != chars.length()) {
break;
}
patternIndex += fromStart ? matchingLength : -matchingLength;
}
}
leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false);
}
return result;
}
@Nullable
public static TextRange getChangedPsiRange(@NotNull PsiFile file, @NotNull FileElement treeElement, @NotNull CharSequence newDocumentText) {
int psiLength = treeElement.getTextLength();
if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) {
return new TextRange(0, psiLength);
}
int commonPrefixLength = getMatchingLength(treeElement, newDocumentText, true);
if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == psiLength) {
return null;
}
int commonSuffixLength = Math.min(getMatchingLength(treeElement, newDocumentText, false), psiLength - commonPrefixLength);
return new TextRange(commonPrefixLength, psiLength - commonSuffixLength);
}
@Nullable
private static TextRange getChangedPsiRange(@NotNull PsiFile file,
@NotNull CharSequence oldDocumentText,
@NotNull CharSequence newDocumentText) {
int psiLength = oldDocumentText.length();
if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) {
return new TextRange(0, psiLength);
}
int commonPrefixLength = StringUtil.commonPrefixLength(oldDocumentText, newDocumentText);
if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == psiLength) {
return null;
}
int commonSuffixLength = Math.min(StringUtil.commonSuffixLength(oldDocumentText, newDocumentText), psiLength - commonPrefixLength);
return new TextRange(commonPrefixLength, psiLength - commonSuffixLength);
}
public static void doActualPsiChange(@NotNull final PsiFile file, @NotNull final DiffLog diffLog) {
CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() {
@Override
public void run() {
synchronized (PsiLock.LOCK) {
file.getViewProvider().beforeContentsSynchronized();
final Document document = file.getViewProvider().getDocument();
PsiDocumentManagerBase documentManager = (PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject());
PsiToDocumentSynchronizer.DocumentChangeTransaction transaction = documentManager.getSynchronizer().getTransaction(document);
final PsiFileImpl fileImpl = (PsiFileImpl)file;
if (transaction == null) {
final PomModel model = PomManager.getModel(fileImpl.getProject());
model.runTransaction(new PomTransactionBase(fileImpl, model.getModelAspect(TreeAspect.class)) {
@Override
public PomModelEvent runInner() {
return new TreeAspectEvent(model, diffLog.performActualPsiChange(file));
}
});
}
else {
diffLog.performActualPsiChange(file);
}
}
}
});
}
private void assertAfterCommit(@NotNull Document document,
@NotNull final PsiFile file,
@NotNull FileElement oldFileNode) {
if (oldFileNode.getTextLength() != document.getTextLength()) {
final String documentText = document.getText();
String fileText = file.getText();
boolean sameText = Comparing.equal(fileText, documentText);
LOG.error("commitDocument() left PSI inconsistent: " + DebugUtil.diagnosePsiDocumentInconsistency(file, document) +
"; node.length=" + oldFileNode.getTextLength() +
"; doc.text" + (sameText ? "==" : "!=") + "file.text",
new Attachment("file psi text", fileText),
new Attachment("old text", documentText));
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
try {
BlockSupport blockSupport = BlockSupport.getInstance(file.getProject());
final DiffLog diffLog = blockSupport.reparseRange(file, file.getNode(), new TextRange(0, documentText.length()), documentText, createProgressIndicator(),
oldFileNode.getText());
doActualPsiChange(file, diffLog);
if (oldFileNode.getTextLength() != document.getTextLength()) {
LOG.error("PSI is broken beyond repair in: " + file);
}
}
finally {
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null);
}
}
}
public void log(Project project, @NonNls String msg, @Nullable CommitTask task, @NonNls Object... args) {
}
@NotNull
protected ProgressIndicator createProgressIndicator() {
return new EmptyProgressIndicator();
}
public interface DocumentCommitProcessor {
void commitSynchronously(@NotNull Document document, @NotNull Project project, @NotNull PsiFile psiFile);
void commitAsynchronously(@NotNull final Project project,
@NotNull final Document document,
@NonNls @NotNull Object reason,
@NotNull ModalityState currentModalityState);
}
@@ -16,6 +16,7 @@
package com.intellij.psi.impl;
import com.intellij.diagnostic.ThreadDumper;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationAdapter;
@@ -23,8 +24,10 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -32,10 +35,23 @@ import com.intellij.openapi.progress.util.StandardProgressIndicatorBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.PomManager;
import com.intellij.pom.PomModel;
import com.intellij.pom.event.PomModelEvent;
import com.intellij.pom.impl.PomTransactionBase;
import com.intellij.pom.tree.TreeAspect;
import com.intellij.pom.tree.TreeAspectEvent;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLock;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.text.DiffLog;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.ForeignLeafPsiElement;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.text.BlockSupport;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
@@ -60,7 +76,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class DocumentCommitThread extends DocumentCommitProcessor implements Runnable, Disposable {
public class DocumentCommitThread implements Runnable, Disposable, DocumentCommitProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread");
private final ExecutorService executor = new BoundedTaskExecutor(PooledThreadExecutor.INSTANCE, 1, this);
@@ -74,7 +90,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
private int runningWriteActions; // accessed in EDT only
public static DocumentCommitThread getInstance() {
return ServiceManager.getService(DocumentCommitThread.class);
return (DocumentCommitThread)ServiceManager.getService(DocumentCommitProcessor.class);
}
public DocumentCommitThread(final ApplicationEx application) {
myApplication = application;
@@ -158,13 +174,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
@NotNull final Document document,
@NonNls @NotNull Object reason,
@NotNull ModalityState currentModalityState) {
queueCommit(project, document, reason, currentModalityState);
}
void queueCommit(@NotNull final Project project,
@NotNull final Document document,
@NonNls @NotNull Object reason,
@NotNull ModalityState currentModalityState) {
assert !isDisposed : "already disposed";
if (!project.isInitialized()) return;
@@ -213,7 +222,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
final StringBuilder log = new StringBuilder();
@SuppressWarnings({"NonConstantStringShouldBeStringBuffer", "StringConcatenationInLoop"})
@Override
public void log(Project project, @NonNls String msg, @Nullable CommitTask task, @NonNls Object... args) {
if (true) return;
@@ -486,7 +494,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
@NotNull
@Override
protected ProgressIndicator createProgressIndicator() {
return new StandardProgressIndicatorBase();
}
@@ -589,7 +596,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
else {
// add document back to the queue
queueCommit(project, document, "Re-added back", task.myCreationModalityState);
commitAsynchronously(project, document, "Re-added back", task.myCreationModalityState);
}
}
catch (Error e) {
@@ -637,4 +644,247 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
((BoundedTaskExecutor)executor).waitAllTasksExecuted(100, TimeUnit.SECONDS);
UIUtil.dispatchAllInvocationEvents();
}
private static class CommitTask {
static final Key<Object> CANCEL_REASON = Key.create("CANCEL_REASON");
@NotNull final Document document;
@NotNull final Project project;
private final int modificationSequence; // store initial document modification sequence here to check if it changed later before commit in EDT
// when queued it's not started
// when dequeued it's started
// when failed it's canceled
@NotNull final ProgressIndicator indicator; // progress to commit this doc under.
@NotNull final Object reason;
@NotNull final ModalityState myCreationModalityState;
private final CharSequence myLastCommittedText;
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> myOldFileNodes;
protected CommitTask(@NotNull final Project project,
@NotNull final Document document,
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
@NotNull ProgressIndicator indicator,
@NotNull Object reason,
@NotNull ModalityState currentModalityState) {
this.document = document;
this.project = project;
this.indicator = indicator;
this.reason = reason;
myCreationModalityState = currentModalityState;
myLastCommittedText = PsiDocumentManager.getInstance(project).getLastCommittedText(document);
myOldFileNodes = oldFileNodes;
modificationSequence = ((DocumentEx)document).getModificationSequence();
}
@NonNls
@Override
public String toString() {
return "Doc: " + document + " (\"" + StringUtil.first(document.getImmutableCharSequence(), 40, true).toString().replaceAll("\n", " ") + "\")"
+ (indicator.isCanceled() ? " (Canceled: " + ((UserDataHolder)indicator).getUserData(CANCEL_REASON) + ")":"")
+" Reason: " + reason
+ (isStillValid() ? "" : "; changed: old seq="+modificationSequence+", new seq="+ ((DocumentEx)document).getModificationSequence())
;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommitTask)) return false;
CommitTask task = (CommitTask)o;
return document.equals(task.document) && project.equals(task.project);
}
@Override
public int hashCode() {
int result = document.hashCode();
result = 31 * result + project.hashCode();
return result;
}
public boolean isStillValid() {
return ((DocumentEx)document).getModificationSequence() == modificationSequence;
}
private void cancel(@NotNull Object reason, @NotNull DocumentCommitThread commitProcessor) {
if (!indicator.isCanceled()) {
commitProcessor.log(project, "indicator cancel", this);
indicator.cancel();
((UserDataHolder)indicator).putUserData(CANCEL_REASON, reason);
}
}
}
// public for Upsource
@Nullable("returns runnable to execute under write action in AWT to finish the commit")
public Processor<Document> doCommit(@NotNull final CommitTask task,
@NotNull final PsiFile file,
@NotNull final FileASTNode oldFileNode) {
Document document = task.document;
final CharSequence newDocumentText = document.getImmutableCharSequence();
final TextRange changedPsiRange = getChangedPsiRange(file, task.myLastCommittedText, newDocumentText);
if (changedPsiRange == null) {
return null;
}
final Boolean data = document.getUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY);
if (data != null) {
document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null);
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, data);
}
BlockSupport blockSupport = BlockSupport.getInstance(file.getProject());
final DiffLog diffLog = blockSupport.reparseRange(file, oldFileNode, changedPsiRange, newDocumentText, task.indicator, task.myLastCommittedText);
return new Processor<Document>() {
@Override
public boolean process(Document document) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
if (!task.isStillValid() ||
((PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject())).getCachedViewProvider(document) != file.getViewProvider()) {
return false; // optimistic locking failed
}
doActualPsiChange(file, diffLog);
assertAfterCommit(document, file, (FileElement)oldFileNode);
return true;
}
};
}
private static int getLeafMatchingLength(CharSequence leafText, CharSequence pattern, int patternIndex, int finalPatternIndex, int direction) {
int leafIndex = direction == 1 ? 0 : leafText.length() - 1;
int finalLeafIndex = direction == 1 ? leafText.length() - 1 : 0;
int result = 0;
while (leafText.charAt(leafIndex) == pattern.charAt(patternIndex)) {
result++;
if (leafIndex == finalLeafIndex || patternIndex == finalPatternIndex) {
break;
}
leafIndex += direction;
patternIndex += direction;
}
return result;
}
private static int getMatchingLength(@NotNull FileElement treeElement, @NotNull CharSequence text, boolean fromStart) {
int patternIndex = fromStart ? 0 : text.length() - 1;
int finalPatternIndex = fromStart ? text.length() - 1 : 0;
int direction = fromStart ? 1 : -1;
ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false);
int result = 0;
while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) {
if (!(leaf instanceof ForeignLeafPsiElement)) {
CharSequence chars = leaf.getChars();
if (chars.length() > 0) {
int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction);
result += matchingLength;
if (matchingLength != chars.length()) {
break;
}
patternIndex += fromStart ? matchingLength : -matchingLength;
}
}
leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false);
}
return result;
}
@Nullable
public static TextRange getChangedPsiRange(@NotNull PsiFile file, @NotNull FileElement treeElement, @NotNull CharSequence newDocumentText) {
int psiLength = treeElement.getTextLength();
if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) {
return new TextRange(0, psiLength);
}
int commonPrefixLength = getMatchingLength(treeElement, newDocumentText, true);
if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == psiLength) {
return null;
}
int commonSuffixLength = Math.min(getMatchingLength(treeElement, newDocumentText, false), psiLength - commonPrefixLength);
return new TextRange(commonPrefixLength, psiLength - commonSuffixLength);
}
@Nullable
private static TextRange getChangedPsiRange(@NotNull PsiFile file,
@NotNull CharSequence oldDocumentText,
@NotNull CharSequence newDocumentText) {
int psiLength = oldDocumentText.length();
if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) {
return new TextRange(0, psiLength);
}
int commonPrefixLength = StringUtil.commonPrefixLength(oldDocumentText, newDocumentText);
if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == psiLength) {
return null;
}
int commonSuffixLength = Math.min(StringUtil.commonSuffixLength(oldDocumentText, newDocumentText), psiLength - commonPrefixLength);
return new TextRange(commonPrefixLength, psiLength - commonSuffixLength);
}
public static void doActualPsiChange(@NotNull final PsiFile file, @NotNull final DiffLog diffLog) {
CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() {
@Override
public void run() {
synchronized (PsiLock.LOCK) {
file.getViewProvider().beforeContentsSynchronized();
final Document document = file.getViewProvider().getDocument();
PsiDocumentManagerBase documentManager = (PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject());
PsiToDocumentSynchronizer.DocumentChangeTransaction transaction = documentManager.getSynchronizer().getTransaction(document);
final PsiFileImpl fileImpl = (PsiFileImpl)file;
if (transaction == null) {
final PomModel model = PomManager.getModel(fileImpl.getProject());
model.runTransaction(new PomTransactionBase(fileImpl, model.getModelAspect(TreeAspect.class)) {
@Override
public PomModelEvent runInner() {
return new TreeAspectEvent(model, diffLog.performActualPsiChange(file));
}
});
}
else {
diffLog.performActualPsiChange(file);
}
}
}
});
}
private void assertAfterCommit(@NotNull Document document, @NotNull final PsiFile file, @NotNull FileElement oldFileNode) {
if (oldFileNode.getTextLength() != document.getTextLength()) {
final String documentText = document.getText();
String fileText = file.getText();
boolean sameText = Comparing.equal(fileText, documentText);
LOG.error("commitDocument() left PSI inconsistent: " + DebugUtil.diagnosePsiDocumentInconsistency(file, document) +
"; node.length=" + oldFileNode.getTextLength() +
"; doc.text" + (sameText ? "==" : "!=") + "file.text",
new Attachment("file psi text", fileText),
new Attachment("old text", documentText));
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
try {
BlockSupport blockSupport = BlockSupport.getInstance(file.getProject());
final DiffLog diffLog = blockSupport.reparseRange(file, file.getNode(), new TextRange(0, documentText.length()), documentText, createProgressIndicator(),
oldFileNode.getText());
doActualPsiChange(file, diffLog);
if (oldFileNode.getTextLength() != document.getTextLength()) {
LOG.error("PSI is broken beyond repair in: " + file);
}
}
finally {
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null);
}
}
}
}
@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SyntheticFileSystemItem extends PsiElementBase implements PsiFileSystemItem {
public static final Logger LOG = Logger.getInstance("#" + SyntheticFileSystemItem.class.getPackage().getName());
private static final Logger LOG = Logger.getInstance("#" + SyntheticFileSystemItem.class.getPackage().getName());
protected final Project myProject;
protected final PsiManager myManager;
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
import com.intellij.openapi.vfs.VirtualFile;
@@ -49,7 +50,7 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp
protected final JPanel myPanel;
protected final JCheckBox myAmend;
@Nullable private String myPreviousMessage;
@Nullable private final String myPreviousMessage;
@Nullable private String myAmendedMessage;
@NotNull protected final CheckinProjectPanel myCheckinPanel;
@Nullable private Map<VirtualFile, String> myMessagesForRoots;
@@ -140,8 +141,8 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp
}
private void substituteCommitMessage(@NotNull String newMessage) {
myPreviousMessage = myCheckinPanel.getCommitMessage();
if (!myPreviousMessage.trim().equals(newMessage.trim())) {
VcsConfiguration.getInstance(myCheckinPanel.getProject()).saveCommitMessage(myPreviousMessage);
myCheckinPanel.setCommitMessage(newMessage);
}
}
@@ -606,7 +606,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
Element element = new Element(OPTION_ELEMENT);
element.setAttribute(NAME_ATTR, key.getExternalName());
if (baseKey != null && value.isFallbackEnabled()) {
if (defaultFallbackAttr != null && defaultAttr != null && defaultAttr != defaultFallbackAttr) {
if (isParentOverwritingInheritance(key)) {
element.setAttribute(BASE_ATTRIBUTES_ATTR, baseKey.getExternalName());
attrElements.addContent(element);
}
@@ -622,6 +622,15 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
}
}
private boolean isParentOverwritingInheritance(@NotNull TextAttributesKey key) {
TextAttributes parentAttrs =
myParentScheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key) : null;
if (parentAttrs != null) {
return !parentAttrs.isFallbackEnabled();
}
return false;
}
protected Color getOwnColor(ColorKey key) {
return myColorsMap.get(key);
}
@@ -73,6 +73,10 @@ public abstract class GutterIconDescriptor {
myIcon = icon;
}
public boolean isEnabled() {
return LineMarkerSettings.getSettings().isEnabled(this);
}
@Nullable
@Override
public Icon getIcon() {
@@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntArrayList;
@@ -107,6 +108,12 @@ public class PathEditor {
public JComponent createComponent() {
myList = new JBList(getListModel());
myList.setCellRenderer(createListCellRenderer(myList));
TreeUIHelper.getInstance().installListSpeedSearch(myList, new Convertor<Object, String>() {
@Override
public String convert(Object file) {
return ((VirtualFile)file).getPresentableUrl();
}
});
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myList)
.disableUpDownActions()
@@ -32,10 +32,12 @@ import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
@@ -80,6 +82,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr
};
MultiMap<PluginDescriptor, LanguageExtensionPoint<LineMarkerProvider>> map = ContainerUtil.groupBy(Arrays.asList(extensions), function);
Map<GutterIconDescriptor, PluginDescriptor> pluginDescriptorMap = ContainerUtil.newHashMap();
Set<String> ids = new HashSet<>();
myDescriptors = new ArrayList<GutterIconDescriptor>();
for (final PluginDescriptor descriptor : map.keySet()) {
Collection<LanguageExtensionPoint<LineMarkerProvider>> points = map.get(descriptor);
@@ -87,16 +90,21 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr
GutterIconDescriptor instance = (GutterIconDescriptor)extensionPoint.getInstance();
if (instance.getOptions().length > 0) {
for (GutterIconDescriptor option : instance.getOptions()) {
myDescriptors.add(option);
if (ids.add(option.getId())) {
myDescriptors.add(option);
}
pluginDescriptorMap.put(option, descriptor);
}
}
else {
myDescriptors.add(instance);
if (ids.add(instance.getId())) {
myDescriptors.add(instance);
}
pluginDescriptorMap.put(instance, descriptor);
}
}
}
/*
List<GutterIconDescriptor> options = new ArrayList<GutterIconDescriptor>();
for (Iterator<GutterIconDescriptor> iterator = myDescriptors.iterator(); iterator.hasNext(); ) {
GutterIconDescriptor descriptor = iterator.next();
@@ -106,6 +114,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr
}
}
myDescriptors.addAll(options);
*/
myDescriptors.sort(new Comparator<GutterIconDescriptor>() {
@Override
public int compare(GutterIconDescriptor o1, GutterIconDescriptor o2) {
@@ -203,4 +212,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr
};
myList.setBorder(BorderFactory.createEmptyBorder());
}
@TestOnly
public List<GutterIconDescriptor> getDescriptors() { return myDescriptors; }
}
@@ -60,6 +60,7 @@ import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.ReferenceRange;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.LightweightHint;
import com.intellij.util.Alarm;
import com.intellij.util.ObjectUtils;
@@ -76,7 +77,6 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
@@ -129,7 +129,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
private volatile boolean myHasPsiElements;
private boolean myLookupUpdated;
private final ConcurrentMap<LookupElement, CompletionSorterImpl> myItemSorters =
ContainerUtil.createConcurrentWeakMap(ContainerUtil.<LookupElement>identityStrategy());
ContainerUtil.createConcurrentWeakMap(ContainerUtil.identityStrategy());
private final PropertyChangeListener myLookupManagerListener;
private final Queue<Runnable> myAdvertiserChanges = new ConcurrentLinkedQueue<Runnable>();
private final List<CompletionResult> myDelayedMiddleMatches = ContainerUtil.newArrayList();
@@ -152,24 +152,16 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
myLookup = lookup;
myStartCaret = myEditor.getCaretModel().getOffset();
myAdvertiserChanges.offer(new Runnable() {
@Override
public void run() {
myLookup.getAdvertiser().clearAdvertisements();
}
});
myAdvertiserChanges.offer(() -> myLookup.getAdvertiser().clearAdvertisements());
myLookup.setArranger(new CompletionLookupArranger(parameters, this));
myLookup.addLookupListener(myLookupListener);
myLookup.setCalculating(true);
myLookupManagerListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() != null) {
LOG.error("An attempt to change the lookup during completion, phase = " + CompletionServiceImpl.getCompletionPhase());
}
myLookupManagerListener = evt -> {
if (evt.getNewValue() != null) {
LOG.error("An attempt to change the lookup during completion, phase = " + CompletionServiceImpl.getCompletionPhase());
}
};
LookupManager.getInstance(getProject()).addPropertyChangeListener(myLookupManagerListener);
@@ -508,43 +500,40 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
myQueue.cancelAllUpdates();
myFreezeSemaphore.up();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (!(phase instanceof CompletionPhase.BgCalculation) || phase.indicator != CompletionProgressIndicator.this) return;
GuiUtils.invokeLaterIfNeeded(() -> {
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
if (!(phase instanceof CompletionPhase.BgCalculation) || phase.indicator != this) return;
LOG.assertTrue(!getProject().isDisposed(), "project disposed");
LOG.assertTrue(!getProject().isDisposed(), "project disposed");
if (myEditor.isDisposed()) {
myLookup.hideLookup(false);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return;
}
if (myEditor.isDisposed()) {
myLookup.hideLookup(false);
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return;
}
if (myEditor instanceof EditorWindow) {
LOG.assertTrue(((EditorWindow)myEditor).getInjectedFile().isValid(), "injected file !valid");
LOG.assertTrue(((DocumentWindow)myEditor.getDocument()).isValid(), "docWindow !valid");
}
PsiFile file = myLookup.getPsiFile();
LOG.assertTrue(file == null || file.isValid(), "file !valid");
if (myEditor instanceof EditorWindow) {
LOG.assertTrue(((EditorWindow)myEditor).getInjectedFile().isValid(), "injected file !valid");
LOG.assertTrue(((DocumentWindow)myEditor.getDocument()).isValid(), "docWindow !valid");
}
PsiFile file = myLookup.getPsiFile();
LOG.assertTrue(file == null || file.isValid(), "file !valid");
myLookup.setCalculating(false);
myLookup.setCalculating(false);
if (myCount == 0) {
myLookup.hideLookup(false);
if (!isAutopopupCompletion()) {
final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
LOG.assertTrue(current == null, current + "!=" + CompletionProgressIndicator.this);
if (myCount == 0) {
myLookup.hideLookup(false);
if (!isAutopopupCompletion()) {
final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
LOG.assertTrue(current == null, current + "!=" + this);
handleEmptyLookup(!((CompletionPhase.BgCalculation)phase).modifiersChanged);
}
}
else {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(CompletionProgressIndicator.this));
updateLookup();
handleEmptyLookup(!((CompletionPhase.BgCalculation)phase).modifiersChanged);
}
}
else {
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(this));
updateLookup();
}
}, myQueue.getModalityState());
}
@@ -740,12 +729,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
private static LightweightHint showErrorHint(Project project, Editor editor, String text) {
final LightweightHint[] result = {null};
final EditorHintListener listener = new EditorHintListener() {
@Override
public void hintShown(final Project project, final LightweightHint hint, final int flags) {
result[0] = hint;
}
};
final EditorHintListener listener = (project1, hint, flags) -> result[0] = hint;
final MessageBusConnection connection = project.getMessageBus().connect();
connection.subscribe(EditorHintListener.TOPIC, listener);
assert text != null;
@@ -774,12 +758,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
boolean sync = ApplicationManager.getApplication().isUnitTestMode() && !CompletionAutoPopupHandler.ourTestingAutopopup;
final CompletionThreading strategy = sync ? new SyncCompletion() : new AsyncCompletion();
strategy.startThread(ProgressWrapper.wrap(this), new Runnable() {
@Override
public void run() {
scheduleAdvertising();
}
});
strategy.startThread(ProgressWrapper.wrap(this), this::scheduleAdvertising);
final WeighingDelegate weigher = strategy.delegateWeighing(this);
class CalculateItems implements Runnable {
@@ -812,12 +791,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
}
public void addAdvertisement(@NotNull final String text, @Nullable final Color bgColor) {
myAdvertiserChanges.offer(new Runnable() {
@Override
public void run() {
myLookup.addAdvertisement(text, bgColor);
}
});
myAdvertiserChanges.offer(() -> myLookup.addAdvertisement(text, bgColor));
myQueue.queue(myUpdate);
}
@@ -59,6 +59,7 @@ import com.intellij.util.Consumer;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -626,7 +627,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
EditorColorsScheme scheme = colorsManager.getGlobalScheme();
StyleConstants.setFontSize(myFontSizeStyle, scheme.getQuickDocFontSize().getSize());
StyleConstants.setFontSize(myFontSizeStyle, JBUI.scale(scheme.getQuickDocFontSize().getSize()));
if (Registry.is("documentation.component.editor.font")) {
StyleConstants.setFontFamily(myFontSizeStyle, scheme.getEditorFontName());
}
@@ -93,7 +93,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
private final NotNullLazyValue<ContentManager> myContentManager;
private InspectionResultsView myView;
private Content myContent;
private volatile boolean myUseView;
private volatile boolean myViewClosed = true;
@NotNull
private AnalysisUIOptions myUIOptions;
@@ -319,7 +319,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
if (!ApplicationManager.getApplication().isUnitTestMode()) {
myUIOptions = AnalysisUIOptions.getInstance(getProject()).copy();
}
myUseView = true;
myViewClosed = false;
super.launchInspections(scope);
}
@@ -589,7 +589,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
if (virtualFile == null) return null;
if (isBinary(file)) return null; //do not inspect binary files
if (!myUseView && !headlessEnvironment) {
if (myViewClosed && !headlessEnvironment) {
throw new ProcessCanceledException();
}
@@ -785,7 +785,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final ContentManager contentManager = getContentManager();
contentManager.removeContent(myContent, true);
}
myUseView = false;
myViewClosed = true;
myView = null;
super.close(noSuspisiousCodeFound);
}
@@ -977,7 +977,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
return file instanceof PsiBinaryFile || file.getFileType().isBinary();
}
public boolean useView() {
return myUseView;
public boolean isViewClosed() {
return myViewClosed;
}
}
@@ -329,7 +329,8 @@ public abstract class InspectionRVContentProvider {
}
}
else if (current instanceof RefElementNode) {
if (((RefElementNode)current).getElement().getName().compareTo(((RefElementNode)child).getElement().getName()) == 0) {
if (((RefElementNode)current).getElement().getName().compareTo(((RefElementNode)child).getElement().getName()) == 0 &&
((RefElementNode)current).getElement().getQualifiedName().compareTo(((RefElementNode)child).getElement().getQualifiedName()) == 0) {
processDepth(model, child, current);
return;
}
@@ -46,6 +46,9 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.*;
/**
@@ -170,6 +173,15 @@ public class QuickFixAction extends AnAction {
}, templatePresentationText, null);
refreshViews(project, ignoredElements, myToolWrapper);
final InspectionTree tree = context.getView().getTree();
final TreePath[] selected = tree.getSelectionPaths();
if (selected != null) {
for (TreePath path : selected) {
path.getLastPathComponent();
((DefaultTreeModel) tree.getModel()).reload((TreeNode)path.getLastPathComponent());
}
}
tree.restoreExpansionAndSelection();
}
finally { //to make offline view lazy
if (initial) refManager.inspectionReadActionStarted();
@@ -222,7 +222,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
}
final GlobalInspectionContextImpl context = getContext();
if (!context.useView() || !(refElement instanceof RefElement)) {
if (context.isViewClosed() || !(refElement instanceof RefElement)) {
return;
}
if (myToolWrapper instanceof LocalInspectionToolWrapper) {
@@ -393,24 +393,34 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
if (descriptors != null) {
ArrayList<CommonProblemDescriptor> newDescriptors = new ArrayList<CommonProblemDescriptor>(Arrays.asList(descriptors));
newDescriptors.remove(problem);
CommonProblemDescriptor[] newDescriptorsAsArray = newDescriptors.toArray(new CommonProblemDescriptor[newDescriptors.size()]);
getQuickFixActions().put(refEntity, null);
if (!newDescriptors.isEmpty()) {
problemElements.put(refEntity, newDescriptors.toArray(new CommonProblemDescriptor[newDescriptors.size()]));
problemElements.put(refEntity, newDescriptorsAsArray);
for (CommonProblemDescriptor descriptor : newDescriptors) {
collectQuickFixes(descriptor.getFixes(), refEntity);
}
}
else {
ignoreProblemElement(refEntity);
}
ignoreProblemElement(refEntity, newDescriptorsAsArray, problem);
}
}
}
}
private void ignoreProblemElement(RefEntity refEntity){
final CommonProblemDescriptor[] problemDescriptors = getProblemElements().remove(refEntity);
getIgnoredElements().put(refEntity, problemDescriptors);
private void ignoreProblemElement(RefEntity refEntity, CommonProblemDescriptor[] newDescriptors, CommonProblemDescriptor toIgnore){
if (newDescriptors != null && newDescriptors.length == 0) {
newDescriptors = null;
}
if (newDescriptors == null) {
getProblemElements().remove(refEntity);
} else {
getProblemElements().put(refEntity, newDescriptors);
}
CommonProblemDescriptor[] oldIgnored = getIgnoredElements().getOrDefault(refEntity, CommonProblemDescriptor.EMPTY_ARRAY);
CommonProblemDescriptor[] update = new CommonProblemDescriptor[oldIgnored.length + 1];
System.arraycopy(oldIgnored, 0, update, 0, oldIgnored.length);
update[update.length - 1] = toIgnore;
getIgnoredElements().put(refEntity, update);
}
@Override
@@ -594,7 +604,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
myModulesProblems.add((RefModule)element);
}
else {
String groupName = element instanceof RefElement ? element.getRefManager().getGroupName((RefElement)element) : null;
String groupName = element instanceof RefElement ? element.getRefManager().getGroupName((RefElement)element) : element.getQualifiedName() ;
Set<RefEntity> content = myContents.get(groupName);
if (content == null) {
content = new HashSet<RefEntity>();
@@ -733,6 +743,11 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
public boolean isElementIgnored(final RefEntity element) {
for (RefEntity entity : getIgnoredElements().keySet()) {
if (Comparing.equal(entity, element)) {
for (RefEntity entity1 : getProblemElements().keySet()) {
if (Comparing.equal(entity1, element)) {
return false;
}
}
return true;
}
}
@@ -46,7 +46,7 @@ public class InspectionNodeInfo extends JPanel {
public InspectionNodeInfo(final InspectionToolWrapper toolWrapper, Project project) {
setLayout(new GridBagLayout());
setBorder(IdeBorderFactory.createEmptyBorder(5, 3, 0, 0));
setBorder(IdeBorderFactory.createEmptyBorder(5, 12, 0, 0));
myProject = project;
myTitle = new SimpleColoredComponent();
myCurrentProfile = (InspectionProfileImpl)InspectionProjectProfileManager.getInstance(project).getProjectProfileImpl();
@@ -55,7 +55,7 @@ public class InspectionNodeInfo extends JPanel {
myButton = new JButton();
add(myTitle,
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new JBInsets(0, 2, 0, 0),
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0),
0, 0));
JEditorPane description = new JEditorPane();
@@ -64,14 +64,14 @@ public class InspectionNodeInfo extends JPanel {
description.setOpaque(false);
description.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
final String toolDescription = toolWrapper.loadDescription();
SingleInspectionProfilePanel.readHTML(description, SingleInspectionProfilePanel.toHTML(description, toolDescription == null ? "" : toolDescription, true));
SingleInspectionProfilePanel.readHTML(description, SingleInspectionProfilePanel.toHTML(description, toolDescription == null ? "" : toolDescription, false));
add(ScrollPaneFactory.createScrollPane(description, true),
new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
new JBInsets(5, 5, 0, 0), 0, 0));
new Insets(0, 0, 0, 0), 0, 0));
add(myButton,
new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new JBInsets(15, 0, 0, 0), 0, 0));
new Insets(15, 0, 0, 0), 0, 0));
updateEnableButtonText(false);
new ClickListener() {
@@ -99,9 +99,9 @@ public class InspectionNodeInfo extends JPanel {
}
myButton.setText((isEnabled ? "Disable" : "Enable") + " inspection");
myTitle.clear();
myTitle.append(myName, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
myTitle.append(myName + " inspection", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
if (!isEnabled) {
myTitle.append(" Disabled", SimpleTextAttributes.GRAYED_ATTRIBUTES);
myTitle.append(" Disabled", SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
}
}
@@ -90,7 +90,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
private static final Logger LOG = Logger.getInstance(InspectionResultsView.class);
public static final DataKey<InspectionResultsView> DATA_KEY = DataKey.create("inspectionView");
private static final Key<Boolean> PREVIEW_EDITOR_IS_REUSED_KEY = Key.create("inspection.tool.window.preview.editor.is.reused.");
private static final Key<Boolean> PREVIEW_EDITOR_IS_REUSED_KEY = Key.create("inspection.tool.window.preview.editor.is.reused");
private final Project myProject;
private final InspectionTree myTree;
@@ -627,7 +627,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
severityGroupNode = ConcurrencyUtil.cacheOrGet(mySeverityGroupNodes, level, newNode);
if (severityGroupNode == newNode) {
InspectionTreeNode root = myTree.getRoot();
insertByIndex(root, severityGroupNode);
insertByIndex(severityGroupNode, root);
}
}
return severityGroupNode;
@@ -80,7 +80,11 @@ public class InspectionResultsViewComparator implements Comparator {
if (node2 instanceof InspectionModuleNode) return 1;
if (node1 instanceof InspectionPackageNode && node2 instanceof InspectionPackageNode) {
return ((InspectionPackageNode)node1).getPackageName().compareToIgnoreCase(((InspectionPackageNode)node2).getPackageName());
final int nonQualified = ((InspectionPackageNode)node1).getPackageName().compareToIgnoreCase(((InspectionPackageNode)node2).getPackageName());
if (nonQualified != 0) {
return nonQualified;
}
return nonQualified;
}
if (node1 instanceof InspectionPackageNode) return -1;
if (node2 instanceof InspectionPackageNode) return 1;
@@ -159,10 +163,17 @@ public class InspectionResultsViewComparator implements Comparator {
private static int compareEntities(final RefEntity entity1, final RefEntity entity2) {
if (entity1 instanceof RefElement && entity2 instanceof RefElement) {
return PsiUtilCore.compareElementsByPosition(((RefElement)entity1).getElement(), ((RefElement)entity2).getElement());
final int positionComparing = PsiUtilCore.compareElementsByPosition(((RefElement)entity1).getElement(), ((RefElement)entity2).getElement());
if (positionComparing != 0) {
return positionComparing;
}
}
if (entity1 != null && entity2 != null) {
return entity1.getName().compareToIgnoreCase(entity2.getName());
final int nameComparing = entity1.getName().compareToIgnoreCase(entity2.getName());
if (nameComparing != 0) {
return nameComparing;
}
return entity1.getQualifiedName().compareToIgnoreCase(entity2.getQualifiedName());
}
if (entity1 != null) return -1;
return entity2 != null ? 1 : 0;
@@ -31,7 +31,9 @@ import com.intellij.ui.ClickListener;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +41,7 @@ import javax.swing.*;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.function.Supplier;
/**
@@ -57,7 +60,7 @@ public class QuickFixToolbar extends JPanel {
final boolean multipleDescriptors = problemCount > 1;
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
setBorder(IdeBorderFactory.createEmptyBorder(hasFixes ? 0 : 5, 5, 0, 0));
setBorder(IdeBorderFactory.createEmptyBorder(7 + (hasFixes ? 0 : 5), hasFixes ? 12 : 9, hasFixes ? 0 : 6, 0));
fill(multipleDescriptors, () -> getLabel(fixes, tree.getSelectionCount() == 1 ? (InspectionTreeNode)tree.getSelectionPath().getLastPathComponent() : null, problemCount), this);
fill(hasFixes, () -> createFixPanel(fixes, multipleDescriptors), this);
@@ -74,11 +77,11 @@ public class QuickFixToolbar extends JPanel {
label.append(problemsCount + " problems" +
(targetName == null ? "" : (" in " + targetName)) +
(problemsCount > 1 && (fixes != null && fixes.length == MAX_FIX_COUNT) ? " Fix all:" : "") +
(hasFixesNonIntersectedFixes ? ":" : "" ),
SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
(hasFixesNonIntersectedFixes ? ":" : "" ));
if (hasFixesNonIntersectedFixes) {
label.append(" select a single problem to see its quick fixes");
}
label.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 0, 2));
return label;
}
@@ -86,16 +89,18 @@ public class QuickFixToolbar extends JPanel {
@NotNull final TreePath[] paths,
@NotNull final Project project,
boolean multipleDescriptors) {
final AnAction[] suppressors = new SuppressActionWrapper(project, toolWrapper, paths).getChildren(null);
final ComboBoxAction action = new ComboBoxAction() {
{
getTemplatePresentation().setText(multipleDescriptors ? "Suppress All" : "Suppress");
getTemplatePresentation().setEnabledAndVisible(suppressors.length != 0);
}
@NotNull
@Override
protected DefaultActionGroup createPopupActionGroup(JComponent button) {
DefaultActionGroup group = new DefaultActionGroup();
group.addAll(new SuppressActionWrapper(project, toolWrapper, paths).getChildren(null));
group.addAll(suppressors);
return group;
}
};
@@ -77,7 +77,7 @@ public class RefElementNode extends InspectionTreeNode {
if (element == null || !element.isValid()) {
return InspectionsBundle.message("inspection.reference.invalid");
}
return element.getRefManager().getRefinedElement(element).getQualifiedName();
return element.getRefManager().getRefinedElement(element).getName();
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SystemProperties;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -132,14 +133,7 @@ public class ConsoleBuffer {
}
public static int getLegacyCycleBufferSize() {
String cycleBufferSizeProperty = System.getProperty("idea.cycle.buffer.size");
if (cycleBufferSizeProperty == null) return 1024 * 1024;
try {
return Integer.parseInt(cycleBufferSizeProperty) * 1024;
}
catch (NumberFormatException e) {
return 1024 * 1024;
}
return SystemProperties.getIntProperty("idea.cycle.buffer.size", 1024) * 1024;
}
public boolean isUseCyclicBuffer() {
@@ -85,7 +85,7 @@ public class RunContentBuilder extends RunTab {
}
initLogConsoles(profile, contentDescriptor, console);
}
myUi.getOptions().setLeftToolbar(createActionToolbar(contentDescriptor), ActionPlaces.UNKNOWN);
myUi.getOptions().setLeftToolbar(createActionToolbar(contentDescriptor), ActionPlaces.RUNNER_TOOLBAR);
if (profile instanceof RunConfigurationBase) {
if (console instanceof ObservableConsoleView && !ApplicationManager.getApplication().isUnitTestMode()) {
@@ -131,7 +131,7 @@ public class RunContentBuilder extends RunTab {
}
}
consoleContent.setActions(consoleActions, ActionPlaces.UNKNOWN, console.getComponent());
consoleContent.setActions(consoleActions, ActionPlaces.RUNNER_TOOLBAR, console.getComponent());
}
@NotNull
@@ -871,7 +871,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
final AnAction[] actions = groupToBuild.getChildren(null);
if (!Arrays.equals(actions, myContextActions.get(entry.getKey()))) {
ActionToolbar tb = myActionManager.createActionToolbar(myActionsPlace, groupToBuild, true);
String adjustedPlace = myActionsPlace == ActionPlaces.UNKNOWN ? ActionPlaces.TOOLBAR : myActionsPlace;
ActionToolbar tb = myActionManager.createActionToolbar(adjustedPlace, groupToBuild, true);
tb.getComponent().setBorder(null);
tb.setTargetComponent(contextComponent);
eachPlaceholder.setContent(tb.getComponent());
@@ -169,13 +169,13 @@ public abstract class LRUPopupBuilder<T> {
new BaseListPopupStep<T>(myTitle, combinedItems) {
@NotNull
@Override
public String getTextFor(@NotNull T t) {
return getPresentation(t).first;
public String getTextFor(T t) {
return t == null ? "" : getPresentation(t).first;
}
@Override
public Icon getIconFor(@NotNull T t) {
return getPresentation(t).second;
public Icon getIconFor(T t) {
return t == null ? null : getPresentation(t).second;
}
@Override
@@ -62,6 +62,4 @@ public abstract class RootDetector {
*/
@NotNull
public abstract Collection<VirtualFile> detectRoots(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator);
public static ExtensionPointName<RootDetector> JAVA_SOURCE_ROOT_DETECTOR = ExtensionPointName.create("com.intellij.library.javaSourceRootDetector");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -171,7 +171,7 @@ public class RegistryUi implements Disposable {
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(!myTable.isEditing() && myTable.getSelectedRow() >= 0);
e.getPresentation().setText("Revert to Default");
e.getPresentation().setIcon(AllIcons.General.Remove);
e.getPresentation().setIcon(AllIcons.General.Reset);
if (e.getPresentation().isEnabled()) {
final RegistryValue rv = myModel.getRegistryValue(myTable.getSelectedRow());
@@ -56,14 +56,14 @@ import java.util.List;
//todo listen & notifyListeners readonly events?
public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements SettingsSavingComponent {
private final DocumentCommitThread myDocumentCommitThread;
private final DocumentCommitProcessor myDocumentCommitThread;
private final boolean myUnitTestMode = ApplicationManager.getApplication().isUnitTestMode();
public PsiDocumentManagerImpl(@NotNull final Project project,
@NotNull PsiManager psiManager,
@NotNull EditorFactory editorFactory,
@NotNull MessageBus bus,
@NonNls @NotNull final DocumentCommitThread documentCommitThread) {
@NonNls @NotNull final DocumentCommitProcessor documentCommitThread) {
super(project, psiManager, bus, documentCommitThread);
myDocumentCommitThread = documentCommitThread;
editorFactory.getEventMulticaster().addDocumentListener(this, project);
@@ -71,19 +71,15 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
busConnection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
@Override
public void fileContentLoaded(@NotNull final VirtualFile virtualFile, @NotNull Document document) {
PsiFile psiFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@Override
public PsiFile compute() {
return myProject.isDisposed() || !virtualFile.isValid() ? null : getCachedPsiFile(virtualFile);
}
});
PsiFile psiFile = ApplicationManager.getApplication().runReadAction(
(Computable<PsiFile>)() -> myProject.isDisposed() || !virtualFile.isValid() ? null : getCachedPsiFile(virtualFile));
fireDocumentCreated(document, psiFile);
}
});
busConnection.subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
@Override
public void updateFinished(@NotNull Document doc) {
documentCommitThread.queueCommit(project, doc, "Bulk update finished", ApplicationManager.getApplication().getDefaultModalityState());
documentCommitThread.commitAsynchronously(project, doc, "Bulk update finished", ApplicationManager.getApplication().getDefaultModalityState());
}
});
}
@@ -161,15 +157,12 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
@Override
public void save() {
// Ensure all documents are committed on save so file content dependent indices, that use PSI to build have consistent content.
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
try {
commitAllDocuments();
}
catch (Exception e) {
LOG.error(e);
}
UIUtil.invokeLaterIfNeeded(() -> {
try {
commitAllDocuments();
}
catch (Exception e) {
LOG.error(e);
}
});
}
@@ -178,7 +171,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
@TestOnly
public void clearUncommittedDocuments() {
super.clearUncommittedDocuments();
myDocumentCommitThread.clearQueue();
((DocumentCommitThread)myDocumentCommitThread).clearQueue();
}
@NonNls
@@ -39,7 +39,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.DocumentCommitProcessor;
import com.intellij.psi.impl.DocumentCommitThread;
import com.intellij.psi.impl.PsiDocumentManagerBase;
import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
@@ -467,7 +467,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
try {
final DiffLog diffLog = BlockSupportImpl.mergeTrees(oldFile, oldFileNode, injectedNode, new DaemonProgressIndicator(),
oldFileNode.getText());
DocumentCommitProcessor.doActualPsiChange(oldFile, diffLog);
DocumentCommitThread.doActualPsiChange(oldFile, diffLog);
}
finally {
DebugUtil.finishPsiModification();
@@ -26,7 +26,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.DumbModePermission;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
@@ -188,7 +187,9 @@ public class SafeDeleteProcessor extends BaseRefactoringProcessor {
for (PsiElement element : myElements) {
for(SafeDeleteProcessorDelegate delegate: Extensions.getExtensions(SafeDeleteProcessorDelegate.EP_NAME)) {
if (delegate.handlesElement(element)) {
Collection<String> foundConflicts = delegate.findConflicts(element, myElements);
Collection<String> foundConflicts = delegate instanceof SafeDeleteProcessorDelegateBase
? ((SafeDeleteProcessorDelegateBase)delegate).findConflicts(element, myElements, usages)
: delegate.findConflicts(element, myElements);
if (foundConflicts != null) {
conflicts.addAll(foundConflicts);
}
@@ -42,4 +42,8 @@ public abstract class SafeDeleteProcessorDelegateBase implements SafeDeleteProce
public UsageView showUsages(UsageInfo[] usages, UsageViewPresentation presentation, UsageViewManager manager, PsiElement[] elements) {
return null;
}
public Collection<String> findConflicts(PsiElement element, PsiElement[] elements, UsageInfo[] usages) {
return findConflicts(element, elements);
}
}
@@ -15,9 +15,11 @@
*/
package com.intellij.openapi.actionSystem;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* Possible places in the IDEA user interface where an action can appear.
*/
@@ -25,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"HardCodedStringLiteral"})
public abstract class ActionPlaces {
public static final String UNKNOWN = "unknown";
public static final String TOOLBAR = "toolbar";
/**
* consider to use {@link #isMainMenuOrActionSearch(String)} instead
@@ -63,13 +66,13 @@ public abstract class ActionPlaces {
public static final String CALL_HIERARCHY_VIEW_TOOLBAR = "CallHierarchyViewToolbar";
public static final String J2EE_ATTRIBUTES_VIEW_POPUP = "J2EEAttributesViewPopup";
public static final String J2EE_VIEW_POPUP = "J2EEViewPopup";
public static final String RUNNER_TOOLBAR = "RunnerToolbar";
public static final String DEBUGGER_TOOLBAR = "DebuggerToolbar";
public static final String USAGE_VIEW_POPUP = "UsageViewPopup";
public static final String USAGE_VIEW_TOOLBAR = "UsageViewToolbar";
public static final String STRUCTURE_VIEW_POPUP = "StructureViewPopup";
public static final String STRUCTURE_VIEW_TOOLBAR = "StructureViewToolbar";
public static final String NAVIGATION_BAR_POPUP = "NavBar";
@Deprecated public static final String NAVIGATION_BAR = NAVIGATION_BAR_POPUP;
public static final String NAVIGATION_BAR_TOOLBAR = "NavBarToolbar";
public static final String TODO_VIEW_POPUP = "TodoViewPopup";
@@ -128,22 +131,25 @@ public abstract class ActionPlaces {
public static final String V8_HEAP_PROFILING_POPUP = "V8_HEAP_PROFILING_POPUP";
public static final String V8_HEAP_DIFF_PROFILING_POPUP = "V8_HEAP_DIFF_PROFILING_POPUP";
private static final String[] ourToolbarPlaces = {EDITOR_TOOLBAR, PROJECT_VIEW_TOOLBAR, TESTTREE_VIEW_TOOLBAR, MAIN_TOOLBAR,
private static final Set<String> ourToolbarPlaces = ContainerUtil.newHashSet(
EDITOR_TOOLBAR, PROJECT_VIEW_TOOLBAR, TESTTREE_VIEW_TOOLBAR, MAIN_TOOLBAR, TOOLBAR, RUNNER_TOOLBAR,
ANT_EXPLORER_TOOLBAR, ANT_MESSAGES_TOOLBAR, COMPILER_MESSAGES_TOOLBAR, TODO_VIEW_TOOLBAR, STRUCTURE_VIEW_TOOLBAR, USAGE_VIEW_TOOLBAR,
DEBUGGER_TOOLBAR, CALL_HIERARCHY_VIEW_TOOLBAR, METHOD_HIERARCHY_VIEW_TOOLBAR, TYPE_HIERARCHY_VIEW_TOOLBAR, JAVADOC_TOOLBAR,
FILE_HISTORY_TOOLBAR, FILEHISTORY_VIEW_TOOLBAR, LVCS_DIRECTORY_HISTORY_TOOLBAR, CHANGES_VIEW_TOOLBAR, PHING_EXPLORER_TOOLBAR,
PHING_MESSAGES_TOOLBAR, ANALYZE_STACKTRACE_PANEL_TOOLBAR};
PHING_MESSAGES_TOOLBAR, ANALYZE_STACKTRACE_PANEL_TOOLBAR
);
public static boolean isToolbarPlace(@NotNull String place) {
return ArrayUtil.find(ourToolbarPlaces, place) != -1;
return ourToolbarPlaces.contains(place);
}
public static boolean isMainMenuOrActionSearch(String place) {
return MAIN_MENU.equals(place) || ACTION_SEARCH.equals(place);
}
private static final String[] ourPopupPlaces = {EDITOR_POPUP, EDITOR_TAB_POPUP, COMMANDER_POPUP,
private static final Set<String> ourPopupPlaces = ContainerUtil.newHashSet(
EDITOR_POPUP, EDITOR_TAB_POPUP, COMMANDER_POPUP,
PROJECT_VIEW_POPUP, FAVORITES_VIEW_POPUP, SCOPE_VIEW_POPUP, TESTTREE_VIEW_POPUP, TESTSTATISTICS_VIEW_POPUP, TYPE_HIERARCHY_VIEW_POPUP,
METHOD_HIERARCHY_VIEW_POPUP, CALL_HIERARCHY_VIEW_POPUP, J2EE_ATTRIBUTES_VIEW_POPUP, J2EE_VIEW_POPUP, USAGE_VIEW_POPUP,
STRUCTURE_VIEW_POPUP, TODO_VIEW_POPUP, COMPILER_MESSAGES_POPUP, ANT_MESSAGES_POPUP, ANT_EXPLORER_POPUP, UPDATE_POPUP,
@@ -152,9 +158,9 @@ public abstract class ActionPlaces {
CREATE_EJB_POPUP, CHANGES_VIEW_POPUP, REMOTE_HOST_VIEW_POPUP, REMOTE_HOST_DIALOG_POPUP, TFS_TREE_POPUP,
ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION, PHING_EXPLORER_POPUP, NAVIGATION_BAR_POPUP, JS_BUILD_TOOL_POPUP, DIFF_TOOLBAR,
V8_CPU_PROFILING_POPUP, V8_HEAP_PROFILING_POPUP, V8_HEAP_PROFILING_POPUP
};
);
public static boolean isPopupPlace(@NotNull String place) {
return ArrayUtil.find(ourPopupPlaces, place) != -1;
return ourPopupPlaces.contains(place);
}
}
@@ -147,8 +147,9 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent
public ComboBoxButton(Presentation presentation) {
myPresentation = presentation;
setEnabled(myPresentation.isEnabled());
setModel(new MyButtonModel());
getModel().setEnabled(myPresentation.isEnabled());
setVisible(presentation.isVisible());
setHorizontalAlignment(LEFT);
setFocusable(false);
if (isSmallVariant()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,23 +18,22 @@ package com.intellij.openapi.ui;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.ui.Animator;
import javax.swing.*;
import java.awt.*;
/**
* @author Konstantin Bulenkov
*/
public class DialogEarthquakeShaker {
private JDialog myDialog;
private Window myWindow;
private Point myNaturalLocation;
private long myStartTime;
private DialogEarthquakeShaker(JDialog dialog) {
myDialog = dialog;
private DialogEarthquakeShaker(Window window) {
myWindow = window;
}
public void startShake() {
myNaturalLocation = myDialog.getLocation();
myNaturalLocation = myWindow.getLocation();
myStartTime = System.currentTimeMillis();
new Animator("EarthQuake", 10, 70, true) {
@Override
@@ -43,19 +42,19 @@ public class DialogEarthquakeShaker {
final double waveOffset = (elapsed % 70) / 70d;
final double angle = waveOffset * 2d * Math.PI;
final int shakenX = (int)((Math.sin(angle) * 10) + myNaturalLocation.x);
myDialog.setLocation(shakenX, myNaturalLocation.y);
myDialog.repaint();
myWindow.setLocation(shakenX, myNaturalLocation.y);
myWindow.repaint();
if (elapsed > 150) {
suspend();
myDialog.setLocation(myNaturalLocation);
myDialog.repaint();
myWindow.setLocation(myNaturalLocation);
myWindow.repaint();
Disposer.dispose(this);
}
}
}.resume();
}
public static void shake(JDialog dialog) {
new DialogEarthquakeShaker(dialog).startShake();
public static void shake(Window window) {
new DialogEarthquakeShaker(window).startShake();
}
}
@@ -139,7 +139,7 @@ public abstract class IdeFocusManager implements FocusRequestor {
public abstract Component getFocusOwner();
/**
* Runs runnable for whicj <code>DataContext</code> will no be computed from the current focus owner,
* Runs runnable for which <code>DataContext</code> will no be computed from the current focus owner,
* but used the given one
*/
public abstract void runOnOwnContext(@NotNull DataContext context, @NotNull Runnable runnable);
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.concurrency.EdtExecutorService;
import com.intellij.util.concurrency.QueueProcessor;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
@@ -52,8 +53,8 @@ public class Alarm implements Disposable {
private volatile boolean myDisposed;
private final List<Request> myRequests = new SmartList<Request>(); // guarded by LOCK
private final List<Request> myPendingRequests = new SmartList<Request>(); // guarded by LOCK
private final List<Request> myRequests = new SmartList<>(); // guarded by LOCK
private final List<Request> myPendingRequests = new SmartList<>(); // guarded by LOCK
private final ScheduledExecutorService myExecutorService;
@@ -68,7 +69,9 @@ public class Alarm implements Disposable {
myDisposed = true;
cancelAllRequests();
myExecutorService.shutdownNow();
if (myThreadToUse != ThreadToUse.SWING_THREAD) {
myExecutorService.shutdownNow();
}
}
}
@@ -123,7 +126,12 @@ public class Alarm implements Disposable {
public Alarm(@NotNull ThreadToUse threadToUse, @Nullable Disposable parentDisposable) {
myThreadToUse = threadToUse;
myExecutorService = // have to restrict the number of running tasks because otherwise the (implicit) contract of
myExecutorService = threadToUse == ThreadToUse.SWING_THREAD ?
// pass straight to EDT
EdtExecutorService.getScheduledExecutorInstance() :
// or pass to app pooled thread.
// have to restrict the number of running tasks because otherwise the (implicit) contract of
// "addRequests with the same delay are executed in order" will be broken
AppExecutorUtil.createBoundedScheduledExecutorService(1);
@@ -258,7 +266,7 @@ public class Alarm implements Disposable {
return;
}
requests = new SmartList<Pair<Request, Runnable>>();
requests = new SmartList<>();
for (Request request : myRequests) {
Runnable existingTask = request.cancel();
if (existingTask != null) {
@@ -280,7 +288,7 @@ public class Alarm implements Disposable {
void waitForAllExecuted(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
List<Request> requests;
synchronized (LOCK) {
requests = new ArrayList<Request>(myRequests);
requests = new ArrayList<>(myRequests);
}
for (Request request : requests) {
@@ -357,12 +365,9 @@ public class Alarm implements Disposable {
if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
//noinspection SSBasedInspection
EdtInvocationManager.getInstance().invokeLater(new Runnable() {
@Override
public void run() {
if (!myDisposed) {
QueueProcessor.runSafely(task);
}
EdtInvocationManager.getInstance().invokeLater(() -> {
if (!myDisposed) {
QueueProcessor.runSafely(task);
}
});
}
@@ -17,6 +17,11 @@ package com.intellij.execution.process;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
public class ProcessInfo {
@@ -24,6 +29,7 @@ public class ProcessInfo {
private final int myPid;
@NotNull private final String myCommandLine;
@NotNull private final Optional<String> myExecutablePath;
@NotNull private final String myExecutableName;
@NotNull private final String myArgs;
@@ -33,10 +39,23 @@ public class ProcessInfo {
@NotNull String args) {
myPid = pid;
myCommandLine = commandLine;
myExecutablePath = Optional.empty();
myExecutableName = executableName;
myArgs = args;
}
public ProcessInfo(int pid,
@NotNull String commandLine,
@NotNull String executableName,
@NotNull String args,
@Nullable String executablePath) {
myPid = pid;
myCommandLine = commandLine;
myExecutableName = executableName;
myExecutablePath = StringUtil.isNotEmpty(executablePath) ? Optional.of(executablePath) : Optional.empty();
myArgs = args;
}
public int getPid() {
return myPid;
}
@@ -51,6 +70,18 @@ public class ProcessInfo {
return myExecutableName;
}
@NotNull
public Optional<String> getExecutableCannonicalPath() {
return myExecutablePath.map(s -> {
try {
return new File(s).getCanonicalPath();
}
catch (IOException e) {
return s;
}
});
}
@NotNull
public String getExecutableDisplayName() {
return StringUtil.trimEnd(myExecutableName, ".exe", true);
@@ -90,7 +90,7 @@ public class ProcessListUtil {
ProcessOutput processOutput = ExecUtil.execAndGetOutput(new GeneralCommandLine(command));
int exitCode = processOutput.getExitCode();
if (exitCode != 0) {
LOG.error("Cannot get process list, 'ps' exited with code " + exitCode + ", stdout:\n"
LOG.error("Cannot get process list, 'ps' exited with code " + exitCode + ", stdout:\n"
+ processOutput.getStdout()
+ "\nstderr:\n"
+ processOutput.getStderr());
@@ -98,7 +98,7 @@ public class ProcessListUtil {
output = processOutput.getStdout();
}
catch (ExecutionException e) {
LOG.error("Cannot get process list", e);
LOG.error("Cannot get process list", e);
return null;
}
return parser.fun(output);
@@ -110,7 +110,7 @@ public class ProcessListUtil {
File[] processes = proc.listFiles();
if (processes == null) {
LOG.error("Cannot read /proc, not mounted?");
LOG.error("Cannot read /proc, not mounted?");
return null;
}
@@ -137,9 +137,22 @@ public class ProcessListUtil {
}
if (cmdline.isEmpty()) continue;
String executablePath = null;
try {
File exe = new File(each, "exe");
if (!exe.getAbsolutePath().equals(exe.getCanonicalPath())) {
executablePath = exe.getCanonicalPath();
}
}
catch (IOException e) {
// couldn't resolve symlink
}
result.add(new ProcessInfo(pid, StringUtil.join(cmdline, " "),
PathUtil.getFileName(cmdline.get(0)),
StringUtil.join(cmdline.subList(1, cmdline.size()), " ")
StringUtil.join(cmdline.subList(1, cmdline.size()), " "),
executablePath
));
}
return result;
@@ -192,7 +205,7 @@ public class ProcessListUtil {
String name = PathUtil.getFileName(command);
String args = each.commandLine.substring(command.length()).trim();
result.add(new ProcessInfo(each.pid, each.commandLine, name, args));
result.add(new ProcessInfo(each.pid, each.commandLine, name, args, command));
}
return result;
}
@@ -219,16 +232,21 @@ public class ProcessListUtil {
for (int i = 1; i < lines.length; i++) {
String line = lines[i];
int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1);
if (pid == -1) continue;
try {
int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1);
if (pid == -1) continue;
String state = line.substring(statStart, userStart).trim();
if (state.contains("Z")) continue; // zombie
String state = line.substring(statStart, userStart).trim();
if (state.contains("Z")) continue; // zombie
String user = line.substring(userStart, commandStart).trim();
String commandLine = line.substring(commandStart).trim();
String user = line.substring(userStart, commandStart).trim();
String commandLine = line.substring(commandStart).trim();
result.add(new MacProcessInfo(pid, commandLine, user, state));
result.add(new MacProcessInfo(pid, commandLine, user, state));
}
catch (Exception e) {
LOG.error("Can't parse line '" + line + "'", e);
}
}
return result;
}
@@ -249,7 +267,7 @@ public class ProcessListUtil {
@Nullable
static List<ProcessInfo> getProcessList_WindowsWMIC() {
return parseCommandOutput(Arrays.asList("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline"),
return parseCommandOutput(Arrays.asList("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline,ExecutablePath"),
new NullableFunction<String, List<ProcessInfo>>() {
@Nullable
@Override
@@ -272,12 +290,18 @@ public class ProcessListUtil {
int pidStart = header.indexOf("ProcessId");
if (pidStart == -1) return null;
int executablePathStart = header.indexOf("ExecutablePath");
if (executablePathStart == -1) return null;
for (int i = 1; i < lines.length; i++) {
String line = lines[i];
int pid = StringUtil.parseInt(line.substring(pidStart, line.length()).trim(), -1);
if (pid == -1 || pid == 0) continue;
String executablePath = line.substring(executablePathStart, pidStart).trim();
String name = line.substring(0, commandLineStart).trim();
if (name.isEmpty()) continue;
@@ -294,7 +318,7 @@ public class ProcessListUtil {
}
}
result.add(new ProcessInfo(pid, commandLine, name, args));
result.add(new ProcessInfo(pid, commandLine, name, args, executablePath));
}
return result;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,7 +69,6 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter {
public void initComponent() {
checkJvm();
checkIBus();
checkJAyatana();
startDiskSpaceMonitoring();
}
@@ -100,16 +99,6 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter {
}
}
@SuppressWarnings("SpellCheckingInspection")
private void checkJAyatana() {
if (SystemInfo.isXWindow) {
String originalOpts = System.getenv("_ORIGINAL_JAVA_TOOL_OPTIONS");
if (originalOpts != null && originalOpts.contains("jayatanaag.jar")) {
showNotification("ayatana.menu.warn.message");
}
}
}
private void showNotification(@PropertyKey(resourceBundle = "messages.IdeBundle") String key) {
final String ignoreKey = "ignore." + key;
boolean ignored = myProperties.isValueSet(ignoreKey);

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