Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2016-06-30 15:18:24 +03:00
304 changed files with 5489 additions and 4930 deletions
+2 -2
View File
@@ -1,8 +1,7 @@
<component name="libraryTable">
<library name="Mocks">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymockclassextension.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
@@ -10,6 +9,7 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
+2 -2
View File
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="pty4j">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7-src.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7.1-src.jar!/" />
</SOURCES>
</library>
</component>
+1 -1
View File
@@ -279,7 +279,7 @@ libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", vers
libraryLicense(name: "pockets", attachedTo: "python-helpers", version: "0.2.4", license: "BSD", url: "http://pockets.readthedocs.org/")
libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "https://github.com/google/protobuf/blob/master/LICENSE")
libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20131209", license: "New BSD License", url: "http://code.google.com/p/proxy-vole/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7.1", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "PureJavaComm", libraryName: "purejavacomm", version: "0.0.16", license: "BSD", url: "http://www.sparetimelabs.com/purejavacomm")
libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Relax NG Object Model", libraryName: "rngom-20051226-patched.jar", license: "MIT", url: "http://java.net/projects/rngom/", licenseUrl: "http://www.opensource.org/licenses/mit-license.php")
@@ -56,9 +56,15 @@ public class SdkSettingsStep extends ModuleWizardStep {
private final JPanel myJdkPanel;
public SdkSettingsStep(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkFilter) {
@NotNull Condition<SdkTypeId> sdkTypeIdFilter) {
this(settingsStep.getContext(), moduleBuilder, sdkFilter);
this(settingsStep, moduleBuilder, sdkTypeIdFilter, null);
}
public SdkSettingsStep(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkTypeIdFilter, @Nullable Condition<Sdk> sdkFilter) {
this(settingsStep.getContext(), moduleBuilder, sdkTypeIdFilter, sdkFilter);
if (!isEmpty()) {
settingsStep.addSettingsField(getSdkFieldLabel(settingsStep.getContext().getProject()), myJdkPanel);
}
@@ -66,7 +72,8 @@ public class SdkSettingsStep extends ModuleWizardStep {
public SdkSettingsStep(WizardContext context,
@NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkFilter) {
@NotNull Condition<SdkTypeId> sdkTypeIdFilter,
@Nullable Condition<Sdk> sdkFilter) {
myModuleBuilder = moduleBuilder;
myWizardContext = context;
@@ -74,7 +81,11 @@ public class SdkSettingsStep extends ModuleWizardStep {
Project project = myWizardContext.getProject();
myModel.reset(project);
myJdkComboBox = new JdkComboBox(myModel, sdkFilter, sdkFilter, false);
if (sdkFilter == null) {
sdkFilter = JdkComboBox.getSdkFilter(sdkTypeIdFilter);
}
myJdkComboBox = new JdkComboBox(myModel, sdkFilter, sdkTypeIdFilter, false);
myJdkPanel = new JPanel(new GridBagLayout());
final PropertiesComponent component = project == null ? PropertiesComponent.getInstance() : PropertiesComponent.getInstance(project);
@@ -91,7 +102,7 @@ public class SdkSettingsStep extends ModuleWizardStep {
}
});
Sdk sdk = getPreselectedSdk(project, component.getValue(selectedJdkProperty), sdkFilter);
Sdk sdk = getPreselectedSdk(project, component.getValue(selectedJdkProperty), sdkTypeIdFilter);
myJdkComboBox.setSelectedJdk(sdk);
JButton button = new JButton("Ne\u001Bw...");
@@ -103,7 +114,7 @@ public class SdkSettingsStep extends ModuleWizardStep {
myJdkPanel.add(myJdkComboBox, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, CENTER, HORIZONTAL, JBUI.emptyInsets(), 0, 0));
myJdkPanel.add(myJdkComboBox.getSetUpButton(), new GridBagConstraints(1, 0, 1, 1, 0, 0, WEST, NONE, JBUI.insetsLeft(4), 0, 0));
if (myJdkComboBox.getItemCount() == 0) {
SdkType type = ContainerUtil.find(SdkType.getAllTypes(), sdkFilter);
SdkType type = ContainerUtil.find(SdkType.getAllTypes(), sdkTypeIdFilter);
if (type != null && type.getDownloadSdkUrl() != null) {
HyperlinkLabel label = new HyperlinkLabel("Download " + type.getPresentableName());
label.setHyperlinkTarget(type.getDownloadSdkUrl());
@@ -55,7 +55,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
private static final Icon EMPTY_ICON = EmptyIcon.create(1, 16);
@Nullable
private final Condition<SdkTypeId> myFilter;
private final Condition<Sdk> myFilter;
@Nullable
private final Condition<SdkTypeId> myCreationFilter;
private JButton mySetUpButton;
@@ -66,11 +66,11 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel,
@Nullable Condition<SdkTypeId> filter) {
this(jdkModel, filter, filter, false);
this(jdkModel, getSdkFilter(filter), filter, false);
}
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel,
@Nullable Condition<SdkTypeId> filter,
@Nullable Condition<Sdk> filter,
@Nullable Condition<SdkTypeId> creationFilter,
boolean addSuggestedItems) {
super(new JdkComboBoxModel(jdkModel, filter, addSuggestedItems));
@@ -280,7 +280,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
List<Sdk> projectJdks = new ArrayList<Sdk>(projectJdksModel.getProjectSdks().values());
if (myFilter != null) {
projectJdks = ContainerUtil.filter(projectJdks, getSdkFilter(myFilter));
projectJdks = ContainerUtil.filter(projectJdks, myFilter);
}
Collections.sort(projectJdks, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
for (Sdk projectJdk : projectJdks) {
@@ -289,11 +289,11 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
private static class JdkComboBoxModel extends DefaultComboBoxModel {
public JdkComboBoxModel(final ProjectSdksModel jdksModel, @Nullable Condition<SdkTypeId> sdkFilter, boolean addSuggested) {
public JdkComboBoxModel(final ProjectSdksModel jdksModel, @Nullable Condition<Sdk> sdkFilter, boolean addSuggested) {
Sdk[] jdks = jdksModel.getSdks();
Arrays.sort(jdks, (s1, s2) -> s1.getName().compareToIgnoreCase(s2.getName()));
for (Sdk jdk : jdks) {
if (sdkFilter == null || sdkFilter.value(jdk.getSdkType())) {
if (sdkFilter == null || sdkFilter.value(jdk)) {
addElement(new JdkComboBoxItem(jdk));
}
}
@@ -302,10 +302,10 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
}
protected void addSuggestedItems(@Nullable Condition<SdkTypeId> sdkFilter, Sdk[] jdks) {
protected void addSuggestedItems(@Nullable Condition<Sdk> sdkFilter, Sdk[] jdks) {
SdkType[] types = SdkType.getAllTypes();
for (SdkType type : types) {
if (sdkFilter == null || sdkFilter.value(type) && ContainerUtil.find(jdks, sdk -> sdk.getSdkType() == type) == null) {
if (sdkFilter == null || ContainerUtil.find(jdks, sdkFilter) == null) {
String homePath = type.suggestHomePath();
if (homePath != null && type.isValidSdkHome(homePath)) {
addElement(new SuggestedJdkItem(type, homePath));
@@ -321,7 +321,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
}
private static Condition<Sdk> getSdkFilter(@Nullable final Condition<SdkTypeId> filter) {
public static Condition<Sdk> getSdkFilter(@Nullable final Condition<SdkTypeId> filter) {
return filter == null ? Conditions.<Sdk>alwaysTrue() : (Condition<Sdk>)sdk -> filter.value(sdk.getSdkType());
}
@@ -406,12 +406,6 @@ class PostHighlightingVisitor {
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
if (!myRefCountHolder.isReferenced(parameter) && !UnusedSymbolUtil.isImplicitUsage(myProject, parameter, progress)) {
//parameter is defined by functional interface
final PsiElement declarationScope = parameter.getDeclarationScope();
if (declarationScope instanceof PsiMethod &&
myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope, myLanguageLevel)) {
return null;
}
String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
return UnusedSymbolUtil.createUnusedSymbolInfo(identifier, message, myDeadCodeInfoType);
}
@@ -222,26 +222,6 @@ class RefCountHolder {
return usedStatus == Boolean.TRUE;
}
boolean isReferencedByMethodReference(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return false;
Collection<PsiReference> array;
synchronized (myLocalRefsMap) {
array = myLocalRefsMap.get(method);
}
if (!array.isEmpty()) {
for (PsiReference reference : array) {
final PsiElement element = reference.getElement();
if (element instanceof PsiMethodReferenceExpression) {
return true;
}
}
}
return false;
}
private static boolean isParameterUsedRecursively(@NotNull PsiElement element, @NotNull Collection<PsiReference> array) {
if (!(element instanceof PsiParameter)) return false;
PsiParameter parameter = (PsiParameter)element;
@@ -140,14 +140,6 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
return true;
}
PsiType inferenceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(inferredType);
PsiType existingMethodReturnType = method.getReturnType();
if (existingMethodReturnType == null ||
inferenceMethodReturnType != null &&
!PsiType.VOID.equals(inferenceMethodReturnType) && !TypeConversionUtil.isAssignable(existingMethodReturnType, inferenceMethodReturnType)) {
return true;
}
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(method, aClass);
final PsiCodeBlock body = method.getBody();
LOG.assertTrue(body != null);
@@ -81,9 +81,16 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
}
final PsiMethodCallExpression qualifierCall = getQualifierMethodCall(methodCall);
if (isCallOf(qualifierCall, CommonClassNames.JAVA_UTIL_COLLECTION, STREAM_METHOD, 0)) {
holder.registerProblem(methodCall, getCallChainRange(methodCall, qualifierCall),
"Collection.stream()." + name + "() can be replaced with Collection.forEach()",
FOR_EACH_METHOD.equals(name) ? new CollectionForEachFix() : new CollectionForEachOrderedFix());
String message = "Collection.stream()." + name + "() can be replaced with Collection.forEach()";
final LocalQuickFix fix;
if (FOR_EACH_METHOD.equals(name)) {
fix = new CollectionForEachFix();
}
else {
fix = new CollectionForEachOrderedFix();
message += " (may change semantics)";
}
holder.registerProblem(methodCall, getCallChainRange(methodCall, qualifierCall), message, fix);
}
}
}
@@ -221,7 +228,7 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
@NotNull
@Override
public String getFamilyName() {
return "Replace Collection.stream()." + FOR_EACH_ORDERED_METHOD + "() with Collection.forEach()";
return "Replace Collection.stream()." + FOR_EACH_ORDERED_METHOD + "() with Collection.forEach() (may change semantics)";
}
@Override
@@ -17,6 +17,7 @@ package com.intellij.codeInspection.reference;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -426,24 +427,19 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
@Override
public String getName() {
if (isValid()) {
final String[] result = new String[1];
final Runnable runnable = () -> {
return ReadAction.compute(() -> {
PsiMethod psiMethod = (PsiMethod) getElement();
if (psiMethod instanceof SyntheticElement) {
result[0] = psiMethod.getName();
return psiMethod.getName();
}
else {
result[0] = PsiFormatUtil.formatMethod(psiMethod,
return PsiFormatUtil.formatMethod(psiMethod,
PsiSubstitutor.EMPTY,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
PsiFormatUtilBase.SHOW_TYPE
);
}
};
ApplicationManager.getApplication().runReadAction(runnable);
return result[0];
});
} else {
return super.getName();
}
@@ -451,16 +447,11 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
@Override
public String getExternalName() {
final String[] result = new String[1];
final Runnable runnable = () -> {
return ReadAction.compute(() -> {
final PsiMethod psiMethod = (PsiMethod)getElement();
LOG.assertTrue(psiMethod != null);
result[0] = PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
};
ApplicationManager.getApplication().runReadAction(runnable);
return result[0];
return PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
});
}
@Nullable
@@ -686,4 +677,8 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS_MASK);
}
private static String extractMethodName(String methodSignature) {
final String returnTypeAndName = methodSignature.substring(0, methodSignature.indexOf('('));
return returnTypeAndName.substring(returnTypeAndName.indexOf(' ') + 1);
}
}
@@ -34,10 +34,10 @@ import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.fixes.ChangeModifierFix;
import com.siyeh.ig.psiutils.MethodUtils;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -87,7 +87,7 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)profile.getUnwrappedTool(UnusedDeclarationInspectionBase.SHORT_NAME, holder.getFile());
myDeadCodeInspection = tool == null ? new UnusedDeclarationInspectionBase() : tool;
}
private final Set<PsiClass> childMembersAreUsedOutsideMyPackage = ContainerUtil.newConcurrentSet();
private final TObjectIntHashMap<PsiClass> maxSuggestedLevelForChildMembers = new TObjectIntHashMap<>();
@Override
public void visitClass(PsiClass aClass) {
@@ -105,48 +105,79 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
}
private void checkMember(@NotNull final PsiMember member) {
if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return;
if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return;
final PsiClass memberClass = member.getContainingClass();
PsiModifierList memberModifierList = member.getModifierList();
if (memberModifierList == null) return;
int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
int suggestedLevel = suggestLevel(member, memberClass, currentLevel);
if (memberClass != null) {
synchronized (maxSuggestedLevelForChildMembers) {
int prevMax = maxSuggestedLevelForChildMembers.get(memberClass);
maxSuggestedLevelForChildMembers.put(memberClass, Math.max(prevMax, suggestedLevel));
}
}
log(member.getName() + ": effective level is '" + PsiUtil.getAccessModifier(suggestedLevel) + "'");
if (suggestedLevel < currentLevel) {
if (member instanceof PsiClass) {
int memberMaxLevel;
synchronized (maxSuggestedLevelForChildMembers) {
memberMaxLevel = maxSuggestedLevelForChildMembers.get((PsiClass)member);
}
if (memberMaxLevel > suggestedLevel) {
// a class can't have visibility less than its members
return;
}
}
PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner)member).getNameIdentifier() : ContainerUtil.find(
memberModifierList.getChildren(),
element -> element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel)));
assert toHighlight != null : member +" ; " + ((PsiNameIdentifierOwner)member).getNameIdentifier() + "; "+ memberModifierList.getText();
String suggestedModifier = PsiUtil.getAccessModifier(suggestedLevel);
myHolder.registerProblem(toHighlight, "Access can be " + VisibilityUtil.toPresentableText(suggestedModifier), new ChangeModifierFix(suggestedModifier));
}
}
private int suggestLevel(@NotNull PsiMember member, PsiClass memberClass, int currentLevel) {
if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return currentLevel;
if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return currentLevel;
if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod)member;
if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) {
log(member.getName() + " overrides");
return; // overrides
return currentLevel; // overrides
}
if (MethodUtils.isOverridden(method)) {
log(member.getName() + " overridden");
return;
return currentLevel;
}
}
if (member instanceof PsiEnumConstant) return;
if (member instanceof PsiEnumConstant) return currentLevel;
if (member instanceof PsiClass && (member instanceof PsiAnonymousClass ||
member instanceof PsiTypeParameter ||
member instanceof PsiSyntheticClass ||
PsiUtil.isLocalClass((PsiClass)member))) {
return;
return currentLevel;
}
final PsiClass memberClass = member.getContainingClass();
if (memberClass != null && (memberClass.isInterface() || memberClass.isEnum() || memberClass.isAnnotationType() || PsiUtil.isLocalClass(memberClass) && member instanceof PsiClass)) {
return;
return currentLevel;
}
final PsiFile memberFile = member.getContainingFile();
Project project = memberFile.getProject();
if (myDeadCodeInspection.isEntryPoint(member)) {
log(member.getName() +" is entry point");
return;
return currentLevel;
}
PsiModifierList memberModifierList = member.getModifierList();
if (memberModifierList == null) return;
final int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
final AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
final AtomicBoolean foundUsage = new AtomicBoolean();
PsiDirectory memberDirectory = memberFile.getContainingDirectory();
final PsiPackage memberPackage = memberDirectory == null ? null : JavaDirectoryService.getInstance().getPackage(memberDirectory);
log(member.getName()+ ": checking effective level for "+member);
AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
AtomicBoolean foundUsage = new AtomicBoolean();
boolean proceed = UnusedSymbolUtil.processUsages(project, memberFile, member, new EmptyProgressIndicator(), null, info -> {
PsiElement element = info.getElement();
if (element == null) return true;
@@ -165,30 +196,21 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
}
if (!foundUsage.get()) {
log(member.getName() + " unused; ignore");
return; // do not propose private for unused method
return currentLevel; // do not propose private for unused method
}
int max = maxLevel.get();
if (max == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
max = suggestPackageLocal(member);
int suggestedLevel = maxLevel.get();
if (suggestedLevel == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
suggestedLevel = suggestPackageLocal(member);
}
String maxModifier = PsiUtil.getAccessModifier(max);
log(member.getName() + ": effective level is '" + maxModifier + "'");
String suggestedModifier = PsiUtil.getAccessModifier(suggestedLevel);
log(member.getName() + ": effective level is '" + suggestedModifier + "'");
if (max < currentLevel) {
if (max == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL && member instanceof PsiClass && childMembersAreUsedOutsideMyPackage.contains(member)) {
log(member.getName() + " children used outside my package; ignore");
return; // e.g. some public method is used outside my package (without importing class)
}
PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner)member).getNameIdentifier() : ContainerUtil.find(
memberModifierList.getChildren(),
element -> element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel)));
assert toHighlight != null : member +" ; " + ((PsiNameIdentifierOwner)member).getNameIdentifier() + "; "+ memberModifierList.getText();
myHolder.registerProblem(toHighlight, "Access can be " + VisibilityUtil.toPresentableText(maxModifier), new ChangeModifierFix(maxModifier));
}
return suggestedLevel;
}
private boolean handleUsage(@NotNull PsiMember member,
@Nullable PsiClass memberClass,
@NotNull PsiFile memberFile,
@@ -201,20 +223,12 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
if (!(psiFile instanceof PsiJavaFile)) {
log(" refd from " + psiFile.getName() + "; set to public");
maxLevel.set(PsiUtil.ACCESS_LEVEL_PUBLIC);
if (memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return false; // referenced from XML, has to be public
}
//int offset = info.getNavigationOffset();
//if (offset == -1) return true;
@PsiUtil.AccessLevel
int level = getEffectiveLevel(element, psiFile, member, memberFile, memberClass, memberPackage);
log(" ref in file " + psiFile.getName() + "; level = " + PsiUtil.getAccessModifier(level) + "; (" + element + ")");
maxLevel.getAndAccumulate(level, Math::max);
if (level == PsiUtil.ACCESS_LEVEL_PUBLIC && memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return level != PsiUtil.ACCESS_LEVEL_PUBLIC;
}
@@ -50,7 +50,8 @@ public class AddMethodQualifierFix implements IntentionAction {
@NotNull
@Override
public String getText() {
String text = QuickFixBundle.message("add.method.qualifier.fix.text", myCandidates.size() > 1 ? "" : myCandidates.get(0).getName());
final List<PsiVariable> candidates = getOrFindCandidates();
String text = QuickFixBundle.message("add.method.qualifier.fix.text", candidates.size() > 1 ? "" : candidates.get(0).getName());
if (myCandidates.size() > 1) {
text += "...";
}
@@ -71,7 +71,6 @@ import java.util.regex.Pattern;
public class JavaDocInfoGenerator {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocInfoGenerator");
@NonNls private static final Pattern ourNotDot = Pattern.compile("[^.]");
@NonNls private static final Pattern ourWhitespaces = Pattern.compile("[ \\n\\r\\t]+");
@NonNls private static final Pattern ourRelativeHtmlLinks = Pattern.compile("<A.*?HREF=\"([^\":]*)\"",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
@@ -1408,8 +1407,7 @@ public class JavaDocInfoGenerator {
return "";
}
//noinspection ReplaceAllDot
return "../" + ourNotDot.matcher(qName).replaceAll("").replaceAll(".", "../");
return StringUtil.repeat("../", StringUtil.countChars(qName, '.') + 1);
}
private void generateValue(StringBuilder buffer,
@@ -18,7 +18,6 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubsHierarchy.ClassHierarchy;
@@ -113,10 +112,6 @@ public class SingleClassHierarchy extends ClassHierarchy {
@NotNull
@Override
public SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull PsiClass psiClass) {
PsiElement original = psiClass.getOriginalElement();
if (original instanceof PsiClass) {
psiClass = (PsiClass)original;
}
VirtualFile vFile = psiClass.getContainingFile().getVirtualFile();
if (!(vFile instanceof VirtualFileWithId)) return StubClassAnchor.EMPTY_ARRAY;
@@ -18,6 +18,7 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
@@ -69,7 +70,7 @@ public class StubResolver {
private void findType(Symbol startScope, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
// looking up
for (Symbol s = startScope; s != null; s = s.myOwner)
findMemberType(s, name, symbols, new HashSet<Symbol>());
findMemberType(s, name, symbols);
// type from current package
findIdentInPackage(startScope.pkg(), name, IndexTree.CLASS, symbols);
}
@@ -79,7 +80,7 @@ public class StubResolver {
if (receiver.isPackage())
findIdentInPackage((Symbol.PackageSymbol)receiver, name, kind, symbols);
else
findMemberType(receiver, name, symbols, new HashSet<Symbol>());
findMemberType(receiver, name, symbols);
}
private void findIdentInPackage(Symbol.PackageSymbol pck, int name, int kind, Set<Symbol> symbols) {
@@ -97,19 +98,34 @@ public class StubResolver {
}
}
private void findMemberType(Symbol s, int name, Set<Symbol> symbols, Set<Symbol> processed) throws IncompleteHierarchyException {
if (!processed.add(s)) {
return;
private void findMemberType(Symbol s, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
if (s.isClass()) {
processInheritedMembers((Symbol.ClassSymbol)s, name, false, symbols, null);
} else {
processMembers(s.getMembers(), name, symbols, false);
}
processMembers(s.getMembers(), name, symbols, false);
if (s.isClass())
findInheritedMemberType((Symbol.ClassSymbol)s, name, symbols, processed);
}
private void findInheritedMemberType(Symbol.ClassSymbol c, int name, Set<Symbol> symbols, Set<Symbol> processed)
throws IncompleteHierarchyException {
for (Symbol.ClassSymbol st : c.getSuperClasses(myConnector))
findMemberType(st, name, symbols, processed);
private void processInheritedMembers(Symbol.ClassSymbol s,
int name,
boolean requireStatic,
Set<Symbol> symbols,
@Nullable Set<Symbol> processed) throws IncompleteHierarchyException {
processMembers(s.getMembers(), name, symbols, requireStatic);
@CompactArray(Symbol.ClassSymbol.class) Object supers = s.getSuperClasses(myConnector);
if (supers == null) return;
if (processed == null) processed = new HashSet<>();
if (!processed.add(s)) return;
if (supers instanceof Symbol.ClassSymbol) {
processInheritedMembers((Symbol.ClassSymbol)supers, name, requireStatic, symbols, processed);
} else if (supers instanceof Symbol.ClassSymbol[]) {
for (Symbol.ClassSymbol st : (Symbol.ClassSymbol[])supers) {
processInheritedMembers(st, name, requireStatic, symbols, processed);
}
}
}
private Symbol.ClassSymbol[] loadClass(@NotNull QualifiedName fqn) {
@@ -171,16 +187,7 @@ public class StubResolver {
// handling of import static `tsym.name` as
private void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
new Object() {
Set<Symbol> processed = new HashSet<Symbol>();
void importFrom(Symbol.ClassSymbol cs) throws IncompleteHierarchyException {
if (cs == null || !processed.add(cs))
return;
for (Symbol.ClassSymbol c : cs.getSuperClasses(myConnector))
importFrom(c);
processMembers(cs.getMembers(), name, symbols, true);
}
}.importFrom(tsym);
processInheritedMembers(tsym, name, true, symbols, null);
}
private static void processMembers(Symbol.ClassSymbol[] members, int name, Set<Symbol> symbols, boolean requireStatic) {
@@ -19,6 +19,7 @@ import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Comparator;
@@ -125,13 +126,14 @@ public abstract class Symbol {
return BitUtil.isSet(myFlags, CONNECT_STARTED);
}
@NotNull
ClassSymbol[] getSuperClasses(StubHierarchyConnector connector) throws IncompleteHierarchyException {
@Nullable
@CompactArray(ClassSymbol.class)
Object getSuperClasses(StubHierarchyConnector connector) throws IncompleteHierarchyException {
connect(connector);
if (isHierarchyIncomplete()) {
throw IncompleteHierarchyException.INSTANCE;
}
return rawSuperClasses();
return mySuperClasses;
}
@NotNull
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -27,6 +28,7 @@ import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.WindowManager;
@@ -77,38 +79,43 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
final String localName = local.getName();
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
return;
}
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final List<PsiElement> innerClassesWithUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
ApplicationManager.getApplication().invokeLater(() -> {
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
}, ModalityState.NON_MODAL);
return;
}
return true;
});
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
}
return true;
});
}, "Find Usages", true, project)) {
return;
}
final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
if (containerBlock == null) {
final String message = RefactoringBundle.getCannotRefactorMessage("Variable is declared outside a code block");
@@ -116,9 +123,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
return;
}
final PsiExpression defToInline = innerClassesWithUsages.isEmpty()
? getDefToInline(local, refExpr, containerBlock)
: getDefToInline(local, innerClassesWithUsages.get(0), containerBlock);
final PsiExpression defToInline = getDefToInline(local, innerClassesWithUsages.isEmpty() ? refExpr : innerClassesWithUsages.get(0), containerBlock);
if (defToInline == null){
final String key = refExpr == null ? "variable.has.no.initializer" : "variable.has.no.dominating.definition";
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName));
@@ -150,7 +155,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
}
if (refExpr != null && inlineLocalDialog.isInlineThis()) {
refsToInlineList = Collections.<PsiElement>singletonList(refExpr);
refsToInlineList = Collections.singletonList(refExpr);
inlineAll.set(false);
}
}
@@ -353,14 +353,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
try {
text = file.getText().subSequence(startOffset, endOffset).toString();
String prefix = null;
String stripped = text;
if (startLiteralExpression != null) {
final int startExpressionOffset = startLiteralExpression.getTextOffset();
if (startOffset == startExpressionOffset) {
if (StringUtil.startsWithChar(text, '\"') || StringUtil.startsWithChar(text, '\'')) {
stripped = text.substring(1);
}
} else if (startOffset == startExpressionOffset + 1) {
if (startOffset == startExpressionOffset + 1) {
text = "\"" + text;
} else if (startOffset > startExpressionOffset + 1){
prefix = "\" + ";
@@ -371,11 +366,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
String suffix = null;
if (endLiteralExpression != null) {
final int endExpressionOffset = endLiteralExpression.getTextOffset() + endLiteralExpression.getTextLength();
if (endOffset == endExpressionOffset ) {
if (StringUtil.endsWithChar(stripped, '\"') || StringUtil.endsWithChar(stripped, '\'')) {
stripped = stripped.substring(0, stripped.length() - 1);
}
} else if (endOffset == endExpressionOffset - 1) {
if (endOffset == endExpressionOffset - 1) {
text += "\"";
} else if (endOffset < endExpressionOffset - 1) {
suffix = " + \"";
@@ -383,24 +374,6 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
}
boolean primitive = false;
if (stripped.equals("true") || stripped.equals("false")) {
primitive = true;
}
else {
try {
Integer.parseInt(stripped);
primitive = true;
}
catch (NumberFormatException e1) {
//then not primitive
}
}
if (primitive) {
text = stripped;
}
if (literalExpression != null && text.equals(literalExpression.getText())) return literalExpression;
final PsiElement parent = literalExpression != null ? literalExpression : elementAt;
@@ -19,7 +19,6 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFunctionalExpression;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiElementProcessorAdapter;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
@@ -37,20 +36,16 @@ public class ClassImplementationsSearch implements QueryExecutor<PsiElement, Def
}
public static boolean processImplementations(final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) {
if (!FunctionalExpressionSearch.search(psiClass, scope).forEach(expression -> {
return processor.process(expression);
})) {
return false;
}
final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces");
return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() {
public boolean execute(@NotNull PsiClass element) {
if (!ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(element -> {
if (!showInterfaces && element.isInterface()) {
return true;
}
return processor.process(element);
}
}));
}))) {
return false;
}
return FunctionalExpressionSearch.search(psiClass, scope).forEach((Processor<PsiFunctionalExpression>)processor::process);
}
}
@@ -59,14 +59,14 @@ public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClas
private static boolean processAllClassesInGlobalScope(@NotNull final GlobalSearchScope scope,
@NotNull final AllClassesSearch.SearchParameters parameters,
@NotNull Processor<PsiClass> processor) {
final Set<String> names = new THashSet<String>(10000);
final Set<String> names = new THashSet<>(10000);
processClassNames(parameters.getProject(), scope, s -> {
if (parameters.nameMatches(s)) {
names.add(s);
}
});
List<String> sorted = new ArrayList<String>(names);
List<String> sorted = new ArrayList<>(names);
Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER);
return processClassesByNames(parameters.getProject(), scope, sorted, processor);
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
@@ -26,9 +27,9 @@ import com.intellij.psi.search.searches.AnnotatedElementsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -39,15 +40,15 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
@Override
public boolean execute(@NotNull final AnnotatedElementsSearch.Parameters p, @NotNull final Processor<PsiModifierListOwner> consumer) {
final PsiClass annClass = p.getAnnotationClass();
assert annClass.isAnnotationType() : "Annotation type should be passed to annotated members search";
if (!annClass.isAnnotationType()) throw new IllegalArgumentException("Annotation type should be passed to annotated members search but got: "+annClass);
final String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return annClass.getQualifiedName();
}
});
assert annotationFQN != null;
if (annotationFQN == null) throw new IllegalArgumentException("FQN is null for "+annClass);
final PsiManager psiManager = ApplicationManager.getApplication().runReadAction(new Computable<PsiManager>() {
@Override
@@ -59,7 +60,7 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
final SearchScope useScope = p.getScope();
final Class<? extends PsiModifierListOwner>[] types = p.getTypes();
for (final PsiAnnotation ann : getAnnotationCandidates(annClass, useScope)) {
for (final PsiAnnotation ann : getAnnotationCandidates(annClass, useScope, psiManager.getProject())) {
final PsiModifierListOwner candidate = ApplicationManager.getApplication().runReadAction(new Computable<PsiModifierListOwner>() {
@Override
public PsiModifierListOwner compute() {
@@ -90,15 +91,17 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
return true;
}
private static Collection<PsiAnnotation> getAnnotationCandidates(final PsiClass annClass, final SearchScope useScope) {
@NotNull
private static Collection<PsiAnnotation> getAnnotationCandidates(@NotNull PsiClass annClass,
@NotNull SearchScope useScope, @NotNull Project project) {
return ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiAnnotation>>() {
@Override
public Collection<PsiAnnotation> compute() {
if (useScope instanceof GlobalSearchScope) {
return JavaAnnotationIndex.getInstance().get(annClass.getName(), annClass.getProject(), (GlobalSearchScope)useScope);
return JavaAnnotationIndex.getInstance().get(annClass.getName(), project, (GlobalSearchScope)useScope);
}
final List<PsiAnnotation> result = ContainerUtil.newArrayList();
List<PsiAnnotation> result = new ArrayList<>();
for (PsiElement element : ((LocalSearchScope)useScope).getScope()) {
result.addAll(PsiTreeUtil.findChildrenOfType(element, PsiAnnotation.class));
}
@@ -107,7 +110,7 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
});
}
public static boolean isInstanceof(PsiElement owner, Class<? extends PsiModifierListOwner>[] types) {
public static boolean isInstanceof(PsiElement owner, @NotNull Class<? extends PsiModifierListOwner>[] types) {
for (Class<? extends PsiModifierListOwner> type : types) {
if(type.isInstance(owner)) return true;
}
@@ -75,9 +75,9 @@ public class AnnotatedPackagesSearcher implements QueryExecutor<PsiPackage, Anno
boolean accepted = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>(){
@Override
public Boolean compute() {
PsiModifierList modlist = (PsiModifierList)annotation.getParent();
final PsiElement owner = modlist.getParent();
if ((owner instanceof PsiClass)) {
PsiModifierList modList = (PsiModifierList)annotation.getParent();
final PsiElement owner = modList.getParent();
if (owner instanceof PsiClass) {
PsiClass candidate = (PsiClass)owner;
if ("package-info".equals(candidate.getName())) {
LOG.assertTrue(candidate.isValid());
@@ -15,10 +15,11 @@
*/
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.*;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMember;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
@@ -45,7 +46,7 @@ public class ClassesWithAnnotatedMembersSearcher extends QueryExecutorBase<PsiCl
}
}
final Set<PsiClass> processed = new HashSet<PsiClass>();
final Set<PsiClass> processed = new HashSet<>();
AnnotatedElementsSearch.searchPsiMembers(queryParameters.getAnnotationClass(), scope).forEach(member -> {
PsiClass psiClass;
AccessToken token = ReadAction.start();
@@ -35,10 +35,10 @@ import org.jetbrains.annotations.NotNull;
/**
* @author max
*/
public class ConstructorReferencesSearchHelper {
class ConstructorReferencesSearchHelper {
private final PsiManager myManager;
public ConstructorReferencesSearchHelper(@NotNull PsiManager manager) {
ConstructorReferencesSearchHelper(@NotNull PsiManager manager) {
myManager = manager;
}
@@ -48,14 +48,14 @@ public class ConstructorReferencesSearchHelper {
* 2. Exception avoidance. Project is needed outside of read action (to run it via DumbService in the first place),
* and so getProject would fail with an assertion that read action is required but not present.
*/
public boolean processConstructorReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final PsiClass containingClass,
@NotNull final SearchScope searchScope,
@NotNull final Project project,
boolean ignoreAccessScope,
final boolean isStrictSignatureSearch,
@NotNull SearchRequestCollector collector) {
boolean processConstructorReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final PsiClass containingClass,
@NotNull final SearchScope searchScope,
@NotNull final Project project,
boolean ignoreAccessScope,
final boolean isStrictSignatureSearch,
@NotNull SearchRequestCollector collector) {
final boolean[] constructorCanBeCalledImplicitly = new boolean[1];
final boolean[] isEnum = new boolean[1];
final boolean[] isUnder18 = new boolean[1];
@@ -22,6 +22,7 @@ public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReferenc
final PsiMethod method = (PsiMethod)element;
final PsiManager[] manager = new PsiManager[1];
PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
@Override
public PsiClass compute() {
if (!method.isConstructor()) return null;
PsiClass aClass = method.getContainingClass();
@@ -29,7 +29,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex;
import com.intellij.psi.impl.java.stubs.index.JavaSuperClassNameOccurenceIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.GlobalSearchScopeUtil;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.AllClassesSearch;
@@ -43,9 +43,11 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
/**
* @author max
@@ -82,7 +84,8 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
int groupStart = 0;
boolean sameJarClassFound = false;
String currentFQN = null;
for (int i = 0; i < cache.length +1; i++) {
boolean[] isOutOfScope = new boolean[cache.length]; // here we cache results of isInScope(scope, subClass) to avoid calculating it twice
for (int i = 0; i <= cache.length; i++) {
ProgressManager.checkCanceled();
PsiClass subClass = i == cache.length ? null : cache[i];
@@ -92,9 +95,12 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return true;
}
}
if (i != cache.length && !isInScope(scope, subClass)) {
isOutOfScope[i] = true;
continue;
}
String fqn = i == cache.length ? null : ApplicationManager.getApplication().runReadAction((Computable<String>)subClass::getQualifiedName);
if (i != cache.length && !isInScope(scope, subClass)) continue;
if (currentFQN != null && Comparing.equal(fqn, currentFQN)) {
VirtualFile currentJarFile = getJarFile(subClass);
@@ -113,8 +119,9 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
if (!sameJarClassFound) {
for (int g=groupStart; g<i; g++) {
ProgressManager.checkCanceled();
PsiClass anonSubClass = cache[g];
if (!consumer.process(anonSubClass)) return false;
if (isOutOfScope[g]) continue;
PsiClass subClassCandidate = cache[g];
if (!consumer.process(subClassCandidate)) return false;
}
}
groupStart = i;
@@ -162,27 +169,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return ContainerUtil.process(collection, processor);
}
@NotNull
private static GlobalSearchScope toGlobal(@NotNull final SearchScope scope, @NotNull Project project) {
if (scope instanceof GlobalSearchScope) {
return (GlobalSearchScope)scope;
}
Set<VirtualFile> files = Arrays.stream(((LocalSearchScope)scope).getScope()).map(PsiUtil::getVirtualFile).collect(Collectors.toSet());
return GlobalSearchScope.filesScope(project, files);
}
@NotNull
private static PsiClass[] calculateDirectSubClasses(@NotNull Project project,
@NotNull PsiClass baseClass,
@NotNull String baseClassName,
@NotNull SearchScope useScope) {
DumbService dumbService = DumbService.getInstance(project);
GlobalSearchScope globalUseScope = dumbService.runReadActionInSmartMode(() -> StubHierarchyInheritorSearcher.restrictScope(toGlobal(useScope, project)));
GlobalSearchScope globalUseScope = dumbService.runReadActionInSmartMode(
() -> StubHierarchyInheritorSearcher.restrictScope(GlobalSearchScopeUtil.toGlobalSearchScope(useScope, project)));
Collection<PsiReferenceList> candidates =
dumbService.runReadActionInSmartMode(() -> JavaSuperClassNameOccurenceIndex.getInstance().get(baseClassName, project, globalUseScope));
// memory/speed optimisation: it really is a map(string -> PsiClass or List<PsiClass>)
final Map<String, Object> classes = new HashMap<>();
final Map<String, Object> classesWithFqn = new HashMap<>();
processConcurrentlyIfTooMany(candidates,
referenceList -> {
@@ -192,16 +191,16 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
boolean isInheritor = candidate.isInheritor(baseClass, false);
if (isInheritor) {
String fqn = candidate.getQualifiedName();
synchronized (classes) {
Object value = classes.get(fqn);
synchronized (classesWithFqn) {
Object value = classesWithFqn.get(fqn);
if (value == null) {
classes.put(fqn, candidate);
classesWithFqn.put(fqn, candidate);
}
else if (value instanceof PsiClass) {
List<PsiClass> list = new ArrayList<>();
list.add((PsiClass)value);
list.add(candidate);
classes.put(fqn, list);
classesWithFqn.put(fqn, list);
}
else {
@SuppressWarnings("unchecked")
@@ -216,7 +215,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
});
final List<PsiClass> result = new ArrayList<>();
for (Object value : classes.values()) {
for (Object value : classesWithFqn.values()) {
if (value instanceof PsiClass) {
result.add((PsiClass)value);
}
@@ -34,7 +34,7 @@ import java.io.IOException;
import java.util.*;
public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<String, Collection<JavaFunctionalExpressionIndex.IndexHolder>> implements PsiDependentIndex {
public static final ID<String, Collection<IndexHolder>> JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID = ID.create("java.functional.expression");
static final ID<String, Collection<IndexHolder>> JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID = ID.create("java.functional.expression");
private static final String THIS_REF_NAME = "this";
private static final String SUPER_REF_NAME = "super";
@@ -47,84 +47,80 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
@NotNull
@Override
public DataIndexer<String, Collection<IndexHolder>, FileContent> getIndexer() {
return new DataIndexer<String, Collection<IndexHolder>, FileContent>() {
@NotNull
@Override
public Map<String, Collection<IndexHolder>> map(@NotNull FileContent inputData) {
if (!JavaStubElementTypes.JAVA_FILE.shouldBuildStubFor(inputData.getFile())) {
return Collections.emptyMap();
}
final CharSequence contentAsText = inputData.getContentAsText();
if (!StringUtil.contains(contentAsText, "::") && !StringUtil.contains(contentAsText, "->")) {
return Collections.emptyMap();
}
return inputData -> {
if (!JavaStubElementTypes.JAVA_FILE.shouldBuildStubFor(inputData.getFile())) {
return Collections.emptyMap();
}
final CharSequence contentAsText = inputData.getContentAsText();
if (!StringUtil.contains(contentAsText, "::") && !StringUtil.contains(contentAsText, "->")) {
return Collections.emptyMap();
}
final PsiFile file = ((FileContentImpl)inputData).getPsiFileForPsiDependentIndex();
if (!(file instanceof PsiJavaFile)) {
return Collections.emptyMap();
}
final PsiFile file = ((FileContentImpl)inputData).getPsiFileForPsiDependentIndex();
if (!(file instanceof PsiJavaFile)) {
return Collections.emptyMap();
}
final HashMap<String, Collection<IndexHolder>> methodsMap = ContainerUtil.newHashMap();
for (PsiFunctionalExpression expression : SyntaxTraverser.psiTraverser().withRoot(file).filter(PsiFunctionalExpression.class)) {
final PsiExpressionList expressionList =
PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, true, PsiStatement.class, PsiModifierListOwner.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
String methodName = null;
if (parent instanceof PsiMethodCallExpression) {
methodName = ((PsiMethodCallExpression)parent).getMethodExpression().getReferenceName();
if (methodName != null) {
final boolean thisRef = methodName.equals(THIS_REF_NAME);
if (thisRef || methodName.equals(SUPER_REF_NAME)) {
methodName = null;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(parent, PsiClass.class);
if (containingClass != null) {
if (thisRef) {
methodName = containingClass.getName();
} else {
final PsiReferenceList extendsList = containingClass.getExtendsList();
if (extendsList != null) {
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
if (referenceElements.length > 0) {
methodName = referenceElements[0].getReferenceName();
}
final HashMap<String, Collection<IndexHolder>> methodsMap = ContainerUtil.newHashMap();
for (PsiFunctionalExpression expression : SyntaxTraverser.psiTraverser().withRoot(file).filter(PsiFunctionalExpression.class)) {
final PsiExpressionList expressionList =
PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, true, PsiStatement.class, PsiModifierListOwner.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
String methodName = null;
if (parent instanceof PsiMethodCallExpression) {
methodName = ((PsiMethodCallExpression)parent).getMethodExpression().getReferenceName();
if (methodName != null) {
final boolean thisRef = methodName.equals(THIS_REF_NAME);
if (thisRef || methodName.equals(SUPER_REF_NAME)) {
methodName = null;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(parent, PsiClass.class);
if (containingClass != null) {
if (thisRef) {
methodName = containingClass.getName();
} else {
final PsiReferenceList extendsList = containingClass.getExtendsList();
if (extendsList != null) {
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
if (referenceElements.length > 0) {
methodName = referenceElements[0].getReferenceName();
}
}
}
}
}
}
else if (parent instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference();
if (classReference != null) {
methodName = classReference.getReferenceName();
}
}
else if (parent instanceof PsiEnumConstant) {
final PsiClass containingClass = ((PsiEnumConstant)parent).getContainingClass();
if (containingClass != null) {
final String shortEnumName = containingClass.getName();
if (shortEnumName != null) { //should be always true as enums can't be local
methodName = shortEnumName;
}
}
}
else if (parent instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference();
if (classReference != null) {
methodName = classReference.getReferenceName();
}
if (methodName != null) {
Collection<IndexHolder> holders = methodsMap.get(methodName);
if (holders == null) {
holders = new HashSet<IndexHolder>();
methodsMap.put(methodName, holders);
}
else if (parent instanceof PsiEnumConstant) {
final PsiClass containingClass = ((PsiEnumConstant)parent).getContainingClass();
if (containingClass != null) {
final String shortEnumName = containingClass.getName();
if (shortEnumName != null) { //should be always true as enums can't be local
methodName = shortEnumName;
}
holders.add(new IndexHolder(expression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)expression).getParameterList().getParametersCount() : -1,
expressionList.getExpressions().length,
LambdaUtil.getLambdaIdx(expressionList, expression)));
}
}
}
return methodsMap;
if (methodName != null) {
Collection<IndexHolder> holders = methodsMap.get(methodName);
if (holders == null) {
holders = new HashSet<>();
methodsMap.put(methodName, holders);
}
holders.add(new IndexHolder(expression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)expression).getParameterList().getParametersCount() : -1,
expressionList.getExpressions().length,
LambdaUtil.getLambdaIdx(expressionList, expression)));
}
}
}
return methodsMap;
};
}
@@ -151,7 +147,7 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
@Override
public Collection<IndexHolder> read(@NotNull DataInput in) throws IOException {
int l = DataInputOutputUtil.readINT(in);
final Collection<IndexHolder> holders = new HashSet<IndexHolder>(l);
final Collection<IndexHolder> holders = new HashSet<>(l);
while (l-- > 0) {
holders.add(new IndexHolder(DataInputOutputUtil.readINT(in),
DataInputOutputUtil.readINT(in),
@@ -178,26 +174,26 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
return 0;
}
public static class IndexHolder {
static class IndexHolder {
private final int myLambdaParamsNumber;
private final int myMethodArgsLength;
private final int myFunctionExpressionIndex;
public IndexHolder(int lambdaParamsNumber, int methodArgsLength, int functionExpressionIndex) {
IndexHolder(int lambdaParamsNumber, int methodArgsLength, int functionExpressionIndex) {
myLambdaParamsNumber = lambdaParamsNumber;
myMethodArgsLength = methodArgsLength;
myFunctionExpressionIndex = functionExpressionIndex;
}
public int getLambdaParamsNumber() {
int getLambdaParamsNumber() {
return myLambdaParamsNumber;
}
public int getMethodArgsLength() {
int getMethodArgsLength() {
return myMethodArgsLength;
}
public int getFunctionExpressionIndex() {
int getFunctionExpressionIndex() {
return myFunctionExpressionIndex;
}
@@ -40,15 +40,13 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Processor;
import com.intellij.util.Processors;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static com.intellij.util.containers.ContainerUtil.*;
import static com.intellij.util.containers.ContainerUtilRt.newHashSet;
public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
private static final Logger LOG = Logger.getInstance("#" + JavaFunctionalExpressionSearcher.class.getName());
/**
@@ -98,7 +96,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
//collect all methods with parameter of functional interface or free type parameter type
final Collection<PsiMethod> methodCandidates = getCandidateMethodsWithSuitableParams(aClass, project, useScope, candidateFiles, candidateScope);
final LinkedHashSet<VirtualFile> filesToProcess = new LinkedHashSet<VirtualFile>();
final Set<VirtualFile> filesToProcess = new LinkedHashSet<>();
final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
//find all usages of method candidates in files with functional expressions
@@ -109,7 +107,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final boolean varArgs = psiMethod.isVarArgs();
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
final GlobalSearchScope methodUseScope = convertToGlobalScope(project, psiMethod.getUseScope());
final LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders = new LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>>();
final LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders = new LinkedHashMap<>();
//functional expressions checker: number and type of parameters at call site should correspond to candidate method currently check
final SuitableFilesProcessor processor = new SuitableFilesProcessor(holders, expectedFunExprParamsCount, parametersCount, varArgs, parameters);
fileBasedIndex.processValues(JavaFunctionalExpressionIndex.JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID, psiMethod.getName(), null, processor, useScope.intersectWith(methodUseScope));
@@ -134,7 +132,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
private static Set<Module> getJava8Modules(Project project) {
final boolean projectLevelIsHigh = PsiUtil.getLanguageLevel(project).isAtLeast(LanguageLevel.JDK_1_8);
final Set<Module> highLevelModules = new HashSet<Module>();
final Set<Module> highLevelModules = new HashSet<>();
for (Module module : ModuleManager.getInstance(project).getModules()) {
final LanguageLevelModuleExtension extension = ModuleRootManager.getInstance(module).getModuleExtension(LanguageLevelModuleExtension.class);
if (extension != null) {
@@ -151,7 +149,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final Processor<PsiFunctionalExpression> consumer,
Set<VirtualFile> filesToProcess, final int expectedFunExprParamsCount, boolean isVoid) {
LOG.info("#usage files: " + filesToProcess.size());
process(filesToProcess, new ReadActionProcessor<VirtualFile>() {
ContainerUtil.process(filesToProcess, new ReadActionProcessor<VirtualFile>() {
@Override
public boolean processInReadAction(VirtualFile file) {
//resolve functional expressions to ensure that functional expression type is appropriate
@@ -172,11 +170,11 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
GlobalSearchScope visibleFromCandidates = combineResolveScopes(project, candidateFiles);
final Set<String> usedMethodNames = newHashSet();
Set<String> usedMethodNames = new HashSet<>();
FileBasedIndex.getInstance().processAllKeys(JavaFunctionalExpressionIndex.JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID,
Processors.cancelableCollectProcessor(usedMethodNames), candidateScope, null);
final LinkedHashSet<PsiMethod> methods = newLinkedHashSet();
Set<PsiMethod> methods = ContainerUtil.newLinkedHashSet();
Processor<PsiMethod> methodProcessor = method -> {
if (usedMethodNames.contains(method.getName())) {
methods.add(method);
@@ -197,7 +195,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
@NotNull
private static GlobalSearchScope combineResolveScopes(Project project, Set<VirtualFile> candidateFiles) {
final PsiManager psiManager = PsiManager.getInstance(project);
Set<GlobalSearchScope> resolveScopes = newLinkedHashSet(mapNotNull(candidateFiles, file -> {
Set<GlobalSearchScope> resolveScopes = ContainerUtil.newLinkedHashSet(ContainerUtil.mapNotNull(candidateFiles, file -> {
PsiFile psiFile = file.isValid() ? psiManager.findFile(file) : null;
return psiFile == null ? null : psiFile.getResolveScope();
}));
@@ -206,7 +204,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
@NotNull
private static Set<VirtualFile> getFilesWithFunctionalExpressionsScope(Project project, GlobalSearchScope useScope) {
final Set<VirtualFile> files = newLinkedHashSet();
final Set<VirtualFile> files = ContainerUtil.newLinkedHashSet();
final PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(project);
Processor<VirtualFile> processor = Processors.cancelableCollectProcessor(files);
helper.processFilesWithText(useScope, UsageSearchContext.IN_CODE, true, "::", processor);
@@ -221,8 +219,8 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
scope = (GlobalSearchScope)useScope;
}
else if (useScope instanceof LocalSearchScope) {
final Set<VirtualFile> files = new HashSet<VirtualFile>();
addAllNotNull(files, map(((LocalSearchScope)useScope).getScope(), element -> PsiUtilCore.getVirtualFile(element)));
final Set<VirtualFile> files = new HashSet<>();
ContainerUtil.addAllNotNull(files, ContainerUtil.map(((LocalSearchScope)useScope).getScope(), PsiUtilCore::getVirtualFile));
scope = GlobalSearchScope.filesScope(project, files);
}
else {
@@ -247,15 +245,15 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
}
</pre>
*/
private static void collectFilesWithTypeOccurrencesAndFieldAssignments(PsiClass aClass,
GlobalSearchScope filesScope,
final LinkedHashSet<VirtualFile> usageFiles) {
final Set<PsiField> fields = new LinkedHashSet<PsiField>();
private static void collectFilesWithTypeOccurrencesAndFieldAssignments(@NotNull PsiClass aClass,
@NotNull GlobalSearchScope filesScope,
@NotNull Set<VirtualFile> usageFiles) {
final Set<PsiField> fields = new LinkedHashSet<>();
for (final PsiReference reference : ReferencesSearch.search(aClass, filesScope)) {
ApplicationManager.getApplication().runReadAction(() -> {
final PsiElement element = reference.getElement();
if (element != null) {
addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(element));
ContainerUtil.addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(element));
final PsiElement parent = element.getParent();
if (parent instanceof PsiTypeElement) {
final PsiElement gParent = parent.getParent();
@@ -276,7 +274,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final PsiElement fieldElement = fieldRef.getElement();
final PsiAssignmentExpression varElementParent = PsiTreeUtil.getParentOfType(fieldElement, PsiAssignmentExpression.class);
if (varElementParent != null && PsiTreeUtil.isAncestor(varElementParent.getLExpression(), fieldElement, false)) {
addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(fieldElement));
ContainerUtil.addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(fieldElement));
}
return true;
}
@@ -291,7 +289,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
VirtualFile file) {
final PsiFile psiFile = aClass.getManager().findFile(file);
if (psiFile != null) {
final Ref<Boolean> ref = new Ref<Boolean>(true);
final Ref<Boolean> ref = new Ref<>(true);
psiFile.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
@@ -345,11 +343,11 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
private final boolean myVarArgs;
private final PsiParameter[] myParameters;
public SuitableFilesProcessor(Map<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders,
int expectedFunExprParamsCount,
int parametersCount,
boolean varArgs,
PsiParameter[] parameters) {
SuitableFilesProcessor(Map<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders,
int expectedFunExprParamsCount,
int parametersCount,
boolean varArgs,
PsiParameter[] parameters) {
myHolders = holders;
myExpectedFunExprParamsCount = expectedFunExprParamsCount;
myParametersCount = parametersCount;
@@ -372,7 +370,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
}
if (suitableParamNumbers) {
if (savedHolders == null) {
savedHolders = new LinkedHashSet<JavaFunctionalExpressionIndex.IndexHolder>();
savedHolders = new LinkedHashSet<>();
myHolders.put(file, savedHolders);
}
savedHolders.add(holder);
@@ -116,11 +116,10 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor<PsiMethod, O
@NotNull
private static Iterable<PsiMethod> compute(@NotNull PsiMethod method, @NotNull Project project) {
Collection<PsiMethod> result = new LinkedHashSet<>();
Application application = ApplicationManager.getApplication();
final PsiClass containingClass = application.runReadAction((Computable<PsiClass>)method::getContainingClass);
assert containingClass != null;
Collection<PsiMethod> result = new LinkedHashSet<>();
Processor<PsiClass> inheritorsProcessor = inheritor -> {
PsiMethod found = application.runReadAction((Computable<PsiMethod>)() -> findOverridingMethod(project, inheritor, method, containingClass));
if (found != null) {
@@ -20,7 +20,6 @@
package com.intellij.psi.impl.search;
import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -38,12 +37,7 @@ public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
super(delegate);
Project project = getProject();
if (project != null) {
myIndex = ProjectRootManager.getInstance(project).getFileIndex();
}
else {
myIndex = null;
}
myIndex = project == null ? null : ProjectRootManager.getInstance(project).getFileIndex();
}
@Override
@@ -34,16 +34,16 @@ public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiM
return processDeepestSuperMethods(method, consumer);
}
public static boolean processDeepestSuperMethods(PsiMethod method, Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<PsiMethod>();
public static boolean processDeepestSuperMethods(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<>();
methods.add(method);
return findDeepestSuperOrSelfSignature(method, methods, null, consumer);
}
private static boolean findDeepestSuperOrSelfSignature(final PsiMethod method,
Set<PsiMethod> set,
private static boolean findDeepestSuperOrSelfSignature(@NotNull PsiMethod method,
@NotNull Set<PsiMethod> set,
Set<PsiMethod> guard,
Processor<PsiMethod> processor) {
@NotNull Processor<PsiMethod> processor) {
if (guard != null && !guard.add(method)) return true;
PsiMethod[] supers = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
@Override
@@ -57,7 +57,7 @@ public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiM
}
for (PsiMethod superMethod : supers) {
if (guard == null) {
guard = new THashSet<PsiMethod>();
guard = new THashSet<>();
guard.add(method);
}
if (!findDeepestSuperOrSelfSignature(superMethod, set, guard, processor)) return false;
@@ -63,7 +63,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
final SearchRequestCollector collector = p.getOptimizer();
final SearchScope searchScope = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(() -> p.getEffectiveSearchScope());
final SearchScope searchScope = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(p::getEffectiveSearchScope);
if (searchScope == GlobalSearchScope.EMPTY_SCOPE) {
return;
}
@@ -65,7 +65,8 @@ public class PsiAnnotationMethodReferencesSearcher implements QueryExecutor<PsiR
return true;
}
public static ReadActionProcessor<PsiReference> createImplicitDefaultAnnotationMethodConsumer(final Processor<PsiReference> consumer) {
@NotNull
static ReadActionProcessor<PsiReference> createImplicitDefaultAnnotationMethodConsumer(@NotNull Processor<PsiReference> consumer) {
return new ReadActionProcessor<PsiReference>() {
@Override
public boolean processInReadAction(final PsiReference reference) {
@@ -34,7 +34,6 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
public SimpleAccessorReferenceSearcher() {
super(true);
}
@@ -47,7 +46,7 @@ public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiRefere
addPropertyAccessUsages((PsiMethod)refElement, queryParameters.getEffectiveSearchScope(), queryParameters.getOptimizer());
}
static void addPropertyAccessUsages(PsiMethod method, SearchScope scope, SearchRequestCollector collector) {
static void addPropertyAccessUsages(@NotNull PsiMethod method, @NotNull SearchScope scope, @NotNull SearchRequestCollector collector) {
final String propertyName = PropertyUtil.getPropertyName(method);
if (StringUtil.isNotEmpty(propertyName)) {
SearchScope additional = GlobalSearchScope.EMPTY_SCOPE;
@@ -16,10 +16,12 @@
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
@@ -33,6 +35,7 @@ import org.jetbrains.annotations.NotNull;
* @author peter
*/
public class StubHierarchyInheritorSearcher extends QueryExecutorBase<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.StubHierarchyInheritorSearcher");
public StubHierarchyInheritorSearcher() {
super(true);
}
@@ -54,6 +57,11 @@ public class StubHierarchyInheritorSearcher extends QueryExecutorBase<PsiClass,
if (!(p.getScope() instanceof GlobalSearchScope) || !isSearching()) return;
PsiClass base = p.getClassToProcess();
PsiElement original = base.getOriginalElement();
if (original instanceof PsiClass) {
base = (PsiClass)original;
}
GlobalSearchScope scope = (GlobalSearchScope)p.getScope();
ClassHierarchy hierarchy = HierarchyService.getHierarchy(base.getProject());
for (SmartClassAnchor anchor : hierarchy.getDirectSubtypeCandidates(base)) {
@@ -50,24 +50,21 @@ public class VariableInIncompleteCodeSearcher extends QueryExecutorBase<PsiRefer
PsiElement[] elements = ((LocalSearchScope)scope).getScope();
if (elements.length == 0) return;
PsiSearchHelper.SERVICE.getInstance(p.getProject()).processElementsWithWord(new TextOccurenceProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, int offsetInElement) {
for (PsiElement child = element.findElementAt(offsetInElement); child != null; child = child.getParent()) {
if (!name.equals(child.getText())) {
break;
}
if (child instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)child;
if (!ref.isQualified() &&
!(ref.getParent() instanceof PsiMethodCallExpression) &&
ref.resolve() == null && ref.advancedResolve(true).getElement() == refElement) {
consumer.process(ref);
}
PsiSearchHelper.SERVICE.getInstance(p.getProject()).processElementsWithWord((element, offsetInElement) -> {
for (PsiElement child = element.findElementAt(offsetInElement); child != null; child = child.getParent()) {
if (!name.equals(child.getText())) {
break;
}
if (child instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)child;
if (!ref.isQualified() &&
!(ref.getParent() instanceof PsiMethodCallExpression) &&
ref.resolve() == null && ref.advancedResolve(true).getElement() == refElement) {
consumer.process(ref);
}
}
return true;
}
return true;
}, scope, name, UsageSearchContext.ANY, true);
}
}
@@ -298,7 +298,7 @@ public class PropertyUtil {
}
@Nullable
public static String getPropertyName(@NonNls String methodName) {
public static String getPropertyName(@NonNls @NotNull String methodName) {
return StringUtil.getPropertyName(methodName);
}
@@ -183,11 +183,7 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps
if (type instanceof PsiClassReferenceType) {
return ((PsiClassReferenceType)type).getReference();
}
final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
final PsiClass refClass = resolveResult.getElement();
assert refClass != null : type;
return new LightClassReference(myManager, type.getCanonicalText(true), refClass, resolveResult.getSubstitutor());
return new LightClassTypeReference(myManager, type);
}
@NotNull
@@ -15,27 +15,21 @@
*/
package com.intellij.psi.impl.light;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LightClassReference extends LightElement implements PsiJavaCodeReferenceElement {
private final String myText;
public class LightClassReference extends LightClassReferenceBase implements PsiJavaCodeReferenceElement {
private final String myClassName;
private final PsiElement myContext;
@NotNull private final GlobalSearchScope myResolveScope;
private final PsiClass myRefClass;
private final PsiSubstitutor mySubstitutor;
private LightReferenceParameterList myParameterList;
private LightClassReference(@NotNull PsiManager manager,
@NotNull @NonNls String text,
@Nullable @NonNls String className,
@@ -43,8 +37,7 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
@NotNull GlobalSearchScope resolveScope,
@Nullable PsiElement context,
@Nullable PsiClass refClass) {
super(manager, JavaLanguage.INSTANCE);
myText = text;
super(manager, text);
myClassName = className;
myResolveScope = resolveScope;
@@ -107,32 +100,6 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
return new CandidateInfo(resolved, substitutor);
}
@Override
@NotNull
public JavaResolveResult[] multiResolve(boolean incompleteCode){
final JavaResolveResult result = advancedResolve(incompleteCode);
if(result != JavaResolveResult.EMPTY) return new JavaResolveResult[]{result};
return JavaResolveResult.EMPTY_ARRAY;
}
@Override
public void processVariants(@NotNull PsiScopeProcessor processor){
throw new RuntimeException("Variants are not available for light references");
}
@Override
public PsiElement getReferenceNameElement() {
return null;
}
@Override
public PsiReferenceParameterList getParameterList() {
if (myParameterList == null) {
myParameterList = new LightReferenceParameterList(myManager, PsiTypeElement.EMPTY_ARRAY);
}
return myParameterList;
}
@Override
public String getQualifiedName() {
if (myClassName != null) {
@@ -162,36 +129,6 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
}
}
@Override
public String getText() {
return myText;
}
@Override
public PsiReference getReference() {
return this;
}
@Override
@NotNull
public String getCanonicalText() {
String name = getQualifiedName();
if (name == null) return "";
PsiType[] types = getTypeParameters();
if (types.length == 0) return name;
StringBuilder buf = new StringBuilder();
buf.append(name);
buf.append('<');
for (int i = 0; i < types.length; i++) {
if (i > 0) buf.append(',');
buf.append(types[i].getCanonicalText());
}
buf.append('>');
return buf.toString();
}
@Override
public PsiElement copy() {
if (myClassName != null) {
@@ -207,79 +144,11 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
}
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitReferenceElement(this);
}
else {
visitor.visitElement(this);
}
}
public String toString() {
return "LightClassReference:" + myText;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return element instanceof PsiClass && getManager().areElementsEquivalent(resolve(), element);
}
@Override
@NotNull
public Object[] getVariants() {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public boolean isSoft(){
return false;
}
@Override
public TextRange getRangeInElement() {
return new TextRange(0, getTextLength());
}
@Override
public PsiElement getElement() {
return this;
}
@Override
public boolean isValid() {
return myRefClass == null || myRefClass.isValid();
}
@Override
@NotNull
public PsiType[] getTypeParameters() {
return PsiType.EMPTY_ARRAY;
}
@Override
public PsiElement getQualifier() {
return null;
}
@Override
public boolean isQualified() {
return false;
}
@NotNull
@Override
public GlobalSearchScope getResolveScope() {
@@ -0,0 +1,168 @@
/*
* 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.
*/
package com.intellij.psi.impl.light;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
abstract class LightClassReferenceBase extends LightElement implements PsiJavaCodeReferenceElement {
protected final String myText;
private LightReferenceParameterList myParameterList;
protected LightClassReferenceBase(@NotNull PsiManager manager, @NotNull String text) {
super(manager, JavaLanguage.INSTANCE);
myText = text;
}
@Override
@NotNull
public JavaResolveResult[] multiResolve(boolean incompleteCode) {
final JavaResolveResult result = advancedResolve(incompleteCode);
if (result != JavaResolveResult.EMPTY) return new JavaResolveResult[]{result};
return JavaResolveResult.EMPTY_ARRAY;
}
@Override
public void processVariants(@NotNull PsiScopeProcessor processor) {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public PsiElement getReferenceNameElement() {
return null;
}
@Override
public PsiReferenceParameterList getParameterList() {
if (myParameterList == null) {
myParameterList = new LightReferenceParameterList(myManager, PsiTypeElement.EMPTY_ARRAY);
}
return myParameterList;
}
@Override
public String getQualifiedName() {
PsiClass psiClass = (PsiClass)resolve();
if (psiClass != null) {
return psiClass.getQualifiedName();
}
return null;
}
@Override
public String getText() {
return myText;
}
@Override
public PsiReference getReference() {
return this;
}
@Override
@NotNull
public String getCanonicalText() {
String name = getQualifiedName();
if (name == null) return "";
PsiType[] types = getTypeParameters();
if (types.length == 0) return name;
StringBuilder buf = new StringBuilder();
buf.append(name);
buf.append('<');
for (int i = 0; i < types.length; i++) {
if (i > 0) buf.append(',');
buf.append(types[i].getCanonicalText());
}
buf.append('>');
return buf.toString();
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitReferenceElement(this);
}
else {
visitor.visitElement(this);
}
}
public String toString() {
return getClass().getSimpleName() + getText();
}
@Override
public boolean isReferenceTo(PsiElement element) {
return element instanceof PsiClass && getManager().areElementsEquivalent(resolve(), element);
}
@Override
@NotNull
public Object[] getVariants() {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public boolean isSoft() {
return false;
}
@Override
public TextRange getRangeInElement() {
return new TextRange(0, getTextLength());
}
@Override
public PsiElement getElement() {
return this;
}
@Override
@NotNull
public PsiType[] getTypeParameters() {
return PsiType.EMPTY_ARRAY;
}
@Override
public PsiElement getQualifier() {
return null;
}
@Override
public boolean isQualified() {
return false;
}
}
@@ -0,0 +1,69 @@
/*
* 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.
*/
package com.intellij.psi.impl.light;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LightClassTypeReference extends LightClassReferenceBase implements PsiJavaCodeReferenceElement {
private final @NotNull PsiClassType myType;
private LightClassTypeReference(@NotNull PsiManager manager, @NotNull String text, @NotNull PsiClassType type) {
super(manager, text);
myType = type;
}
public LightClassTypeReference(@NotNull PsiManager manager, @NotNull PsiClassType type) {
this(manager, type.getCanonicalText(true), type);
}
@Nullable
@Override
public PsiElement resolve() {
return myType.resolve();
}
@NotNull
@Override
public JavaResolveResult advancedResolve(boolean incompleteCode) {
return myType.resolveGenerics();
}
@Nullable
@Override
public String getReferenceName() {
return myType.getClassName();
}
@Override
public PsiElement copy() {
return new LightClassTypeReference(myManager, myText, myType);
}
@Override
public boolean isValid() {
return myType.isValid();
}
@NotNull
@Override
public GlobalSearchScope getResolveScope() {
return myType.getResolveScope();
}
}
@@ -183,15 +183,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC
@NotNull PsiElement place) {
if (lastParent instanceof PsiExpressionList) return true;
final PsiClassStub stub = getStub();
if (stub != null) {
// no tree is loaded
// that means we could not have come from resolving something inside anonymous class, we just resolving the base class reference
// so skip the (very expensive) getBaseClassReference() call which would load tree
return true;
}
if (lastParent != null/* IMPORTANT: do not call getBaseClassReference() for lastParent == null and lastParent which is not under our node - loads tree!*/
if (lastParent instanceof PsiJavaCodeReferenceElement/* IMPORTANT: do not call getBaseClassReference() for lastParent == null and lastParent which is not under our node - loads tree!*/
&& lastParent.getParent() == this && lastParent == getBaseClassReference()) {
return true;
}
@@ -20,6 +20,7 @@ import com.intellij.navigation.ColoredItemPresentation;
import com.intellij.navigation.LocationPresentation;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -104,7 +105,12 @@ public abstract class JavaClassTreeElementBase<Value extends PsiElement> extends
@Override
public TextAttributesKey getTextAttributesKey() {
return isDeprecated() ? CodeInsightColors.DEPRECATED_ATTRIBUTES : null;
try {
return isDeprecated() ? CodeInsightColors.DEPRECATED_ATTRIBUTES : null;
}
catch (IndexNotReadyException ignore) {
return null; // do not show deprecated elements while indexing
}
}
private boolean isDeprecated(){
@@ -0,0 +1,17 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
abstract class Test {
{
Consumer<? extends Double> bar = bar(instanceOf(Integer.class), i -> i + 2);
Consumer<? extends String> bar1 = bar(instanceOf(Integer.class), i -> i + 2);
}
abstract <T, R> Consumer<T> bar(Predicate<? super T> predicate, Function<T, R> f);
abstract <P> Predicate<P> instanceOf(Class<? extends P> type);
}
@@ -14,7 +14,7 @@ class Test {
class Test2 {
static void m(Integer i) { }
static void m(Integer <warning descr="Parameter 'i' is never used">i</warning>) { }
interface I1 {
void m(int x);
@@ -77,7 +77,7 @@ abstract class AbstractCollection<E> implements Collection<E> {
public boolean add(E e) {
return true;
}
public boolean addAll(Collection<? extends E> c) {
public boolean addAll(Collection<? extends E> <warning descr="Parameter 'c' is never used">c</warning>) {
boolean modified = false;
return modified;
}
@@ -6,11 +6,11 @@ class Test {
Test m(List<Integer> l1, List<Integer> l2);
}
static Test meth(List<Integer>... lli) {
static Test meth(List<Integer>... <warning descr="Parameter 'lli' is never used">lli</warning>) {
return null;
}
Test(List<Integer>... lli) {}
Test(List<Integer>... <warning descr="Parameter 'lli' is never used">lli</warning>) {}
{
I <warning descr="Variable 'i1' is never used">i1</warning> = <warning descr="Unchecked generics array creation for varargs parameter">Test::meth</warning>;
@@ -1,7 +1,7 @@
import java.util.stream.Stream;
class A {
private void test5(Integer i, String... strings) {}
private void test5(Integer <warning descr="Parameter 'i' is never used">i</warning>, String... <warning descr="Parameter 'strings' is never used">strings</warning>) {}
private void <warning descr="Private method 'test5(java.lang.Integer, java.lang.Integer, java.lang.String...)' is never used">test5</warning>(Integer i, Integer b, String... strings) {
System.out.println(i);
System.out.println(b);
@@ -12,7 +12,7 @@ class MyTest<T> {
public static class Builder<E> {
public Builder<E> add(E element) {
public Builder<E> add(E <warning descr="Parameter 'element' is never used">element</warning>) {
return this;
}
@@ -8,6 +8,6 @@ class Main {
}
public static boolean checkForJdk(String <warning descr="Parameter 'homePath' is never used">homePath</warning>) {return false;}
public static boolean checkForJdk(File homePath) {return false;}
public static boolean checkForJdk(File <warning descr="Parameter 'homePath' is never used">homePath</warning>) {return false;}
}
@@ -0,0 +1,28 @@
// "Replace with lambda" "true"
import java.util.*;
import java.util.function.Function;
import static java.util.Collections.emptyList;
class Ambiguous {
public void setRoots(List<String> roots) {}
public static <T> List<T> concat(Iterable<? extends Collection<T>> list) {
return new ArrayList<T>();
}
public static <T> List<T> concat(List<List<? extends T>> lists) {
return new ArrayList<T>();
}
public static <T,V> List<V> map(Collection<? extends T> iterable, Function<T, V> mapping) {
return emptyList();
}
public void anonymousToLambda(HashSet<String> modules) {
setRoots(Ambiguous.concat(Ambiguous.map(modules, (Function<String, List<String>>) s -> null)
));
}
}
@@ -0,0 +1,28 @@
// "Replace with lambda" "true"
import java.util.*;
import java.util.function.Function;
import static java.util.Collections.emptyList;
class Ambiguous {
public void setRoots(List<String> roots) {}
public static <T> List<T> concat(Iterable<? extends Collection<T>> list) {
return new ArrayList<T>();
}
public static <T> List<T> concat(List<List<? extends T>> lists) {
return new ArrayList<T>();
}
public static <T,V> List<V> map(Collection<? extends T> iterable, Function<T, V> mapping) {
return emptyList();
}
public void anonymousToLambda(HashSet<String> modules) {
setRoots(Ambiguous.concat(Ambiguous.map(modules, (Function<String, List<String>>) s -> Arrays.asList(""))
));
}
}
@@ -1,4 +1,4 @@
// "Replace with lambda" "false"
// "Replace with lambda" "true"
class A {
{
bar(new Throwabl<caret>eComputable<String, Exception>() {
@@ -1,4 +1,4 @@
// "Replace with lambda" "false"
// "Replace with lambda" "true"
import java.util.*;
class Test2 {
@@ -1,4 +1,4 @@
// "Replace with lambda" "false"
// "Replace with lambda" "true"
import java.util.*;
import java.util.function.Function;
@@ -1,4 +1,4 @@
// "Replace with lambda" "false"
// "Replace with lambda" "true"
import java.util.*;
import java.util.function.Function;
@@ -1,4 +1,4 @@
// "Replace Collection.stream().forEachOrdered() with Collection.forEach()" "true"
// "Replace Collection.stream().forEachOrdered() with Collection.forEach() (may change semantics)" "true"
import java.util.Arrays;
@@ -1,4 +1,4 @@
// "Replace Collection.stream().forEachOrdered() with Collection.forEach()" "true"
// "Replace Collection.stream().forEachOrdered() with Collection.forEach() (may change semantics)" "true"
import java.util.Arrays;
@@ -0,0 +1,5 @@
class Test {
void foo() {
String s = "5<selection>+5</selection>";
}
}
@@ -0,0 +1,7 @@
class Test {
public static final String xxx = "+5";
void foo() {
String s = "5" + xxx;
}
}
@@ -0,0 +1,8 @@
class Test {
void print(Stirng s) {
}
void foo() {
print("<selection>5</selection>");
}
}
@@ -0,0 +1,10 @@
class Test {
public static final String xxx = "5";
void print(Stirng s) {
}
void foo() {
print(xxx);
}
}
@@ -1,6 +1,6 @@
class A {
public void test() {
boolean str = true;
String str = "true";
String s = "ss" + str;
}
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
import com.intellij.idea.Bombed;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
@@ -26,6 +27,7 @@ import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
@@ -476,6 +478,11 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
@Bombed(month = Calendar.AUGUST, day = 30, user = "ann")
public void testResolutionOrderForVariableCycles() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(false);
}
@@ -116,11 +116,14 @@ class A {
Object field = new B() {
void foo(Object o) {
}
class MyInner extends Inner {}
};
}
class B {
void foo(Object o) {}
static class Inner {}
}
""")
assert !file.contentsLoaded
@@ -138,6 +141,8 @@ class B {
assert !file.contentsLoaded
assert bClass == override.containingClass.superClass
assert bClass.innerClasses[0] == override.containingClass.innerClasses[0].superClass
assert !file.contentsLoaded
}
public void "test AST can be gc-ed and recreated"() {
@@ -109,6 +109,18 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
"}"
);
}
public void test_format_only_selected_range() {
myTextRange = new TextRange(18, 19);
doTextTest(
"public class X {\n" +
" public int a = 2;\n" +
"}",
"public class X {\n" +
" public int a = 2;\n" +
"}"
);
}
public void testNew() throws Exception {
final CommonCodeStyleSettings settings = getSettings();
@@ -75,6 +75,18 @@ public class IntroduceConstantTest extends LightCodeInsightTestCase {
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testPartialStringLiteralConvertibleToInt() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null).invoke(getProject(), getEditor(), getFile(), null);
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testStringLiteralConvertibleToInt() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null).invoke(getProject(), getEditor(), getFile(), null);
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testPartialStringLiteralQualified() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
final PsiClass psiClass = ((PsiJavaFile)getFile()).getClasses()[0];
@@ -250,7 +250,7 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
}
public void testSubPrimitiveLiteral() {
doTest(new MockIntroduceVariableHandler("str", false, false, false, "boolean"));
doTest(new MockIntroduceVariableHandler("str", false, false, false, CommonClassNames.JAVA_LANG_STRING));
}
public void testArrayFromVarargs() {
@@ -139,6 +139,6 @@ public abstract class ModuleRootManagerTestCase extends ModuleTestCase {
}
protected VirtualFile getAsmJar() {
return getJarFromLibDir("asm.jar");
return getJarFromLibDir("asm-all.jar");
}
}
@@ -36,6 +36,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import com.intellij.util.containers.hash.HashMap;
import com.siyeh.ig.controlflow.DoubleNegationInspection;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -150,8 +151,10 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu
}
boolean isCollection =
InheritanceUtil.isInheritor(PsiTypesUtil.getPsiClass(argument.getType()), CommonClassNames.JAVA_UTIL_COLLECTION);
setReplaceByString(isCollection ? "$it$.stream()" : "java.util.stream.StreamSupport.stream($it$.spliterator(), false)");
return super.replace(expression, evaluator);
setReplaceByString(isCollection ? "($it$).stream()" : "java.util.stream.StreamSupport.stream(($it$).spliterator(), false)");
final PsiExpression replaced = super.replace(expression, evaluator);
ParenthesesUtils.removeParentheses(replaced, false);
return replaced;
}
};
} else if (methodName.equals("filter")) {
@@ -282,6 +282,10 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
}
}
public void testFluentIterableFromAndParenthesises() {
doTestAllFile();
}
private void doTestNoQuickFixes(Class<? extends PsiElement>... highlightedElements) {
myFixture.configureByFile(getTestName(true) + ".java");
@@ -0,0 +1,9 @@
import com.google.common.collect.FluentIterable;
import java.util.List;
public class Main {
void m(Object input, List<Object> transformed) {
transformed.addAll(FluentIterable.fro<caret>m((Iterable<Object>) input).toList());
}
}
@@ -0,0 +1,9 @@
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class Main {
void m(Object input, List<Object> transformed) {
transformed.addAll(StreamSupport.stream(((Iterable<Object>) input).spliterator(), false).collect(Collectors.toList()));
}
}
@@ -1,5 +1,4 @@
import java.util.ArrayList;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -8,19 +7,16 @@ class A {
ArrayList<String> strings = new ArrayList<String>();
Stream<String> it = strings.stream();
int i = (int) it.flatMap((o) -> StreamSupport.stream(new Function<String, Iterable<String>>() {
@Override
public Iterable<String> apply(String o) {
if ('a' > 2) {
return getIterable();
} else if ('c' < 123) {
ArrayList<String> strings1 = new ArrayList<>();
strings1.add(o);
return strings1;
}
return null;
int i = (int) it.flatMap(o -> {
if ('a' > 2) {
return StreamSupport.stream(getIterable().spliterator(), false);
} else if ('c' < 123) {
ArrayList<String> strings1 = new ArrayList<>();
strings1.add(o);
return strings1.stream();
}
}.apply(o).spliterator(), false)).count();
return null;
}).count();
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -55,7 +55,7 @@ oromatcher.jar
picocontainer.jar
protobuf-2.5.0.jar
proxy-vole_20131209.jar
pty4j-0.7.jar
pty4j-0.7.1.jar
purejavacomm.jar
resolver.jar
rhino-js-1_7R4.jar
Binary file not shown.
@@ -15,27 +15,33 @@
*/
package com.intellij.codeHighlighting;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.lang.Language;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.colors.TextAttributesScheme;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringHash;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
public class RainbowHighlighter {
private final float[] myFloats;
private static final HashSet<Language> BY_PASS_LANGUAGES = new HashSet<Language>();
@NotNull private final EditorColorsScheme myColorsScheme;
@NotNull private final Color myDefaultBackground;
public RainbowHighlighter(@NotNull TextAttributesScheme colorsScheme) {
float[] components = colorsScheme.getAttributes(DefaultLanguageHighlighterColors.CONSTANT).getForegroundColor().getRGBColorComponents(null);
public RainbowHighlighter(@Nullable EditorColorsScheme colorsScheme, @Nullable Color background) {
myColorsScheme = colorsScheme != null ? colorsScheme : EditorColorsManager.getInstance().getGlobalScheme();
myDefaultBackground = background != null ? background : myColorsScheme.getDefaultBackground();
float[] components = myColorsScheme.getAttributes(DefaultLanguageHighlighterColors.CONSTANT).getForegroundColor().getRGBColorComponents(null);
myFloats = Color.RGBtoHSB((int)(255 * components[0]), (int)(255 * components[0]), (int)(255 * components[0]), null);
}
@@ -46,14 +52,6 @@ public class RainbowHighlighter {
return Registry.is("editor.rainbow.identifiers", false);
}
public static void registerByPassLanguage(@NotNull Language language) {
BY_PASS_LANGUAGES.add(language);
}
public static boolean isByPassLanguage(@Nullable Language language) {
return BY_PASS_LANGUAGES.contains(language);
}
@NotNull
public TextAttributes getAttributes(@NotNull String name, @NotNull TextAttributes origin) {
int hash = StringHash.murmur(name, 0);
@@ -62,11 +60,34 @@ public class RainbowHighlighter {
//System.out.println("name = " + name + " \tv=" + v);
final Color color = Color.getHSBColor(v, 0.7f, myFloats[2] + .3f);
Color bkColor = origin.getBackgroundColor();
if (bkColor == null) {
bkColor = myColorsScheme.getAttributes(HighlighterColors.TEXT).getBackgroundColor();
}
if (bkColor == null) {
bkColor = myDefaultBackground;
}
return TextAttributes.fromFlyweight(origin
.getFlyweight()
.withForeground(color)
//fixme: uta: foreground color is not activated for local variables without background color reset
.withBackground(UIManager.getColor("EditorPane.background"))
.withBackground(bkColor)
);
}
public HighlightInfo getInfo(
@Nullable String nameKey,
@Nullable PsiElement id,
@Nullable TextAttributesKey colorKey) {
if (id == null || nameKey == null || StringUtil.isEmpty(nameKey)) return null;
if (colorKey == null) colorKey = DefaultLanguageHighlighterColors.LOCAL_VARIABLE;
final TextAttributes attributes = getAttributes(nameKey, myColorsScheme.getAttributes(colorKey));
return HighlightInfo
.newHighlightInfo(RAINBOW_ELEMENT)
.textAttributes(attributes)
.range(id)
.create();
}
}
@@ -0,0 +1,41 @@
/*
* 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.
*/
package com.intellij.codeInsight.daemon;
import com.intellij.codeHighlighting.RainbowHighlighter;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface RainbowProvider {
ExtensionPointName<RainbowProvider> EP_NAME = ExtensionPointName.create("com.intellij.rainbowProvider");
@NotNull
static RainbowProvider[] getRainbowFileProcessors() {
return Extensions.getExtensions(EP_NAME);
}
boolean isValidContext(@NotNull final PsiFile file);
List<HighlightInfo> getHighlights(@NotNull PsiFile file,
@NotNull RainbowHighlighter highlighter,
@NotNull ProgressIndicator progress);
}
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.RainbowHighlighter;
import com.intellij.codeInsight.daemon.GutterMark;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.RainbowProvider;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInspection.*;
@@ -48,6 +49,7 @@ import com.intellij.util.BitUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -181,15 +183,26 @@ public class HighlightInfo implements Segment {
TextAttributes attributes = getAttributesByType(element, type, colorsScheme);
if (element != null &&
RainbowHighlighter.isRainbowEnabled() &&
!RainbowHighlighter.isByPassLanguage(element.getLanguage()) &&
!isByPass(element) &&
isLikeVariable(type.getAttributesKey())) {
String text = element.getContainingFile().getText();
String name = text.substring(startOffset, endOffset);
attributes = new RainbowHighlighter(colorsScheme).getAttributes(name, attributes);
attributes = new RainbowHighlighter(colorsScheme, null).getAttributes(name, attributes);
}
return attributes;
}
@Contract("null -> false")
public static boolean isByPass(@Nullable PsiElement element) {
if (element == null) return false;
PsiFile containingFile = element.getContainingFile();
for (RainbowProvider processor : RainbowProvider.getRainbowFileProcessors()) {
if (processor.isValidContext(containingFile)) return true;
}
return false;
}
@Contract("null -> false")
private static boolean isLikeVariable(TextAttributesKey key) {
if (key == null) return false;
TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
@@ -32,13 +32,13 @@ public abstract class LookAheadLexer extends LexerBase{
private final Queue<IElementType> myTypeCache;
private final Queue<Integer> myEndOffsetCache;
public LookAheadLexer(final Lexer baseLexer, int capacity) {
public LookAheadLexer(@NotNull Lexer baseLexer, int capacity) {
myBaseLexer = baseLexer;
myTypeCache = new Queue<IElementType>(capacity);
myEndOffsetCache = new Queue<Integer>(capacity);
}
public LookAheadLexer(final Lexer baseLexer) {
public LookAheadLexer(@NotNull Lexer baseLexer) {
this(baseLexer, 64);
}
@@ -52,7 +52,7 @@ public abstract class LookAheadLexer extends LexerBase{
myEndOffsetCache.addLast(endOffset);
}
protected void lookAhead(Lexer baseLexer) {
protected void lookAhead(@NotNull Lexer baseLexer) {
advanceLexer(baseLexer);
}
@@ -20,9 +20,19 @@ import com.intellij.openapi.application.ModalityState;
import org.jetbrains.annotations.NotNull;
public class EmptyProgressIndicator implements StandardProgressIndicator {
@NotNull private final ModalityState myModalityState;
private volatile boolean myIsRunning;
private volatile boolean myIsCanceled;
public EmptyProgressIndicator() {
this(ModalityState.defaultModalityState());
}
public EmptyProgressIndicator(@NotNull ModalityState modalityState) {
myModalityState = modalityState;
}
@Override
public void start() {
myIsRunning = true;
@@ -108,7 +118,7 @@ public class EmptyProgressIndicator implements StandardProgressIndicator {
@Override
@NotNull
public ModalityState getModalityState() {
return ModalityState.NON_MODAL;
return myModalityState;
}
@Override
@@ -1,23 +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 org.jetbrains.concurrency;
import org.jetbrains.annotations.NotNull;
public interface AsyncFunction<PARAM, RESULT> {
@NotNull
Promise<RESULT> fun(PARAM param);
}
@@ -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.
@@ -203,7 +203,7 @@ public class AsyncPromise<T> extends Promise<T> implements Getter<T> {
@Override
@NotNull
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull final AsyncFunction<? super T, SUB_RESULT> fulfilled) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull final Function<? super T, Promise<SUB_RESULT>> fulfilled) {
switch (state) {
case PENDING:
break;
@@ -1,39 +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 org.jetbrains.concurrency;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class CountDownConsumer<T> implements Consumer<T> {
private volatile int countDown;
private final AsyncPromise<T> promise;
private final T totalResult;
public CountDownConsumer(int countDown, @NotNull AsyncPromise<T> promise, @Nullable T totalResult) {
this.countDown = countDown;
this.promise = promise;
this.totalResult = totalResult;
}
@Override
public void consume(T t) {
if (--countDown == 0) {
promise.setResult(totalResult);
}
}
}
@@ -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.
@@ -68,7 +68,7 @@ class DonePromise<T> extends Promise<T> implements Getter<T> {
@NotNull
@Override
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done) {
return done.fun(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.
@@ -28,7 +28,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
public abstract class Promise<T> {
public static final Promise<Void> DONE = new DonePromise<Void>(null);
@@ -70,40 +69,6 @@ public abstract class Promise<T> {
}
}
@NotNull
public static Promise<?> all(@NotNull Collection<Promise<?>> promises) {
if (promises.size() == 1) {
return promises instanceof List ? ((List<Promise<?>>)promises).get(0) : promises.iterator().next();
}
else {
return all(promises, null);
}
}
@NotNull
public static <T> Promise<T> all(@NotNull Collection<Promise<?>> promises, @Nullable T totalResult) {
if (promises.isEmpty()) {
//noinspection unchecked
return (Promise<T>)DONE;
}
final AsyncPromise<T> totalPromise = new AsyncPromise<T>();
Consumer done = new CountDownConsumer<T>(promises.size(), totalPromise, totalResult);
Consumer<Throwable> rejected = new Consumer<Throwable>() {
@Override
public void consume(Throwable error) {
totalPromise.setError(error);
}
};
for (Promise<?> promise : promises) {
//noinspection unchecked
promise.done(done);
promise.rejected(rejected);
}
return totalPromise;
}
public static <T> Promise<T> any(@NotNull final Collection<Promise<T>> promises, @NotNull final String totalError) {
if (promises.isEmpty()) {
//noinspection unchecked
@@ -187,7 +152,7 @@ public abstract class Promise<T> {
public abstract <SUB_RESULT> Promise<SUB_RESULT> then(@NotNull Function<? super T, ? extends SUB_RESULT> done);
@NotNull
public abstract <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done);
public abstract <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done);
@NotNull
public abstract State getState();
@@ -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.
@@ -63,7 +63,7 @@ class RejectedPromise<T> extends Promise<T> {
@NotNull
@Override
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done) {
//noinspection unchecked
return (Promise<SUB_RESULT>)this;
}
@@ -1153,7 +1153,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
childNode.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, Boolean.TRUE);
}
assert rootNode.textMatches(myText) : rootNode.getElementType();
assert rootNode.getTextLength() == myText.length() : rootNode.getElementType();
return rootNode;
}
@@ -313,23 +313,53 @@ public class CoreProgressManager extends ProgressManager implements Disposable {
runProcessWithProgressSynchronously(task, null);
}
else {
new TaskRunnable(task, new EmptyProgressIndicator()).run();
runProcessWithProgressInCurrentThread(task, new EmptyProgressIndicator(), ModalityState.defaultModalityState());
}
}
else if (task.isModal()) {
runProcessWithProgressSynchronously(task.asModal(), null);
runSynchronously(task.asModal());
}
else {
final Task.Backgroundable backgroundable = task.asBackgroundable();
if (backgroundable.isConditionalModal() && !backgroundable.shouldStartInBackground()) {
runProcessWithProgressSynchronously(task, null);
runSynchronously(task);
}
else {
runProcessWithProgressAsynchronously(backgroundable);
runAsynchronously(backgroundable);
}
}
}
private void runSynchronously(@NotNull final Task task) {
Runnable runnable = new Runnable() {
@Override
public void run() {
runProcessWithProgressSynchronously(task, null);
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
runnable.run();
}
else {
ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.defaultModalityState());
}
}
private void runAsynchronously(@NotNull final Task.Backgroundable task) {
Runnable runnable = new Runnable() {
@Override
public void run() {
runProcessWithProgressAsynchronously(task);
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
runnable.run();
}
else {
ApplicationManager.getApplication().invokeLater(runnable, ModalityState.defaultModalityState());
}
}
@NotNull
public Future<?> runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task) {
return runProcessWithProgressAsynchronously(task, new EmptyProgressIndicator(), null);
@@ -339,7 +369,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable {
public Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task,
@NotNull final ProgressIndicator progressIndicator,
@Nullable final Runnable continuation) {
return runProcessWithProgressAsynchronously(task, progressIndicator, continuation, ModalityState.NON_MODAL);
return runProcessWithProgressAsynchronously(task, progressIndicator, continuation, ModalityState.defaultModalityState());
}
@NotNull
@@ -408,6 +438,43 @@ public class CoreProgressManager extends ProgressManager implements Disposable {
return result;
}
public void runProcessWithProgressInCurrentThread(@NotNull final Task task,
@NotNull final ProgressIndicator progressIndicator,
@NotNull final ModalityState modalityState) {
if (progressIndicator instanceof Disposable) {
Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator);
}
final Runnable process = new TaskRunnable(task, progressIndicator);
boolean processCanceled = false;
Exception exception = null;
try {
runProcess(process, progressIndicator);
}
catch (ProcessCanceledException e) {
processCanceled = true;
}
catch (Exception e) {
exception = e;
}
final boolean finalCanceled = processCanceled || progressIndicator.isCanceled();
final Exception finalException = exception;
if (ApplicationManager.getApplication().isDispatchThread()) {
finishTask(task, finalCanceled, finalException);
}
else {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
finishTask(task, finalCanceled, finalException);
}
}, modalityState);
}
}
static void finishTask(@NotNull Task task, boolean canceled, @Nullable Exception exception) {
try {
if (exception != null) {
@@ -15,8 +15,11 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.concurrency.JobScheduler;
import com.intellij.extapi.psi.StubBasedPsiElementBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.impl.source.tree.AstPath;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.reference.SoftReference;
@@ -27,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* A weak cache for all instantiated stub-based PSI to allow {@link CompositeElement#getPsi()} return it when AST is reloaded.<p/>
@@ -35,24 +37,22 @@ import java.util.concurrent.TimeUnit;
*/
class AstPathPsiMap {
/**
* Not using ConcurrentWeakValueMap because we need to clean them up as ASTs in thousands of files are created and gc-ed.
* So we have a single shared reference queue {@link MyReference#ourQueue} for that.
* Not using ConcurrentWeakValueMap because we need to clean each of them up separately, when ASTs in thousands of files are created and gc-ed.
* So we have a per-project single shared reference queue {@link #myQueue} for that.
* Otherwise the files end up retaining lots of maps with all-gc-ed stuff inside, but the maps are still very large.
*/
private final ConcurrentMap<AstPath, MyReference> myMap = ContainerUtil.newConcurrentMap();
static {
JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// clean up AstPath objects when no PSI is accessed, e.g. after project closing
processQueue();
}
}, 5, 5, TimeUnit.SECONDS);
private static final Key<MyReferenceQueue> STUB_PSI_REFS = Key.create("STUB_PSI_REFS");
private final MyReferenceQueue myQueue;
AstPathPsiMap(@NotNull Project project) {
MyReferenceQueue queue = project.getUserData(STUB_PSI_REFS);
myQueue = queue != null ? queue : ((UserDataHolderEx)project).putUserDataIfAbsent(STUB_PSI_REFS, new MyReferenceQueue());
}
void invalidatePsi() {
processQueue();
myQueue.cleanupStaleReferences();
for (MyReference reference : myMap.values()) {
StubBasedPsiElementBase<?> psi = SoftReference.dereference(reference);
if (psi != null) {
@@ -63,7 +63,7 @@ class AstPathPsiMap {
}
void switchToStrongRefs() {
processQueue();
myQueue.cleanupStaleReferences();
for (MyReference reference : myMap.values()) {
StubBasedPsiElementBase<?> psi = SoftReference.dereference(reference);
if (psi != null) {
@@ -82,30 +82,38 @@ class AstPathPsiMap {
@NotNull
StubBasedPsiElementBase<?> cachePsi(@NotNull AstPath key, @NotNull StubBasedPsiElementBase psi) {
processQueue();
myMap.put(key, new MyReference(psi, key));
myQueue.cleanupStaleReferences();
myMap.put(key, new MyReference(psi, key, myQueue));
psi.setSubstrateRef(key);
return psi;
}
private static void processQueue() {
while (true) {
MyReference reference = (MyReference)MyReference.ourQueue.poll();
if (reference == null) break;
AstPath key = reference.pathRef;
key.getContainingFile().getRefToPsi().myMap.remove(key, reference);
}
}
private static class MyReference extends WeakReference<StubBasedPsiElementBase<?>> {
static final ReferenceQueue<StubBasedPsiElementBase<?>> ourQueue = new ReferenceQueue<StubBasedPsiElementBase<?>>();
final AstPath pathRef;
MyReference(StubBasedPsiElementBase psi, AstPath ref) {
super(psi, ourQueue);
MyReference(StubBasedPsiElementBase psi, AstPath ref, ReferenceQueue<StubBasedPsiElementBase<?>> queue) {
super(psi, queue);
pathRef = ref;
}
}
private static class MyReferenceQueue extends ReferenceQueue<StubBasedPsiElementBase<?>> {
@SuppressWarnings("unused") LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
cleanupStaleReferences();
}
});
void cleanupStaleReferences() {
while (true) {
MyReference reference = (MyReference)poll();
if (reference == null) break;
AstPath key = reference.pathRef;
key.getContainingFile().getRefToPsi().myMap.remove(key, reference);
}
}
}
}
@@ -73,7 +73,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
private boolean myInvalidated;
private volatile boolean myAstLoaded;
private volatile boolean myUseStrongRefs;
private AstPathPsiMap myRefToPsi = new AstPathPsiMap();
private AstPathPsiMap myRefToPsi;
private final ThreadLocal<FileElement> myFileElementBeingLoaded = new ThreadLocal<FileElement>();
protected final PsiManagerEx myManager;
private volatile Getter<FileElement> myTreeElementPointer; // SoftReference/WeakReference to ASTNode or a strong reference to a tree if the file is a DummyHolder
@@ -87,6 +87,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected PsiFileImpl(@NotNull FileViewProvider provider ) {
myManager = (PsiManagerEx)provider.getManager();
myViewProvider = provider;
myRefToPsi = new AstPathPsiMap(getProject());
}
public void setContentElementType(final IElementType contentElementType) {
@@ -482,7 +483,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
PsiFileImpl clone = BlockSupportImpl.getFileCopy(this, providerCopy);
copyCopyableDataTo(clone);
clone.myRefToPsi = new AstPathPsiMap();
clone.myRefToPsi = new AstPathPsiMap(getProject());
if (getTreeElement() != null) {
// not set by provider in clone
final FileElement treeClone = (FileElement)calcTreeElement().clone();
@@ -776,7 +777,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected PsiFileImpl cloneImpl(FileElement treeElementClone) {
PsiFileImpl clone = (PsiFileImpl)super.clone();
clone.myRefToPsi = new AstPathPsiMap();
clone.myRefToPsi = new AstPathPsiMap(getProject());
clone.setTreeElementPointer(treeElementClone); // should not use setTreeElement here because cloned file still have VirtualFile (SCR17963)
treeElementClone.setPsi(clone);
return clone;
@@ -38,8 +38,9 @@ public class PsiMultiReference implements PsiPolyVariantReference {
public static final Comparator<PsiReference> COMPARATOR = new Comparator<PsiReference>() {
@Override
public int compare(final PsiReference ref1, final PsiReference ref2) {
if (ref1.isSoft() && !ref2.isSoft()) return 1;
if (!ref1.isSoft() && ref2.isSoft()) return -1;
boolean soft1 = ref1.isSoft();
boolean soft2 = ref2.isSoft();
if (soft1 != soft2) return soft1 ? 1 : -1;
boolean resolves1 = resolves(ref1);
boolean resolves2 = resolves(ref2);
@@ -210,7 +210,7 @@ public class LazyParseableElement extends CompositeElement {
AstPath.cacheNodePaths(this);
assert super.textMatches(text) : "Text mismatch in " + getElementType();
assertTextLengthIntact(text.length());
myText = new SoftReference<CharSequence>(text);
}
}
@@ -219,6 +219,14 @@ public class LazyParseableElement extends CompositeElement {
}
}
private void assertTextLengthIntact(int expected) {
int length = 0;
for (ASTNode node : getChildren(null)) {
length += node.getTextLength();
}
assert length == expected : "Text mismatch in " + getElementType();
}
@Override
public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) {
if (!isParsed()) {

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