mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Generated
+2
-2
@@ -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!/" />
|
||||
|
||||
Generated
+2
-2
@@ -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>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
-6
@@ -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);
|
||||
}
|
||||
|
||||
-20
@@ -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;
|
||||
|
||||
-8
@@ -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);
|
||||
|
||||
+11
-4
@@ -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
|
||||
|
||||
+12
-17
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+55
-41
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-29
@@ -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;
|
||||
|
||||
+6
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+12
-9
@@ -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;
|
||||
}
|
||||
|
||||
+3
-3
@@ -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());
|
||||
|
||||
+4
-3
@@ -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();
|
||||
|
||||
+10
-10
@@ -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];
|
||||
|
||||
+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();
|
||||
|
||||
+22
-23
@@ -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);
|
||||
}
|
||||
|
||||
+67
-71
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+24
-26
@@ -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);
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
+6
-6
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -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) {
|
||||
|
||||
+1
-2
@@ -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;
|
||||
|
||||
+8
@@ -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)) {
|
||||
|
||||
+12
-15
@@ -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;
|
||||
}
|
||||
|
||||
+7
-1
@@ -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(){
|
||||
|
||||
+17
@@ -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);
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;}
|
||||
|
||||
}
|
||||
|
||||
+28
@@ -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)
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
// "Replace with lambda" "false"
|
||||
// "Replace with lambda" "true"
|
||||
class A {
|
||||
{
|
||||
bar(new Throwabl<caret>eComputable<String, Exception>() {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Replace with lambda" "false"
|
||||
// "Replace with lambda" "true"
|
||||
import java.util.*;
|
||||
class Test2 {
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Replace with lambda" "false"
|
||||
// "Replace with lambda" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Replace with lambda" "false"
|
||||
// "Replace with lambda" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
+1
-1
@@ -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
-1
@@ -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;
|
||||
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
void foo() {
|
||||
String s = "5<selection>+5</selection>";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class Test {
|
||||
public static final String xxx = "+5";
|
||||
|
||||
void foo() {
|
||||
String s = "5" + xxx;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
void print(Stirng s) {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
print("<selection>5</selection>");
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Test {
|
||||
public static final String xxx = "5";
|
||||
|
||||
void print(Stirng s) {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
print(xxx);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
class A {
|
||||
public void test() {
|
||||
boolean str = true;
|
||||
String str = "true";
|
||||
String s = "ss" + str;
|
||||
}
|
||||
}
|
||||
+7
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -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());
|
||||
}
|
||||
}
|
||||
+9
@@ -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.
Binary file not shown.
Binary file not shown.
@@ -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.
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;
|
||||
|
||||
+3
-2
@@ -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
Reference in New Issue
Block a user