Merge remote-tracking branch 'origin/master' into develar/is

# Conflicts:
#	platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
This commit is contained in:
Vladimir Krivosheev
2016-07-01 13:12:59 +02:00
546 changed files with 9620 additions and 6711 deletions
+2 -2
View File
@@ -1,8 +1,7 @@
<component name="libraryTable">
<library name="Mocks">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymockclassextension.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
@@ -10,6 +9,7 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
+2 -2
View File
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="pty4j">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7-src.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7.1-src.jar!/" />
</SOURCES>
</library>
</component>
+1 -1
View File
@@ -279,7 +279,7 @@ libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", vers
libraryLicense(name: "pockets", attachedTo: "python-helpers", version: "0.2.4", license: "BSD", url: "http://pockets.readthedocs.org/")
libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "https://github.com/google/protobuf/blob/master/LICENSE")
libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20131209", license: "New BSD License", url: "http://code.google.com/p/proxy-vole/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7.1", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "PureJavaComm", libraryName: "purejavacomm", version: "0.0.16", license: "BSD", url: "http://www.sparetimelabs.com/purejavacomm")
libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Relax NG Object Model", libraryName: "rngom-20051226-patched.jar", license: "MIT", url: "http://java.net/projects/rngom/", licenseUrl: "http://www.opensource.org/licenses/mit-license.php")
@@ -21,6 +21,8 @@ import com.intellij.debugger.engine.JVMNameUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.MethodBytecodeUtil;
import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.debugger.ui.tree.ValueDescriptor;
@@ -32,6 +34,11 @@ import com.intellij.psi.PsiClass;
import com.intellij.util.containers.ContainerUtil;
import com.sun.jdi.*;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public class JumpToObjectAction extends DebuggerAction{
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.actions.JumpToObjectAction");
@@ -96,7 +103,35 @@ public class JumpToObjectAction extends DebuggerAction{
}
if(type instanceof ClassType) {
final ClassType clsType = (ClassType)type;
final Location location = ContainerUtil.getFirstItem(clsType.allLineLocations());
Location lambdaLocation = null;
if (DebuggerUtilsEx.isLambdaClassName(clsType.name())) {
List<Method> notConstructorMethods = ContainerUtil.filter(clsType.methods(), m -> !m.isConstructor());
if (notConstructorMethods.size() == 1) {
AtomicReference<Location> locationRef = new AtomicReference<>();
MethodBytecodeUtil.visit(clsType, notConstructorMethods.get(0), new MethodVisitor(Opcodes.ASM5) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
ReferenceType cls = ContainerUtil.getFirstItem(clsType.virtualMachine().classesByName(owner));
if (cls != null) {
Method method = ContainerUtil.getFirstItem(cls.methodsByName(name));
if (method != null) {
try {
Location loc = ContainerUtil.getFirstItem(method.allLineLocations());
if (loc != null) {
locationRef.set(loc);
}
}
catch (AbsentInformationException e) {
LOG.debug(e);
}
}
}
}
});
lambdaLocation = locationRef.get();
}
}
final Location location = lambdaLocation != null ? lambdaLocation : ContainerUtil.getFirstItem(clsType.allLineLocations());
if (location != null) {
return ApplicationManager.getApplication().runReadAction(new Computable<SourcePosition>() {
@Override
@@ -118,10 +153,7 @@ public class JumpToObjectAction extends DebuggerAction{
}
}
}
catch (ClassNotPreparedException e) {
LOG.debug(e);
}
catch (AbsentInformationException e) {
catch (ClassNotPreparedException | AbsentInformationException e) {
LOG.debug(e);
}
return null;
@@ -150,13 +150,12 @@ public class LocalVariablesUtil {
com.sun.jdi.Method method = frameProxy.location().method();
final int firstLocalVariableSlot = getFirstLocalsSlot(method);
final int firstArgsSlot = getFirstArgsSlot(method);
// gather code variables names
MultiMap<Integer, String> namesMap = calcNames(new SimpleStackFrameContext(frameProxy, process), firstLocalVariableSlot, firstArgsSlot);
MultiMap<Integer, String> namesMap = calcNames(new SimpleStackFrameContext(frameProxy, process), firstLocalVariableSlot);
// first add arguments
int slot = firstArgsSlot;
int slot = getFirstArgsSlot(method);
List<String> typeNames = method.argumentTypeNames();
List<Value> argValues = frameProxy.getArgumentValues();
for (int i = 0; i < argValues.size(); i++) {
@@ -317,9 +316,7 @@ public class LocalVariablesUtil {
}
@NotNull
private static MultiMap<Integer, String> calcNames(@NotNull final StackFrameContext context,
final int firstLocalsSlot,
final int firstArgsSlot) {
private static MultiMap<Integer, String> calcNames(@NotNull final StackFrameContext context, final int firstLocalsSlot) {
return ApplicationManager.getApplication().runReadAction(new Computable<MultiMap<Integer, String>>() {
@Override
public MultiMap<Integer, String> compute() {
@@ -329,7 +326,7 @@ public class LocalVariablesUtil {
PsiElement method = DebuggerUtilsEx.getContainingMethod(element);
if (method != null) {
MultiMap<Integer, String> res = new MultiMap<>();
int slot = Math.max(0, firstArgsSlot + firstLocalsSlot - getFirstLocalsSlot(method));
int slot = Math.max(0, firstLocalsSlot - getParametersStackSize(method));
for (PsiParameter parameter : DebuggerUtilsEx.getParameters(method)) {
res.putValue(slot, parameter.getName());
slot += getTypeSlotSize(parameter.getType());
@@ -481,11 +478,8 @@ public class LocalVariablesUtil {
}
}
private static int getFirstLocalsSlot(PsiElement method) {
private static int getParametersStackSize(PsiElement method) {
int startSlot = 0;
if (method instanceof PsiModifierListOwner) {
startSlot = ((PsiModifierListOwner)method).hasModifierProperty(PsiModifier.STATIC) ? 0 : 1;
}
for (PsiParameter parameter : DebuggerUtilsEx.getParameters(method)) {
startSlot += getTypeSlotSize(parameter.getType());
}
@@ -0,0 +1,88 @@
/*
* 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.debugger.jdi;
import com.sun.jdi.ClassType;
import com.sun.jdi.Method;
import com.sun.jdi.ReferenceType;
import org.jetbrains.org.objectweb.asm.*;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* @author egor
*/
public class MethodBytecodeUtil {
private MethodBytecodeUtil() {
}
/**
* Allows to use ASM MethodVisitor with jdi method bytecode
*/
public static void visit(ClassType classType, Method method, MethodVisitor methodVisitor) {
try {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeInt(0xCAFEBABE); // magic
dos.writeInt(Opcodes.V1_8); // version
dos.writeShort(classType.constantPoolCount()); // constant_pool_count
dos.write(classType.constantPool()); // constant_pool
// we generate and put code attribute right after the constant pool
byte[] bytecodes = method.bytecodes();
int codeSize = dos.size();
dos.writeShort(0); // max_stack
dos.writeShort(0); // max_locals
dos.writeInt(bytecodes.length); // code_length
dos.write(bytecodes); // code
dos.writeShort(0); // exception_table_length
dos.writeShort(0); // attributes_count
codeSize = dos.size() - codeSize;
ClassReader clsReader = new ClassReader(bos.toByteArray());
ClassWriter clsWriter = new ClassWriter(clsReader, 0);
clsWriter.visit(Opcodes.V1_8,
Opcodes.ACC_PUBLIC,
classType.name(),
classType.signature(),
classType.superclass().name(),
classType.interfaces().stream().map(ReferenceType::name).toArray(String[]::new));
MethodVisitor mv = clsWriter.visitMethod(Opcodes.ACC_PUBLIC, method.name(), method.signature(), method.signature(), null);
mv.visitAttribute(createCode(clsReader, codeSize));
new ClassReader(clsWriter.toByteArray()).accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return methodVisitor;
}
}, 0);
}
}
catch (IOException ignored) {
}
}
private static Attribute createCode(ClassReader cr, int len) {
return new Attribute("Code") {
@Override
public Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
return super.read(cr, off, len, buf, codeOff, labels);
}
}.read(cr, cr.header, len, null, 0, null);
}
}
@@ -156,7 +156,6 @@ public abstract class JavaTestFrameworkRunnableState<T extends
@Override
public void processTerminated(ProcessEvent event) {
Runnable runnable = () -> {
root.flush();
deleteTempFiles();
clear();
};
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.TestFrameworks;
import com.intellij.codeInsight.actions.FormatChangedTextUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.changes.Change;
@@ -28,6 +27,7 @@ import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.diff.FilesTooBigForDiffException;
@@ -99,7 +99,9 @@ public class TestDiscoverySearchHelper {
});
}
return patterns;
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final GlobalSearchScope searchScope = GlobalSearchScope.projectScope(project);
return new HashSet<>(ContainerUtil.filter(patterns, fqn -> psiFacade.findClass(fqn, searchScope) != null));
}
private static void collectPatterns(final Project project,
@@ -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());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 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.
@@ -255,8 +255,7 @@ public abstract class QuickFixFactory {
public abstract IntentionAction createSafeDeleteFix(@NotNull PsiElement element);
@Nullable
public abstract List<LocalQuickFix> registerOrderEntryFixes(@NotNull QuickFixActionRegistrar registrar,
@NotNull PsiReference reference);
public abstract List<LocalQuickFix> registerOrderEntryFixes(@NotNull QuickFixActionRegistrar registrar, @NotNull PsiReference reference);
@NotNull
public abstract IntentionAction createAddMissingRequiredAnnotationParametersFix(@NotNull PsiAnnotation annotation,
@@ -274,5 +273,5 @@ public abstract class QuickFixFactory {
@NotNull
public IntentionAction createWrapWithOptionalFix(@Nullable PsiType type, @NotNull PsiExpression expression) {
throw new UnsupportedOperationException();
};
}
}
}
@@ -1521,6 +1521,9 @@ public class HighlightUtil extends HighlightUtilBase {
}
else {
aClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class);
if (aClass instanceof PsiAnonymousClass && PsiTreeUtil.isAncestor(((PsiAnonymousClass)aClass).getArgumentList(), expr, false)) {
aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true);
}
}
if (aClass == null) return null;
@@ -2981,7 +2984,8 @@ public class HighlightUtil extends HighlightUtilBase {
LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"),
TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"),
RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers"),
REFS_AS_RESOURCE(LanguageLevel.JDK_1_9, "feature.try.with.resources.refs");
REFS_AS_RESOURCE(LanguageLevel.JDK_1_9, "feature.try.with.resources.refs"),
MODULES(LanguageLevel.JDK_1_9, "feature.modules");
private final LanguageLevel level;
private final String key;
@@ -3007,4 +3011,4 @@ public class HighlightUtil extends HighlightUtilBase {
return null;
}
}
}
@@ -1598,19 +1598,27 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverType(parameter));
}
@Override
public void visitModule(PsiJavaModule module) {
super.visitModule(module);
if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(module, Feature.MODULES));
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileName(module, myFile));
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileDuplicates(module, myFile));
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileLocation(module, myFile));
}
@Nullable
private HighlightInfo checkFeature(@NotNull PsiElement element, @NotNull Feature feature) {
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
}
protected void prepareToRunAsInspection(@NotNull HighlightInfoHolder holder) {
myHolder = holder;
PsiFile file = holder.getContextFile();
JavaSdkVersion sdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(file);
final PsiFile file = holder.getContextFile();
myHolder = holder;
myFile = file;
myLanguageLevel = PsiUtil.getLanguageLevel(file);
myJavaSdkVersion = ObjectUtils.notNull(JavaVersionService.getInstance().getJavaSdkVersion(file),
JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
myJavaSdkVersion = sdkVersion != null ? sdkVersion : JavaSdkVersion.fromLanguageLevel(myLanguageLevel);
}
}
@@ -0,0 +1,99 @@
/*
* 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.impl.analysis;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.MoveFileFix;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.impl.scopes.ModulesScope;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.PsiJavaModuleReference;
import com.intellij.psi.search.FilenameIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
public class ModuleHighlightUtil {
private static final String MODULE_FILE_NAME = "module-info.java";
@Nullable
static HighlightInfo checkFileName(@NotNull PsiJavaModule element, @NotNull PsiFile file) {
if (!MODULE_FILE_NAME.equals(file.getName())) {
String message = JavaErrorMessages.message("module.file.wrong.name");
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).description(message).create();
QuickFixAction.registerQuickFixAction(info, factory().createRenameFileFix(MODULE_FILE_NAME));
return info;
}
return null;
}
@Nullable
static HighlightInfo checkFileDuplicates(@NotNull PsiJavaModule element, @NotNull PsiFile file) {
VirtualFile vFile = file.getVirtualFile();
if (vFile != null) {
Project project = file.getProject();
Module module = ProjectFileIndex.SERVICE.getInstance(project).getModuleForFile(vFile);
if (module != null) {
Collection<VirtualFile> others =
FilenameIndex.getVirtualFilesByName(project, MODULE_FILE_NAME, new ModulesScope(Collections.singleton(module), project));
if (others.size() > 1) {
String message = JavaErrorMessages.message("module.file.duplicate");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).description(message).create();
//todo show duplicates quick fix
}
}
}
return null;
}
@Nullable
static HighlightInfo checkFileLocation(@NotNull PsiJavaModule element, @NotNull PsiFile file) {
VirtualFile vFile = file.getVirtualFile();
if (vFile != null) {
VirtualFile root = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getSourceRootForFile(vFile);
if (root != null && !root.equals(vFile.getParent())) {
String message = JavaErrorMessages.message("module.file.wrong.location");
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(element)).description(message).create();
QuickFixAction.registerQuickFixAction(info, new MoveFileFix(vFile, root));
return info;
}
}
return null;
}
private static QuickFixFactory factory() {
return QuickFixFactory.getInstance();
}
private static TextRange range(PsiJavaModule module) {
PsiJavaModuleReference name = module.getNameElement();
return name != null ? new TextRange(module.getTextOffset(), name.getTextRange().getEndOffset()) : module.getTextRange();
}
}
@@ -406,12 +406,6 @@ class PostHighlightingVisitor {
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
if (!myRefCountHolder.isReferenced(parameter) && !UnusedSymbolUtil.isImplicitUsage(myProject, parameter, progress)) {
//parameter is defined by functional interface
final PsiElement declarationScope = parameter.getDeclarationScope();
if (declarationScope instanceof PsiMethod &&
myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope, myLanguageLevel)) {
return null;
}
String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
return UnusedSymbolUtil.createUnusedSymbolInfo(identifier, message, myDeadCodeInfoType);
}
@@ -222,26 +222,6 @@ class RefCountHolder {
return usedStatus == Boolean.TRUE;
}
boolean isReferencedByMethodReference(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return false;
Collection<PsiReference> array;
synchronized (myLocalRefsMap) {
array = myLocalRefsMap.get(method);
}
if (!array.isEmpty()) {
for (PsiReference reference : array) {
final PsiElement element = reference.getElement();
if (element instanceof PsiMethodReferenceExpression) {
return true;
}
}
}
return false;
}
private static boolean isParameterUsedRecursively(@NotNull PsiElement element, @NotNull Collection<PsiReference> array) {
if (!(element instanceof PsiParameter)) return false;
PsiParameter parameter = (PsiParameter)element;
@@ -0,0 +1,74 @@
/*
* 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.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class MoveFileFix implements IntentionAction {
private final VirtualFile myFile;
private final VirtualFile myTarget;
public MoveFileFix(@NotNull VirtualFile file, @NotNull VirtualFile target) {
myFile = file;
myTarget = target;
}
@Nls
@NotNull
@Override
public String getText() {
return QuickFixBundle.message("move.file.to.source.root.text");
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (myFile.isValid() && myTarget.isValid()) {
try {
myFile.move(this, myTarget);
}
catch (IOException e) {
throw new IncorrectOperationException("Cannot move '" + myFile.getPath() + "' into '" + myTarget.getPath() + "'", (Throwable)e);
}
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -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);
@@ -262,6 +254,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
final PsiCodeBlock body = method.getBody();
if (body == null) return null;
final Collection<PsiComment> comments = collectCommentsOutsideMethodBody(anonymousClass, body);
final Project project = element.getProject();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
@@ -285,12 +278,12 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
.giveUniqueNames(project, elementFactory, lambdaExpression,
usedLocalNames, variables.toArray(new PsiVariable[variables.size()]));
final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(
lambdaExpression.getBody());
final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression.getBody());
if (singleExpr != null) {
lambdaExpression.getBody().replace(singleExpr);
}
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
restoreComments(comments, lambdaExpression);
final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
if (forceIgnoreTypeCast) {
@@ -318,6 +311,16 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
return null;
}
private static Collection<PsiComment> collectCommentsOutsideMethodBody(PsiAnonymousClass anonymousClass, PsiCodeBlock body) {
final Collection<PsiComment> psiComments = PsiTreeUtil.findChildrenOfType(anonymousClass, PsiComment.class);
for (Iterator<PsiComment> iterator = psiComments.iterator(); iterator.hasNext(); ) {
if (PsiTreeUtil.isAncestor(body, iterator.next(), false)) {
iterator.remove();
}
}
return ContainerUtil.map(psiComments, (comment) -> (PsiComment)comment.copy());
}
private static void collectLocalVariablesDefinedInsideLambda(PsiLambdaExpression lambdaExpression,
final Set<PsiVariable> variables,
Set<String> namesOfVariablesInTheBlock) {
@@ -460,6 +463,16 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
return false;
}
public static void restoreComments(Collection<PsiComment> comments, PsiElement lambda) {
PsiElement anchor = PsiTreeUtil.getParentOfType(lambda, PsiStatement.class, PsiField.class);
if (anchor == null) {
anchor = lambda;
}
for (PsiComment comment : comments) {
anchor.getParent().addBefore(comment, anchor);
}
}
private static class ForbiddenRefsChecker extends JavaRecursiveElementWalkingVisitor {
private boolean myBodyContainsForbiddenRefs;
@@ -518,13 +518,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
replace = replace.replace(cast);
}
PsiElement anchor = PsiTreeUtil.getParentOfType(replace, PsiStatement.class);
if (anchor == null) {
anchor = replace;
}
for (PsiComment comment : comments) {
anchor.getParent().addBefore(comment, anchor);
}
AnonymousCanBeLambdaInspection.restoreComments(comments, replace);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replace);
}
}
@@ -81,9 +81,16 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
}
final PsiMethodCallExpression qualifierCall = getQualifierMethodCall(methodCall);
if (isCallOf(qualifierCall, CommonClassNames.JAVA_UTIL_COLLECTION, STREAM_METHOD, 0)) {
holder.registerProblem(methodCall, getCallChainRange(methodCall, qualifierCall),
"Collection.stream()." + name + "() can be replaced with Collection.forEach()",
FOR_EACH_METHOD.equals(name) ? new CollectionForEachFix() : new CollectionForEachOrderedFix());
String message = "Collection.stream()." + name + "() can be replaced with Collection.forEach()";
final LocalQuickFix fix;
if (FOR_EACH_METHOD.equals(name)) {
fix = new CollectionForEachFix();
}
else {
fix = new CollectionForEachOrderedFix();
message += " (may change semantics)";
}
holder.registerProblem(methodCall, getCallChainRange(methodCall, qualifierCall), message, fix);
}
}
}
@@ -221,7 +228,7 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
@NotNull
@Override
public String getFamilyName() {
return "Replace Collection.stream()." + FOR_EACH_ORDERED_METHOD + "() with Collection.forEach()";
return "Replace Collection.stream()." + FOR_EACH_ORDERED_METHOD + "() with Collection.forEach() (may change semantics)";
}
@Override
@@ -17,6 +17,7 @@ package com.intellij.codeInspection.reference;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -426,24 +427,19 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
@Override
public String getName() {
if (isValid()) {
final String[] result = new String[1];
final Runnable runnable = () -> {
return ReadAction.compute(() -> {
PsiMethod psiMethod = (PsiMethod) getElement();
if (psiMethod instanceof SyntheticElement) {
result[0] = psiMethod.getName();
return psiMethod.getName();
}
else {
result[0] = PsiFormatUtil.formatMethod(psiMethod,
return PsiFormatUtil.formatMethod(psiMethod,
PsiSubstitutor.EMPTY,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
PsiFormatUtilBase.SHOW_TYPE
);
}
};
ApplicationManager.getApplication().runReadAction(runnable);
return result[0];
});
} else {
return super.getName();
}
@@ -451,16 +447,11 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
@Override
public String getExternalName() {
final String[] result = new String[1];
final Runnable runnable = () -> {
return ReadAction.compute(() -> {
final PsiMethod psiMethod = (PsiMethod)getElement();
LOG.assertTrue(psiMethod != null);
result[0] = PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
};
ApplicationManager.getApplication().runReadAction(runnable);
return result[0];
return PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
});
}
@Nullable
@@ -686,4 +677,8 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS_MASK);
}
private static String extractMethodName(String methodSignature) {
final String returnTypeAndName = methodSignature.substring(0, methodSignature.indexOf('('));
return returnTypeAndName.substring(returnTypeAndName.indexOf(' ') + 1);
}
}
@@ -34,10 +34,10 @@ import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.fixes.ChangeModifierFix;
import com.siyeh.ig.psiutils.MethodUtils;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -87,7 +87,7 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)profile.getUnwrappedTool(UnusedDeclarationInspectionBase.SHORT_NAME, holder.getFile());
myDeadCodeInspection = tool == null ? new UnusedDeclarationInspectionBase() : tool;
}
private final Set<PsiClass> childMembersAreUsedOutsideMyPackage = ContainerUtil.newConcurrentSet();
private final TObjectIntHashMap<PsiClass> maxSuggestedLevelForChildMembers = new TObjectIntHashMap<>();
@Override
public void visitClass(PsiClass aClass) {
@@ -105,48 +105,79 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
}
private void checkMember(@NotNull final PsiMember member) {
if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return;
if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return;
final PsiClass memberClass = member.getContainingClass();
PsiModifierList memberModifierList = member.getModifierList();
if (memberModifierList == null) return;
int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
int suggestedLevel = suggestLevel(member, memberClass, currentLevel);
if (memberClass != null) {
synchronized (maxSuggestedLevelForChildMembers) {
int prevMax = maxSuggestedLevelForChildMembers.get(memberClass);
maxSuggestedLevelForChildMembers.put(memberClass, Math.max(prevMax, suggestedLevel));
}
}
log(member.getName() + ": effective level is '" + PsiUtil.getAccessModifier(suggestedLevel) + "'");
if (suggestedLevel < currentLevel) {
if (member instanceof PsiClass) {
int memberMaxLevel;
synchronized (maxSuggestedLevelForChildMembers) {
memberMaxLevel = maxSuggestedLevelForChildMembers.get((PsiClass)member);
}
if (memberMaxLevel > suggestedLevel) {
// a class can't have visibility less than its members
return;
}
}
PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner)member).getNameIdentifier() : ContainerUtil.find(
memberModifierList.getChildren(),
element -> element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel)));
assert toHighlight != null : member +" ; " + ((PsiNameIdentifierOwner)member).getNameIdentifier() + "; "+ memberModifierList.getText();
String suggestedModifier = PsiUtil.getAccessModifier(suggestedLevel);
myHolder.registerProblem(toHighlight, "Access can be " + VisibilityUtil.toPresentableText(suggestedModifier), new ChangeModifierFix(suggestedModifier));
}
}
private int suggestLevel(@NotNull PsiMember member, PsiClass memberClass, int currentLevel) {
if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return currentLevel;
if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return currentLevel;
if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod)member;
if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) {
log(member.getName() + " overrides");
return; // overrides
return currentLevel; // overrides
}
if (MethodUtils.isOverridden(method)) {
log(member.getName() + " overridden");
return;
return currentLevel;
}
}
if (member instanceof PsiEnumConstant) return;
if (member instanceof PsiEnumConstant) return currentLevel;
if (member instanceof PsiClass && (member instanceof PsiAnonymousClass ||
member instanceof PsiTypeParameter ||
member instanceof PsiSyntheticClass ||
PsiUtil.isLocalClass((PsiClass)member))) {
return;
return currentLevel;
}
final PsiClass memberClass = member.getContainingClass();
if (memberClass != null && (memberClass.isInterface() || memberClass.isEnum() || memberClass.isAnnotationType() || PsiUtil.isLocalClass(memberClass) && member instanceof PsiClass)) {
return;
return currentLevel;
}
final PsiFile memberFile = member.getContainingFile();
Project project = memberFile.getProject();
if (myDeadCodeInspection.isEntryPoint(member)) {
log(member.getName() +" is entry point");
return;
return currentLevel;
}
PsiModifierList memberModifierList = member.getModifierList();
if (memberModifierList == null) return;
final int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
final AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
final AtomicBoolean foundUsage = new AtomicBoolean();
PsiDirectory memberDirectory = memberFile.getContainingDirectory();
final PsiPackage memberPackage = memberDirectory == null ? null : JavaDirectoryService.getInstance().getPackage(memberDirectory);
log(member.getName()+ ": checking effective level for "+member);
AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
AtomicBoolean foundUsage = new AtomicBoolean();
boolean proceed = UnusedSymbolUtil.processUsages(project, memberFile, member, new EmptyProgressIndicator(), null, info -> {
PsiElement element = info.getElement();
if (element == null) return true;
@@ -165,30 +196,21 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
}
if (!foundUsage.get()) {
log(member.getName() + " unused; ignore");
return; // do not propose private for unused method
return currentLevel; // do not propose private for unused method
}
int max = maxLevel.get();
if (max == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
max = suggestPackageLocal(member);
int suggestedLevel = maxLevel.get();
if (suggestedLevel == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
suggestedLevel = suggestPackageLocal(member);
}
String maxModifier = PsiUtil.getAccessModifier(max);
log(member.getName() + ": effective level is '" + maxModifier + "'");
String suggestedModifier = PsiUtil.getAccessModifier(suggestedLevel);
log(member.getName() + ": effective level is '" + suggestedModifier + "'");
if (max < currentLevel) {
if (max == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL && member instanceof PsiClass && childMembersAreUsedOutsideMyPackage.contains(member)) {
log(member.getName() + " children used outside my package; ignore");
return; // e.g. some public method is used outside my package (without importing class)
}
PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner)member).getNameIdentifier() : ContainerUtil.find(
memberModifierList.getChildren(),
element -> element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel)));
assert toHighlight != null : member +" ; " + ((PsiNameIdentifierOwner)member).getNameIdentifier() + "; "+ memberModifierList.getText();
myHolder.registerProblem(toHighlight, "Access can be " + VisibilityUtil.toPresentableText(maxModifier), new ChangeModifierFix(maxModifier));
}
return suggestedLevel;
}
private boolean handleUsage(@NotNull PsiMember member,
@Nullable PsiClass memberClass,
@NotNull PsiFile memberFile,
@@ -201,20 +223,12 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
if (!(psiFile instanceof PsiJavaFile)) {
log(" refd from " + psiFile.getName() + "; set to public");
maxLevel.set(PsiUtil.ACCESS_LEVEL_PUBLIC);
if (memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return false; // referenced from XML, has to be public
}
//int offset = info.getNavigationOffset();
//if (offset == -1) return true;
@PsiUtil.AccessLevel
int level = getEffectiveLevel(element, psiFile, member, memberFile, memberClass, memberPackage);
log(" ref in file " + psiFile.getName() + "; level = " + PsiUtil.getAccessModifier(level) + "; (" + element + ")");
maxLevel.getAndAccumulate(level, Math::max);
if (level == PsiUtil.ACCESS_LEVEL_PUBLIC && memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return level != PsiUtil.ACCESS_LEVEL_PUBLIC;
}
@@ -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.
@@ -19,6 +19,8 @@ import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +29,9 @@ import org.jetbrains.annotations.NotNull;
* @author max
*/
public class JavaHighlightingLexer extends LayeredLexer {
private boolean myAtStart = true;
private boolean myModuleInfo = false;
public JavaHighlightingLexer(@NotNull LanguageLevel languageLevel) {
super(JavaParserDefinition.createLexer(languageLevel));
@@ -42,4 +47,27 @@ public class JavaHighlightingLexer extends LayeredLexer {
docLexer.registerLayer(htmlLexer, JavaDocTokenType.DOC_COMMENT_DATA);
registerSelfStoppingLayer(docLexer, new IElementType[]{JavaDocElementType.DOC_COMMENT}, IElementType.EMPTY_ARRAY);
}
}
@Override
public IElementType getTokenType() {
IElementType t = super.getTokenType();
if (myAtStart && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(t)) {
myAtStart = false;
myModuleInfo = t == JavaTokenType.IDENTIFIER && PsiKeyword.MODULE.equals(getTokenText());
}
if (myModuleInfo && t == JavaTokenType.IDENTIFIER) {
String text = getTokenText();
if (PsiKeyword.MODULE.equals(text)) t = JavaTokenType.MODULE_KEYWORD;
else if (PsiKeyword.REQUIRES.equals(text)) t = JavaTokenType.REQUIRES_KEYWORD;
else if (PsiKeyword.EXPORTS.equals(text)) t = JavaTokenType.EXPORTS_KEYWORD;
else if (PsiKeyword.USES.equals(text)) t = JavaTokenType.USES_KEYWORD;
else if (PsiKeyword.PROVIDES.equals(text)) t = JavaTokenType.PROVIDES_KEYWORD;
else if (PsiKeyword.TO.equals(text)) t = JavaTokenType.TO_KEYWORD;
else if (PsiKeyword.WITH.equals(text)) t = JavaTokenType.WITH_KEYWORD;
}
return t;
}
}
@@ -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 += "...";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -167,8 +167,7 @@ public class JavaElementSignatureProvider extends AbstractElementSignatureProvid
@Nullable StringBuilder processingInfoStorage)
{
if (type.equals("imports")) {
if (!(file instanceof PsiJavaFile)) return null;
return ((PsiJavaFile)file).getImportList();
return file instanceof PsiJavaFile ? ((PsiJavaFile)file).getImportList() : null;
}
else if (type.equals("method")) {
String name = tokenizer.nextToken();
@@ -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,
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
@@ -35,7 +36,6 @@ import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.intellij.util.containers.BidirectionalMap;
import org.jdom.Element;
@@ -138,13 +138,15 @@ public class EmptyMethodInspection extends GlobalJavaBatchInspectionTool {
if (message != null) {
final ArrayList<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
fixes.add(getFix(processor, needToDeleteHierarchy));
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(refMethod.getElement(), qualifiedName -> {
fixes.add(SpecialAnnotationsUtilBase.createAddToSpecialAnnotationsListQuickFix(
QuickFixBundle.message("fix.add.special.annotation.text", qualifiedName),
QuickFixBundle.message("fix.add.special.annotation.family"),
EXCLUDE_ANNOS, qualifiedName, refMethod.getElement()));
return true;
});
if (globalContext instanceof GlobalInspectionContextBase && ((GlobalInspectionContextBase)globalContext).getCurrentProfile().getSingleTool() == null) {
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(refMethod.getElement(), qualifiedName -> {
fixes.add(SpecialAnnotationsUtilBase.createAddToSpecialAnnotationsListQuickFix(
QuickFixBundle.message("fix.add.special.annotation.text", qualifiedName),
QuickFixBundle.message("fix.add.special.annotation.family"),
EXCLUDE_ANNOS, qualifiedName, refMethod.getElement()));
return true;
});
}
final ProblemDescriptor descriptor = manager.createProblemDescriptor(refMethod.getElement().getNavigationElement(), message, false,
fixes.toArray(new LocalQuickFix[fixes.size()]),
@@ -19,10 +19,14 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.JavaChangeInfo;
import com.intellij.refactoring.changeSignature.JavaChangeInfoImpl;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.NotNullFunction;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -66,8 +70,11 @@ public class ParameterCanBeLocalInspection extends ParameterCanBeLocalInspection
}
final ParameterInfoImpl[] newParams = info.toArray(new ParameterInfoImpl[info.size()]);
final String visibilityModifier = VisibilityUtil.getVisibilityModifier(method.getModifierList());
final ChangeSignatureProcessor cp = new ChangeSignatureProcessor(project, method, false, visibilityModifier,
method.getName(), method.getReturnType(), newParams) {
final PsiType returnType = method.getReturnType();
final JavaChangeInfo changeInfo = new JavaChangeInfoImpl(visibilityModifier, method, method.getName(),
returnType != null ? CanonicalTypes.createTypeWrapper(returnType) : null,
newParams, null, false, ContainerUtil.newHashSet(), ContainerUtil.newHashSet());
final ChangeSignatureProcessor cp = new ChangeSignatureProcessor(project, changeInfo) {
@Override
protected void performRefactoring(@NotNull UsageInfo[] usages) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
@@ -1278,8 +1278,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
public SyntheticCodeBlock createCodeBlockBlock(final List<Block> localResult, final Indent indent, final int childrenIndent) {
final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), myJavaSettings, indent, null);
result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null));
return result;
return result;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,13 +18,13 @@ package com.intellij.psi.impl.file;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.psi.*;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* @author Maxim.Mossienko
* Date: Sep 18, 2008
* Time: 3:33:07 PM
* @since Sep 18, 2008
*/
public class JavaUpdateAddedFileProcessor extends UpdateAddedFileProcessor {
@Override
@@ -34,14 +34,17 @@ public class JavaUpdateAddedFileProcessor extends UpdateAddedFileProcessor {
@Override
public void update(final PsiFile element, PsiFile originalElement) throws IncorrectOperationException {
if (element.getViewProvider() instanceof TemplateLanguageFileViewProvider) return;
if (element.getViewProvider() instanceof TemplateLanguageFileViewProvider || PsiUtil.isModuleFile(element)) {
return;
}
PsiDirectory dir = element.getContainingDirectory();
if (dir == null) return;
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(dir);
if (aPackage == null) return;
String packageName = aPackage.getQualifiedName();
((PsiClassOwner)element).setPackageName(packageName);
if (dir != null) {
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(dir);
if (aPackage != null) {
String packageName = aPackage.getQualifiedName();
((PsiClassOwner)element).setPackageName(packageName);
}
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 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.
@@ -66,6 +66,9 @@ public class ImportHelper{
}
public PsiImportList prepareOptimizeImportsResult(@NotNull final PsiJavaFile file) {
PsiImportList oldList = file.getImportList();
if (oldList == null) return null;
// Java parser works in a way that comments may be included to the import list, e.g.:
// import a;
// /* comment */
@@ -98,8 +101,8 @@ public class ImportHelper{
codeStyleManager.reformat(dummyFile);
PsiImportList newImportList = dummyFile.getImportList();
assert newImportList != null : dummyFile.getText();
PsiImportList result = (PsiImportList)newImportList.copy();
PsiImportList oldList = file.getImportList();
if (oldList.isReplaceEquivalent(result)) return null;
if (!nonImports.isEmpty()) {
PsiElement firstPrevious = newImportList.getPrevSibling();
@@ -431,6 +434,7 @@ public class ImportHelper{
try {
PsiImportList importList = file.getImportList();
assert importList != null : file;
PsiImportStatement statement = useOnDemand ? factory.createImportStatementOnDemand(packageName) : factory.createImportStatement(refClass);
importList.add(statement);
if (useOnDemand) {
@@ -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
@@ -118,8 +118,11 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase {
newVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList());
}
return new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate,
propagateParametersMethods, propagateExceptionsMethods);
final JavaChangeInfoImpl javaChangeInfo =
new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate,
propagateParametersMethods, propagateExceptionsMethods);
javaChangeInfo.setCheckUnusedParameter();
return javaChangeInfo;
}
@NotNull
@@ -151,6 +154,7 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase {
RenameUtil.removeConflictUsages(usagesSet);
if (!conflictDescriptions.isEmpty()) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
if (ConflictsInTestsException.isTestIgnore()) return true;
throw new ConflictsInTestsException(conflictDescriptions.values());
}
if (myPrepareSuccessfulSwingThreadCallback != null) {
@@ -68,4 +68,9 @@ public interface JavaChangeInfo extends ChangeInfo {
void updateMethod(PsiMethod psiMethod);
Collection<PsiMethod> getMethodsToPropagateParameters();
default boolean checkUnusedParameter() {
return false;
}
}
@@ -69,6 +69,8 @@ public class JavaChangeInfoImpl extends UserDataHolderBase implements JavaChange
final Set<PsiMethod> propagateParametersMethods;
final Set<PsiMethod> propagateExceptionsMethods;
private boolean myCheckUnusedParameter = false;
/**
* @param newExceptions null if not changed
*/
@@ -201,6 +203,15 @@ public class JavaChangeInfoImpl extends UserDataHolderBase implements JavaChange
}
}
@Override
public boolean checkUnusedParameter() {
return myCheckUnusedParameter;
}
public void setCheckUnusedParameter() {
myCheckUnusedParameter = true;
}
protected void fillOldParams(PsiMethod method) {
PsiParameter[] parameters = method.getParameterList().getParameters();
oldParameterNames = new String[parameters.length];
@@ -24,8 +24,6 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -34,6 +32,8 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.rename.RenameUtil;
@@ -991,7 +991,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
public MultiMap<PsiElement, String> findConflicts(Ref<UsageInfo[]> refUsages) {
MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
addMethodConflicts(conflictDescriptions);
final PsiMethod prototype = addMethodConflicts(conflictDescriptions);
Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(refUsages.get()));
RenameUtil.removeConflictUsages(usagesSet);
if (myChangeInfo.isVisibilityChanged()) {
@@ -1002,7 +1002,13 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
LOG.error(e);
}
}
final boolean[] toRemove = myChangeInfo.toRemoveParm();
//introduce parameter object deletes parameters but replaces their usages with generated code
final boolean checkUnusedParameter = myChangeInfo.checkUnusedParameter();
if (checkUnusedParameter) {
checkParametersToDelete(myChangeInfo.getMethod(), toRemove, conflictDescriptions);
}
checkContract(conflictDescriptions, myChangeInfo.getMethod());
for (UsageInfo usageInfo : usagesSet) {
@@ -1012,11 +1018,16 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
final PsiMethod baseMethod = ((OverriderUsageInfo)usageInfo).getBaseMethod();
final int delta = baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount();
if (delta > 0) {
final boolean[] toRemove = myChangeInfo.toRemoveParm();
if (toRemove[toRemove.length - 1]) { //todo check if implicit parameter is not the last one
conflictDescriptions.putValue(baseMethod, "Implicit last parameter should not be deleted");
}
}
else if (prototype != null && baseMethod == myChangeInfo.getMethod()) {
ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflictDescriptions);
if (checkUnusedParameter) {
checkParametersToDelete(method, toRemove, conflictDescriptions);
}
}
checkContract(conflictDescriptions, method);
}
@@ -1028,6 +1039,19 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
return conflictDescriptions;
}
private static void checkParametersToDelete(PsiMethod method, boolean[] toRemove, MultiMap<PsiElement, String> conflictDescriptions) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiCodeBlock body = method.getBody();
if (body != null) {
final LocalSearchScope searchScope = new LocalSearchScope(body);
for (int i = 0; i < toRemove.length; i++) {
if (toRemove[i] && ReferencesSearch.search(parameters[i], searchScope).findFirst() != null) {
conflictDescriptions.putValue(parameters[i], StringUtil.capitalize(RefactoringUIUtil.getDescription(parameters[i], true)) + " is used in method body");
}
}
}
}
private static void checkContract(MultiMap<PsiElement, String> conflictDescriptions, PsiMethod method) {
PsiAnnotation contract = ControlFlowAnalyzer.findContractAnnotation(method);
if (contract != null && !AnnotationUtil.isInferredAnnotation(contract)) {
@@ -1075,15 +1099,15 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
}
private void addMethodConflicts(MultiMap<PsiElement, String> conflicts) {
private PsiMethod addMethodConflicts(MultiMap<PsiElement, String> conflicts) {
String newMethodName = myChangeInfo.getNewName();
try {
PsiMethod prototype;
final PsiMethod method = myChangeInfo.getMethod();
if (!StdLanguages.JAVA.equals(method.getLanguage())) return;
if (!StdLanguages.JAVA.equals(method.getLanguage())) return null;
PsiManager manager = method.getManager();
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType();
PsiMethod prototype;
if (returnType != null) {
prototype = factory.createMethod(newMethodName, returnType.getType(method, manager));
}
@@ -1104,11 +1128,13 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
prototype.getParameterList().add(param);
}
ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts);
ConflictsUtil.checkMethodConflicts(method.getContainingClass(), myChangeInfo.isGenerateDelegate() ? null : method, prototype, conflicts);
return prototype;
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
return null;
}
}
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -27,6 +28,7 @@ import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.WindowManager;
@@ -77,38 +79,43 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
final String localName = local.getName();
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
return;
}
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final List<PsiElement> innerClassesWithUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
ApplicationManager.getApplication().invokeLater(() -> {
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
}, ModalityState.NON_MODAL);
return;
}
return true;
});
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
}
return true;
});
}, "Find Usages", true, project)) {
return;
}
final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
if (containerBlock == null) {
final String message = RefactoringBundle.getCannotRefactorMessage("Variable is declared outside a code block");
@@ -116,9 +123,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
return;
}
final PsiExpression defToInline = innerClassesWithUsages.isEmpty()
? getDefToInline(local, refExpr, containerBlock)
: getDefToInline(local, innerClassesWithUsages.get(0), containerBlock);
final PsiExpression defToInline = getDefToInline(local, innerClassesWithUsages.isEmpty() ? refExpr : innerClassesWithUsages.get(0), containerBlock);
if (defToInline == null){
final String key = refExpr == null ? "variable.has.no.initializer" : "variable.has.no.dominating.definition";
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName));
@@ -150,7 +155,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
}
if (refExpr != null && inlineLocalDialog.isInlineThis()) {
refsToInlineList = Collections.<PsiElement>singletonList(refExpr);
refsToInlineList = Collections.singletonList(refExpr);
inlineAll.set(false);
}
}
@@ -353,14 +353,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
try {
text = file.getText().subSequence(startOffset, endOffset).toString();
String prefix = null;
String stripped = text;
if (startLiteralExpression != null) {
final int startExpressionOffset = startLiteralExpression.getTextOffset();
if (startOffset == startExpressionOffset) {
if (StringUtil.startsWithChar(text, '\"') || StringUtil.startsWithChar(text, '\'')) {
stripped = text.substring(1);
}
} else if (startOffset == startExpressionOffset + 1) {
if (startOffset == startExpressionOffset + 1) {
text = "\"" + text;
} else if (startOffset > startExpressionOffset + 1){
prefix = "\" + ";
@@ -371,11 +366,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
String suffix = null;
if (endLiteralExpression != null) {
final int endExpressionOffset = endLiteralExpression.getTextOffset() + endLiteralExpression.getTextLength();
if (endOffset == endExpressionOffset ) {
if (StringUtil.endsWithChar(stripped, '\"') || StringUtil.endsWithChar(stripped, '\'')) {
stripped = stripped.substring(0, stripped.length() - 1);
}
} else if (endOffset == endExpressionOffset - 1) {
if (endOffset == endExpressionOffset - 1) {
text += "\"";
} else if (endOffset < endExpressionOffset - 1) {
suffix = " + \"";
@@ -383,24 +374,6 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
}
boolean primitive = false;
if (stripped.equals("true") || stripped.equals("false")) {
primitive = true;
}
else {
try {
Integer.parseInt(stripped);
primitive = true;
}
catch (NumberFormatException e1) {
//then not primitive
}
}
if (primitive) {
text = stripped;
}
if (literalExpression != null && text.equals(literalExpression.getText())) return literalExpression;
final PsiElement parent = literalExpression != null ? literalExpression : elementAt;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,13 +26,13 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.FileTypeUtils;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil;
@@ -40,7 +40,6 @@ import com.intellij.refactoring.util.MoveRenameUsageInfo;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.TextOccurrencesUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.Nullable;
@@ -236,16 +235,15 @@ public class MoveClassesOrPackagesUtil {
final PsiDirectory containingDirectory = file.getContainingDirectory();
if (!Comparing.equal(moveDestination.getVirtualFile(), containingDirectory != null ? containingDirectory.getVirtualFile() : null)) {
LOG.assertTrue(file.getVirtualFile() != null, aClass);
MoveFilesOrDirectoriesUtil.doMoveFile(file, moveDestination);
if (file instanceof PsiClassOwner && newPackage != null && !FileTypeUtils.isInServerPageFile(file)) {
if (newPackage != null && file instanceof PsiClassOwner && !FileTypeUtils.isInServerPageFile(file) && !PsiUtil.isModuleFile(file)) {
// Do not rely on class instance identity retention after setPackageName (Scala)
String aClassName = aClass.getName();
((PsiClassOwner)file).setPackageName(newPackage.getQualifiedName());
newClass = findClassByName((PsiClassOwner)file, aClassName);
LOG.assertTrue(newClass != null, "name: " + aClassName +
", file: " + file +
", classes: " + StringUtil.join(((PsiClassOwner)file).getClasses(),
psiClass -> psiClass.getName(), " "));
LOG.assertTrue(newClass != null, "name:" + aClassName + " file:" + file + " classes:" + Arrays.toString(((PsiClassOwner)file).getClasses()));
}
}
return newClass;
@@ -53,7 +53,7 @@ public class ConflictsUtil {
}
public static void checkMethodConflicts(@Nullable PsiClass aClass,
PsiMethod refactoredMethod,
@Nullable PsiMethod refactoredMethod,
final PsiMethod prototype,
final MultiMap<PsiElement,String> conflicts) {
if (prototype == null) return;
@@ -32,7 +32,6 @@ import com.intellij.util.QueryExecutor;
import org.jetbrains.annotations.NotNull;
public class FunctionalExpressionSearch extends ExtensibleQueryFactory<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
public static final ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.functionalInterfaceSearch");
public static final FunctionalExpressionSearch INSTANCE = new FunctionalExpressionSearch();
public static class SearchParameters {
@@ -19,7 +19,6 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFunctionalExpression;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiElementProcessorAdapter;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
@@ -37,20 +36,16 @@ public class ClassImplementationsSearch implements QueryExecutor<PsiElement, Def
}
public static boolean processImplementations(final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) {
if (!FunctionalExpressionSearch.search(psiClass, scope).forEach(expression -> {
return processor.process(expression);
})) {
return false;
}
final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces");
return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() {
public boolean execute(@NotNull PsiClass element) {
if (!ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(element -> {
if (!showInterfaces && element.isInterface()) {
return true;
}
return processor.process(element);
}
}));
}))) {
return false;
}
return FunctionalExpressionSearch.search(psiClass, scope).forEach((Processor<PsiFunctionalExpression>)processor::process);
}
}
@@ -59,14 +59,14 @@ public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClas
private static boolean processAllClassesInGlobalScope(@NotNull final GlobalSearchScope scope,
@NotNull final AllClassesSearch.SearchParameters parameters,
@NotNull Processor<PsiClass> processor) {
final Set<String> names = new THashSet<String>(10000);
final Set<String> names = new THashSet<>(10000);
processClassNames(parameters.getProject(), scope, s -> {
if (parameters.nameMatches(s)) {
names.add(s);
}
});
List<String> sorted = new ArrayList<String>(names);
List<String> sorted = new ArrayList<>(names);
Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER);
return processClassesByNames(parameters.getProject(), scope, sorted, processor);
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
@@ -26,9 +27,9 @@ import com.intellij.psi.search.searches.AnnotatedElementsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -39,15 +40,15 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
@Override
public boolean execute(@NotNull final AnnotatedElementsSearch.Parameters p, @NotNull final Processor<PsiModifierListOwner> consumer) {
final PsiClass annClass = p.getAnnotationClass();
assert annClass.isAnnotationType() : "Annotation type should be passed to annotated members search";
if (!annClass.isAnnotationType()) throw new IllegalArgumentException("Annotation type should be passed to annotated members search but got: "+annClass);
final String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return annClass.getQualifiedName();
}
});
assert annotationFQN != null;
if (annotationFQN == null) throw new IllegalArgumentException("FQN is null for "+annClass);
final PsiManager psiManager = ApplicationManager.getApplication().runReadAction(new Computable<PsiManager>() {
@Override
@@ -59,7 +60,7 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
final SearchScope useScope = p.getScope();
final Class<? extends PsiModifierListOwner>[] types = p.getTypes();
for (final PsiAnnotation ann : getAnnotationCandidates(annClass, useScope)) {
for (final PsiAnnotation ann : getAnnotationCandidates(annClass, useScope, psiManager.getProject())) {
final PsiModifierListOwner candidate = ApplicationManager.getApplication().runReadAction(new Computable<PsiModifierListOwner>() {
@Override
public PsiModifierListOwner compute() {
@@ -90,15 +91,17 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
return true;
}
private static Collection<PsiAnnotation> getAnnotationCandidates(final PsiClass annClass, final SearchScope useScope) {
@NotNull
private static Collection<PsiAnnotation> getAnnotationCandidates(@NotNull PsiClass annClass,
@NotNull SearchScope useScope, @NotNull Project project) {
return ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiAnnotation>>() {
@Override
public Collection<PsiAnnotation> compute() {
if (useScope instanceof GlobalSearchScope) {
return JavaAnnotationIndex.getInstance().get(annClass.getName(), annClass.getProject(), (GlobalSearchScope)useScope);
return JavaAnnotationIndex.getInstance().get(annClass.getName(), project, (GlobalSearchScope)useScope);
}
final List<PsiAnnotation> result = ContainerUtil.newArrayList();
List<PsiAnnotation> result = new ArrayList<>();
for (PsiElement element : ((LocalSearchScope)useScope).getScope()) {
result.addAll(PsiTreeUtil.findChildrenOfType(element, PsiAnnotation.class));
}
@@ -107,7 +110,7 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
});
}
public static boolean isInstanceof(PsiElement owner, Class<? extends PsiModifierListOwner>[] types) {
public static boolean isInstanceof(PsiElement owner, @NotNull Class<? extends PsiModifierListOwner>[] types) {
for (Class<? extends PsiModifierListOwner> type : types) {
if(type.isInstance(owner)) return true;
}
@@ -75,9 +75,9 @@ public class AnnotatedPackagesSearcher implements QueryExecutor<PsiPackage, Anno
boolean accepted = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>(){
@Override
public Boolean compute() {
PsiModifierList modlist = (PsiModifierList)annotation.getParent();
final PsiElement owner = modlist.getParent();
if ((owner instanceof PsiClass)) {
PsiModifierList modList = (PsiModifierList)annotation.getParent();
final PsiElement owner = modList.getParent();
if (owner instanceof PsiClass) {
PsiClass candidate = (PsiClass)owner;
if ("package-info".equals(candidate.getName())) {
LOG.assertTrue(candidate.isValid());
@@ -15,10 +15,11 @@
*/
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.*;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMember;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
@@ -45,7 +46,7 @@ public class ClassesWithAnnotatedMembersSearcher extends QueryExecutorBase<PsiCl
}
}
final Set<PsiClass> processed = new HashSet<PsiClass>();
final Set<PsiClass> processed = new HashSet<>();
AnnotatedElementsSearch.searchPsiMembers(queryParameters.getAnnotationClass(), scope).forEach(member -> {
PsiClass psiClass;
AccessToken token = ReadAction.start();
@@ -35,10 +35,10 @@ import org.jetbrains.annotations.NotNull;
/**
* @author max
*/
public class ConstructorReferencesSearchHelper {
class ConstructorReferencesSearchHelper {
private final PsiManager myManager;
public ConstructorReferencesSearchHelper(@NotNull PsiManager manager) {
ConstructorReferencesSearchHelper(@NotNull PsiManager manager) {
myManager = manager;
}
@@ -48,14 +48,14 @@ public class ConstructorReferencesSearchHelper {
* 2. Exception avoidance. Project is needed outside of read action (to run it via DumbService in the first place),
* and so getProject would fail with an assertion that read action is required but not present.
*/
public boolean processConstructorReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final PsiClass containingClass,
@NotNull final SearchScope searchScope,
@NotNull final Project project,
boolean ignoreAccessScope,
final boolean isStrictSignatureSearch,
@NotNull SearchRequestCollector collector) {
boolean processConstructorReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final PsiClass containingClass,
@NotNull final SearchScope searchScope,
@NotNull final Project project,
boolean ignoreAccessScope,
final boolean isStrictSignatureSearch,
@NotNull SearchRequestCollector collector) {
final boolean[] constructorCanBeCalledImplicitly = new boolean[1];
final boolean[] isEnum = new boolean[1];
final boolean[] isUnder18 = new boolean[1];
@@ -22,6 +22,7 @@ public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReferenc
final PsiMethod method = (PsiMethod)element;
final PsiManager[] manager = new PsiManager[1];
PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
@Override
public PsiClass compute() {
if (!method.isConstructor()) return null;
PsiClass aClass = method.getContainingClass();
@@ -29,7 +29,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex;
import com.intellij.psi.impl.java.stubs.index.JavaSuperClassNameOccurenceIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.GlobalSearchScopeUtil;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.AllClassesSearch;
@@ -43,9 +43,11 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
/**
* @author max
@@ -82,7 +84,8 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
int groupStart = 0;
boolean sameJarClassFound = false;
String currentFQN = null;
for (int i = 0; i < cache.length +1; i++) {
boolean[] isOutOfScope = new boolean[cache.length]; // here we cache results of isInScope(scope, subClass) to avoid calculating it twice
for (int i = 0; i <= cache.length; i++) {
ProgressManager.checkCanceled();
PsiClass subClass = i == cache.length ? null : cache[i];
@@ -92,9 +95,12 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return true;
}
}
if (i != cache.length && !isInScope(scope, subClass)) {
isOutOfScope[i] = true;
continue;
}
String fqn = i == cache.length ? null : ApplicationManager.getApplication().runReadAction((Computable<String>)subClass::getQualifiedName);
if (i != cache.length && !isInScope(scope, subClass)) continue;
if (currentFQN != null && Comparing.equal(fqn, currentFQN)) {
VirtualFile currentJarFile = getJarFile(subClass);
@@ -113,8 +119,9 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
if (!sameJarClassFound) {
for (int g=groupStart; g<i; g++) {
ProgressManager.checkCanceled();
PsiClass anonSubClass = cache[g];
if (!consumer.process(anonSubClass)) return false;
if (isOutOfScope[g]) continue;
PsiClass subClassCandidate = cache[g];
if (!consumer.process(subClassCandidate)) return false;
}
}
groupStart = i;
@@ -162,27 +169,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return ContainerUtil.process(collection, processor);
}
@NotNull
private static GlobalSearchScope toGlobal(@NotNull final SearchScope scope, @NotNull Project project) {
if (scope instanceof GlobalSearchScope) {
return (GlobalSearchScope)scope;
}
Set<VirtualFile> files = Arrays.stream(((LocalSearchScope)scope).getScope()).map(PsiUtil::getVirtualFile).collect(Collectors.toSet());
return GlobalSearchScope.filesScope(project, files);
}
@NotNull
private static PsiClass[] calculateDirectSubClasses(@NotNull Project project,
@NotNull PsiClass baseClass,
@NotNull String baseClassName,
@NotNull SearchScope useScope) {
DumbService dumbService = DumbService.getInstance(project);
GlobalSearchScope globalUseScope = dumbService.runReadActionInSmartMode(() -> StubHierarchyInheritorSearcher.restrictScope(toGlobal(useScope, project)));
GlobalSearchScope globalUseScope = dumbService.runReadActionInSmartMode(
() -> StubHierarchyInheritorSearcher.restrictScope(GlobalSearchScopeUtil.toGlobalSearchScope(useScope, project)));
Collection<PsiReferenceList> candidates =
dumbService.runReadActionInSmartMode(() -> JavaSuperClassNameOccurenceIndex.getInstance().get(baseClassName, project, globalUseScope));
// memory/speed optimisation: it really is a map(string -> PsiClass or List<PsiClass>)
final Map<String, Object> classes = new HashMap<>();
final Map<String, Object> classesWithFqn = new HashMap<>();
processConcurrentlyIfTooMany(candidates,
referenceList -> {
@@ -192,16 +191,16 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
boolean isInheritor = candidate.isInheritor(baseClass, false);
if (isInheritor) {
String fqn = candidate.getQualifiedName();
synchronized (classes) {
Object value = classes.get(fqn);
synchronized (classesWithFqn) {
Object value = classesWithFqn.get(fqn);
if (value == null) {
classes.put(fqn, candidate);
classesWithFqn.put(fqn, candidate);
}
else if (value instanceof PsiClass) {
List<PsiClass> list = new ArrayList<>();
list.add((PsiClass)value);
list.add(candidate);
classes.put(fqn, list);
classesWithFqn.put(fqn, list);
}
else {
@SuppressWarnings("unchecked")
@@ -216,7 +215,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
});
final List<PsiClass> result = new ArrayList<>();
for (Object value : classes.values()) {
for (Object value : classesWithFqn.values()) {
if (value instanceof PsiClass) {
result.add((PsiClass)value);
}
@@ -34,7 +34,7 @@ import java.io.IOException;
import java.util.*;
public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<String, Collection<JavaFunctionalExpressionIndex.IndexHolder>> implements PsiDependentIndex {
public static final ID<String, Collection<IndexHolder>> JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID = ID.create("java.functional.expression");
static final ID<String, Collection<IndexHolder>> JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID = ID.create("java.functional.expression");
private static final String THIS_REF_NAME = "this";
private static final String SUPER_REF_NAME = "super";
@@ -47,84 +47,80 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
@NotNull
@Override
public DataIndexer<String, Collection<IndexHolder>, FileContent> getIndexer() {
return new DataIndexer<String, Collection<IndexHolder>, FileContent>() {
@NotNull
@Override
public Map<String, Collection<IndexHolder>> map(@NotNull FileContent inputData) {
if (!JavaStubElementTypes.JAVA_FILE.shouldBuildStubFor(inputData.getFile())) {
return Collections.emptyMap();
}
final CharSequence contentAsText = inputData.getContentAsText();
if (!StringUtil.contains(contentAsText, "::") && !StringUtil.contains(contentAsText, "->")) {
return Collections.emptyMap();
}
return inputData -> {
if (!JavaStubElementTypes.JAVA_FILE.shouldBuildStubFor(inputData.getFile())) {
return Collections.emptyMap();
}
final CharSequence contentAsText = inputData.getContentAsText();
if (!StringUtil.contains(contentAsText, "::") && !StringUtil.contains(contentAsText, "->")) {
return Collections.emptyMap();
}
final PsiFile file = ((FileContentImpl)inputData).getPsiFileForPsiDependentIndex();
if (!(file instanceof PsiJavaFile)) {
return Collections.emptyMap();
}
final PsiFile file = ((FileContentImpl)inputData).getPsiFileForPsiDependentIndex();
if (!(file instanceof PsiJavaFile)) {
return Collections.emptyMap();
}
final HashMap<String, Collection<IndexHolder>> methodsMap = ContainerUtil.newHashMap();
for (PsiFunctionalExpression expression : SyntaxTraverser.psiTraverser().withRoot(file).filter(PsiFunctionalExpression.class)) {
final PsiExpressionList expressionList =
PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, true, PsiStatement.class, PsiModifierListOwner.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
String methodName = null;
if (parent instanceof PsiMethodCallExpression) {
methodName = ((PsiMethodCallExpression)parent).getMethodExpression().getReferenceName();
if (methodName != null) {
final boolean thisRef = methodName.equals(THIS_REF_NAME);
if (thisRef || methodName.equals(SUPER_REF_NAME)) {
methodName = null;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(parent, PsiClass.class);
if (containingClass != null) {
if (thisRef) {
methodName = containingClass.getName();
} else {
final PsiReferenceList extendsList = containingClass.getExtendsList();
if (extendsList != null) {
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
if (referenceElements.length > 0) {
methodName = referenceElements[0].getReferenceName();
}
final HashMap<String, Collection<IndexHolder>> methodsMap = ContainerUtil.newHashMap();
for (PsiFunctionalExpression expression : SyntaxTraverser.psiTraverser().withRoot(file).filter(PsiFunctionalExpression.class)) {
final PsiExpressionList expressionList =
PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, true, PsiStatement.class, PsiModifierListOwner.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
String methodName = null;
if (parent instanceof PsiMethodCallExpression) {
methodName = ((PsiMethodCallExpression)parent).getMethodExpression().getReferenceName();
if (methodName != null) {
final boolean thisRef = methodName.equals(THIS_REF_NAME);
if (thisRef || methodName.equals(SUPER_REF_NAME)) {
methodName = null;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(parent, PsiClass.class);
if (containingClass != null) {
if (thisRef) {
methodName = containingClass.getName();
} else {
final PsiReferenceList extendsList = containingClass.getExtendsList();
if (extendsList != null) {
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
if (referenceElements.length > 0) {
methodName = referenceElements[0].getReferenceName();
}
}
}
}
}
}
else if (parent instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference();
if (classReference != null) {
methodName = classReference.getReferenceName();
}
}
else if (parent instanceof PsiEnumConstant) {
final PsiClass containingClass = ((PsiEnumConstant)parent).getContainingClass();
if (containingClass != null) {
final String shortEnumName = containingClass.getName();
if (shortEnumName != null) { //should be always true as enums can't be local
methodName = shortEnumName;
}
}
}
else if (parent instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference();
if (classReference != null) {
methodName = classReference.getReferenceName();
}
if (methodName != null) {
Collection<IndexHolder> holders = methodsMap.get(methodName);
if (holders == null) {
holders = new HashSet<IndexHolder>();
methodsMap.put(methodName, holders);
}
else if (parent instanceof PsiEnumConstant) {
final PsiClass containingClass = ((PsiEnumConstant)parent).getContainingClass();
if (containingClass != null) {
final String shortEnumName = containingClass.getName();
if (shortEnumName != null) { //should be always true as enums can't be local
methodName = shortEnumName;
}
holders.add(new IndexHolder(expression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)expression).getParameterList().getParametersCount() : -1,
expressionList.getExpressions().length,
LambdaUtil.getLambdaIdx(expressionList, expression)));
}
}
}
return methodsMap;
if (methodName != null) {
Collection<IndexHolder> holders = methodsMap.get(methodName);
if (holders == null) {
holders = new HashSet<>();
methodsMap.put(methodName, holders);
}
holders.add(new IndexHolder(expression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)expression).getParameterList().getParametersCount() : -1,
expressionList.getExpressions().length,
LambdaUtil.getLambdaIdx(expressionList, expression)));
}
}
}
return methodsMap;
};
}
@@ -151,7 +147,7 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
@Override
public Collection<IndexHolder> read(@NotNull DataInput in) throws IOException {
int l = DataInputOutputUtil.readINT(in);
final Collection<IndexHolder> holders = new HashSet<IndexHolder>(l);
final Collection<IndexHolder> holders = new HashSet<>(l);
while (l-- > 0) {
holders.add(new IndexHolder(DataInputOutputUtil.readINT(in),
DataInputOutputUtil.readINT(in),
@@ -178,26 +174,26 @@ public class JavaFunctionalExpressionIndex extends FileBasedIndexExtension<Strin
return 0;
}
public static class IndexHolder {
static class IndexHolder {
private final int myLambdaParamsNumber;
private final int myMethodArgsLength;
private final int myFunctionExpressionIndex;
public IndexHolder(int lambdaParamsNumber, int methodArgsLength, int functionExpressionIndex) {
IndexHolder(int lambdaParamsNumber, int methodArgsLength, int functionExpressionIndex) {
myLambdaParamsNumber = lambdaParamsNumber;
myMethodArgsLength = methodArgsLength;
myFunctionExpressionIndex = functionExpressionIndex;
}
public int getLambdaParamsNumber() {
int getLambdaParamsNumber() {
return myLambdaParamsNumber;
}
public int getMethodArgsLength() {
int getMethodArgsLength() {
return myMethodArgsLength;
}
public int getFunctionExpressionIndex() {
int getFunctionExpressionIndex() {
return myFunctionExpressionIndex;
}
@@ -40,15 +40,13 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Processor;
import com.intellij.util.Processors;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static com.intellij.util.containers.ContainerUtil.*;
import static com.intellij.util.containers.ContainerUtilRt.newHashSet;
public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
private static final Logger LOG = Logger.getInstance("#" + JavaFunctionalExpressionSearcher.class.getName());
/**
@@ -98,7 +96,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
//collect all methods with parameter of functional interface or free type parameter type
final Collection<PsiMethod> methodCandidates = getCandidateMethodsWithSuitableParams(aClass, project, useScope, candidateFiles, candidateScope);
final LinkedHashSet<VirtualFile> filesToProcess = new LinkedHashSet<VirtualFile>();
final Set<VirtualFile> filesToProcess = new LinkedHashSet<>();
final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
//find all usages of method candidates in files with functional expressions
@@ -109,7 +107,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final boolean varArgs = psiMethod.isVarArgs();
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
final GlobalSearchScope methodUseScope = convertToGlobalScope(project, psiMethod.getUseScope());
final LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders = new LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>>();
final LinkedHashMap<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders = new LinkedHashMap<>();
//functional expressions checker: number and type of parameters at call site should correspond to candidate method currently check
final SuitableFilesProcessor processor = new SuitableFilesProcessor(holders, expectedFunExprParamsCount, parametersCount, varArgs, parameters);
fileBasedIndex.processValues(JavaFunctionalExpressionIndex.JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID, psiMethod.getName(), null, processor, useScope.intersectWith(methodUseScope));
@@ -134,7 +132,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
private static Set<Module> getJava8Modules(Project project) {
final boolean projectLevelIsHigh = PsiUtil.getLanguageLevel(project).isAtLeast(LanguageLevel.JDK_1_8);
final Set<Module> highLevelModules = new HashSet<Module>();
final Set<Module> highLevelModules = new HashSet<>();
for (Module module : ModuleManager.getInstance(project).getModules()) {
final LanguageLevelModuleExtension extension = ModuleRootManager.getInstance(module).getModuleExtension(LanguageLevelModuleExtension.class);
if (extension != null) {
@@ -151,7 +149,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final Processor<PsiFunctionalExpression> consumer,
Set<VirtualFile> filesToProcess, final int expectedFunExprParamsCount, boolean isVoid) {
LOG.info("#usage files: " + filesToProcess.size());
process(filesToProcess, new ReadActionProcessor<VirtualFile>() {
ContainerUtil.process(filesToProcess, new ReadActionProcessor<VirtualFile>() {
@Override
public boolean processInReadAction(VirtualFile file) {
//resolve functional expressions to ensure that functional expression type is appropriate
@@ -172,11 +170,11 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
GlobalSearchScope visibleFromCandidates = combineResolveScopes(project, candidateFiles);
final Set<String> usedMethodNames = newHashSet();
Set<String> usedMethodNames = new HashSet<>();
FileBasedIndex.getInstance().processAllKeys(JavaFunctionalExpressionIndex.JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID,
Processors.cancelableCollectProcessor(usedMethodNames), candidateScope, null);
final LinkedHashSet<PsiMethod> methods = newLinkedHashSet();
Set<PsiMethod> methods = ContainerUtil.newLinkedHashSet();
Processor<PsiMethod> methodProcessor = method -> {
if (usedMethodNames.contains(method.getName())) {
methods.add(method);
@@ -197,7 +195,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
@NotNull
private static GlobalSearchScope combineResolveScopes(Project project, Set<VirtualFile> candidateFiles) {
final PsiManager psiManager = PsiManager.getInstance(project);
Set<GlobalSearchScope> resolveScopes = newLinkedHashSet(mapNotNull(candidateFiles, file -> {
Set<GlobalSearchScope> resolveScopes = ContainerUtil.newLinkedHashSet(ContainerUtil.mapNotNull(candidateFiles, file -> {
PsiFile psiFile = file.isValid() ? psiManager.findFile(file) : null;
return psiFile == null ? null : psiFile.getResolveScope();
}));
@@ -206,7 +204,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
@NotNull
private static Set<VirtualFile> getFilesWithFunctionalExpressionsScope(Project project, GlobalSearchScope useScope) {
final Set<VirtualFile> files = newLinkedHashSet();
final Set<VirtualFile> files = ContainerUtil.newLinkedHashSet();
final PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(project);
Processor<VirtualFile> processor = Processors.cancelableCollectProcessor(files);
helper.processFilesWithText(useScope, UsageSearchContext.IN_CODE, true, "::", processor);
@@ -221,8 +219,8 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
scope = (GlobalSearchScope)useScope;
}
else if (useScope instanceof LocalSearchScope) {
final Set<VirtualFile> files = new HashSet<VirtualFile>();
addAllNotNull(files, map(((LocalSearchScope)useScope).getScope(), element -> PsiUtilCore.getVirtualFile(element)));
final Set<VirtualFile> files = new HashSet<>();
ContainerUtil.addAllNotNull(files, ContainerUtil.map(((LocalSearchScope)useScope).getScope(), PsiUtilCore::getVirtualFile));
scope = GlobalSearchScope.filesScope(project, files);
}
else {
@@ -247,15 +245,15 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
}
</pre>
*/
private static void collectFilesWithTypeOccurrencesAndFieldAssignments(PsiClass aClass,
GlobalSearchScope filesScope,
final LinkedHashSet<VirtualFile> usageFiles) {
final Set<PsiField> fields = new LinkedHashSet<PsiField>();
private static void collectFilesWithTypeOccurrencesAndFieldAssignments(@NotNull PsiClass aClass,
@NotNull GlobalSearchScope filesScope,
@NotNull Set<VirtualFile> usageFiles) {
final Set<PsiField> fields = new LinkedHashSet<>();
for (final PsiReference reference : ReferencesSearch.search(aClass, filesScope)) {
ApplicationManager.getApplication().runReadAction(() -> {
final PsiElement element = reference.getElement();
if (element != null) {
addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(element));
ContainerUtil.addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(element));
final PsiElement parent = element.getParent();
if (parent instanceof PsiTypeElement) {
final PsiElement gParent = parent.getParent();
@@ -276,7 +274,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
final PsiElement fieldElement = fieldRef.getElement();
final PsiAssignmentExpression varElementParent = PsiTreeUtil.getParentOfType(fieldElement, PsiAssignmentExpression.class);
if (varElementParent != null && PsiTreeUtil.isAncestor(varElementParent.getLExpression(), fieldElement, false)) {
addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(fieldElement));
ContainerUtil.addIfNotNull(usageFiles, PsiUtilCore.getVirtualFile(fieldElement));
}
return true;
}
@@ -291,7 +289,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
VirtualFile file) {
final PsiFile psiFile = aClass.getManager().findFile(file);
if (psiFile != null) {
final Ref<Boolean> ref = new Ref<Boolean>(true);
final Ref<Boolean> ref = new Ref<>(true);
psiFile.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
@@ -345,11 +343,11 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
private final boolean myVarArgs;
private final PsiParameter[] myParameters;
public SuitableFilesProcessor(Map<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders,
int expectedFunExprParamsCount,
int parametersCount,
boolean varArgs,
PsiParameter[] parameters) {
SuitableFilesProcessor(Map<VirtualFile, Set<JavaFunctionalExpressionIndex.IndexHolder>> holders,
int expectedFunExprParamsCount,
int parametersCount,
boolean varArgs,
PsiParameter[] parameters) {
myHolders = holders;
myExpectedFunExprParamsCount = expectedFunExprParamsCount;
myParametersCount = parametersCount;
@@ -372,7 +370,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
}
if (suitableParamNumbers) {
if (savedHolders == null) {
savedHolders = new LinkedHashSet<JavaFunctionalExpressionIndex.IndexHolder>();
savedHolders = new LinkedHashSet<>();
myHolders.put(file, savedHolders);
}
savedHolders.add(holder);
@@ -116,11 +116,10 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor<PsiMethod, O
@NotNull
private static Iterable<PsiMethod> compute(@NotNull PsiMethod method, @NotNull Project project) {
Collection<PsiMethod> result = new LinkedHashSet<>();
Application application = ApplicationManager.getApplication();
final PsiClass containingClass = application.runReadAction((Computable<PsiClass>)method::getContainingClass);
assert containingClass != null;
Collection<PsiMethod> result = new LinkedHashSet<>();
Processor<PsiClass> inheritorsProcessor = inheritor -> {
PsiMethod found = application.runReadAction((Computable<PsiMethod>)() -> findOverridingMethod(project, inheritor, method, containingClass));
if (found != null) {
@@ -20,7 +20,6 @@
package com.intellij.psi.impl.search;
import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -38,12 +37,7 @@ public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
super(delegate);
Project project = getProject();
if (project != null) {
myIndex = ProjectRootManager.getInstance(project).getFileIndex();
}
else {
myIndex = null;
}
myIndex = project == null ? null : ProjectRootManager.getInstance(project).getFileIndex();
}
@Override
@@ -34,16 +34,16 @@ public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiM
return processDeepestSuperMethods(method, consumer);
}
public static boolean processDeepestSuperMethods(PsiMethod method, Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<PsiMethod>();
public static boolean processDeepestSuperMethods(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<>();
methods.add(method);
return findDeepestSuperOrSelfSignature(method, methods, null, consumer);
}
private static boolean findDeepestSuperOrSelfSignature(final PsiMethod method,
Set<PsiMethod> set,
private static boolean findDeepestSuperOrSelfSignature(@NotNull PsiMethod method,
@NotNull Set<PsiMethod> set,
Set<PsiMethod> guard,
Processor<PsiMethod> processor) {
@NotNull Processor<PsiMethod> processor) {
if (guard != null && !guard.add(method)) return true;
PsiMethod[] supers = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
@Override
@@ -57,7 +57,7 @@ public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiM
}
for (PsiMethod superMethod : supers) {
if (guard == null) {
guard = new THashSet<PsiMethod>();
guard = new THashSet<>();
guard.add(method);
}
if (!findDeepestSuperOrSelfSignature(superMethod, set, guard, processor)) return false;
@@ -63,7 +63,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
final SearchRequestCollector collector = p.getOptimizer();
final SearchScope searchScope = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(() -> p.getEffectiveSearchScope());
final SearchScope searchScope = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(p::getEffectiveSearchScope);
if (searchScope == GlobalSearchScope.EMPTY_SCOPE) {
return;
}
@@ -65,7 +65,8 @@ public class PsiAnnotationMethodReferencesSearcher implements QueryExecutor<PsiR
return true;
}
public static ReadActionProcessor<PsiReference> createImplicitDefaultAnnotationMethodConsumer(final Processor<PsiReference> consumer) {
@NotNull
static ReadActionProcessor<PsiReference> createImplicitDefaultAnnotationMethodConsumer(@NotNull Processor<PsiReference> consumer) {
return new ReadActionProcessor<PsiReference>() {
@Override
public boolean processInReadAction(final PsiReference reference) {
@@ -34,7 +34,6 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
public SimpleAccessorReferenceSearcher() {
super(true);
}
@@ -47,7 +46,7 @@ public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiRefere
addPropertyAccessUsages((PsiMethod)refElement, queryParameters.getEffectiveSearchScope(), queryParameters.getOptimizer());
}
static void addPropertyAccessUsages(PsiMethod method, SearchScope scope, SearchRequestCollector collector) {
static void addPropertyAccessUsages(@NotNull PsiMethod method, @NotNull SearchScope scope, @NotNull SearchRequestCollector collector) {
final String propertyName = PropertyUtil.getPropertyName(method);
if (StringUtil.isNotEmpty(propertyName)) {
SearchScope additional = GlobalSearchScope.EMPTY_SCOPE;
@@ -16,10 +16,12 @@
package com.intellij.psi.impl.search;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
@@ -33,6 +35,7 @@ import org.jetbrains.annotations.NotNull;
* @author peter
*/
public class StubHierarchyInheritorSearcher extends QueryExecutorBase<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.StubHierarchyInheritorSearcher");
public StubHierarchyInheritorSearcher() {
super(true);
}
@@ -54,6 +57,11 @@ public class StubHierarchyInheritorSearcher extends QueryExecutorBase<PsiClass,
if (!(p.getScope() instanceof GlobalSearchScope) || !isSearching()) return;
PsiClass base = p.getClassToProcess();
PsiElement original = base.getOriginalElement();
if (original instanceof PsiClass) {
base = (PsiClass)original;
}
GlobalSearchScope scope = (GlobalSearchScope)p.getScope();
ClassHierarchy hierarchy = HierarchyService.getHierarchy(base.getProject());
for (SmartClassAnchor anchor : hierarchy.getDirectSubtypeCandidates(base)) {
@@ -50,24 +50,21 @@ public class VariableInIncompleteCodeSearcher extends QueryExecutorBase<PsiRefer
PsiElement[] elements = ((LocalSearchScope)scope).getScope();
if (elements.length == 0) return;
PsiSearchHelper.SERVICE.getInstance(p.getProject()).processElementsWithWord(new TextOccurenceProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, int offsetInElement) {
for (PsiElement child = element.findElementAt(offsetInElement); child != null; child = child.getParent()) {
if (!name.equals(child.getText())) {
break;
}
if (child instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)child;
if (!ref.isQualified() &&
!(ref.getParent() instanceof PsiMethodCallExpression) &&
ref.resolve() == null && ref.advancedResolve(true).getElement() == refElement) {
consumer.process(ref);
}
PsiSearchHelper.SERVICE.getInstance(p.getProject()).processElementsWithWord((element, offsetInElement) -> {
for (PsiElement child = element.findElementAt(offsetInElement); child != null; child = child.getParent()) {
if (!name.equals(child.getText())) {
break;
}
if (child instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)child;
if (!ref.isQualified() &&
!(ref.getParent() instanceof PsiMethodCallExpression) &&
ref.resolve() == null && ref.advancedResolve(true).getElement() == refElement) {
consumer.process(ref);
}
}
return true;
}
return true;
}, scope, name, UsageSearchContext.ANY, true);
}
}
@@ -74,6 +74,10 @@ public class JavaGenericsUtil {
return true;
}
if (type instanceof PsiCapturedWildcardType) {
return isReifiableType(((PsiCapturedWildcardType)type).getUpperBound());
}
return false;
}
@@ -127,6 +131,9 @@ public class JavaGenericsUtil {
if (castType instanceof PsiClassType) {
final PsiClassType castClassType = (PsiClassType)castType;
operandType = operandType.getDeepComponentType();
if (operandType instanceof PsiCapturedWildcardType) {
operandType = ((PsiCapturedWildcardType)operandType).getUpperBound();
}
if (!(operandType instanceof PsiClassType)) return false;
final PsiClassType operandClassType = (PsiClassType)operandType;
@@ -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.
@@ -18,7 +18,6 @@ package com.intellij.psi;
import com.intellij.psi.javadoc.*;
public abstract class JavaElementVisitor extends PsiElementVisitor {
public void visitAnonymousClass(PsiAnonymousClass aClass) {
visitClass(aClass);
}
@@ -387,4 +386,28 @@ public abstract class JavaElementVisitor extends PsiElementVisitor {
public void visitLambdaExpression(PsiLambdaExpression expression) {
visitExpression(expression);
}
}
public void visitModule(PsiJavaModule module) {
visitElement(module);
}
public void visitModuleReference(PsiJavaModuleReference moduleRef) {
visitElement(moduleRef);
}
public void visitRequiresStatement(PsiRequiresStatement statement) {
visitElement(statement);
}
public void visitExportsStatement(PsiExportsStatement statement) {
visitElement(statement);
}
public void visitUsesStatement(PsiUsesStatement statement) {
visitElement(statement);
}
public void visitProvidesStatement(PsiProvidesStatement statement) {
visitElement(statement);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -139,4 +139,12 @@ public interface JavaTokenType extends TokenType {
IElementType DOUBLE_COLON = new IJavaElementType("DOUBLE_COLON");
IElementType ARROW = new IJavaElementType("ARROW");
}
IElementType MODULE_KEYWORD = new IJavaElementType("MODULE");
IElementType REQUIRES_KEYWORD = new IJavaElementType("REQUIRES");
IElementType EXPORTS_KEYWORD = new IJavaElementType("EXPORTS");
IElementType USES_KEYWORD = new IJavaElementType("USES");
IElementType PROVIDES_KEYWORD = new IJavaElementType("PROVIDES");
IElementType TO_KEYWORD = new IJavaElementType("TO");
IElementType WITH_KEYWORD = new IJavaElementType("WITH");
}
@@ -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.
@@ -13,16 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.concurrency;
package com.intellij.psi;
import com.intellij.util.Consumer;
public abstract class ConsumerRunnable implements Consumer<Void>, Runnable {
@Override
public final void consume(Void aVoid) {
run();
}
@Override
public abstract void run();
}
/**
* Represents an {@code exports} statement of a Java module declaration.
*
* @since 2016.3
*/
public interface PsiExportsStatement extends PsiElement {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
import com.intellij.pom.java.LanguageLevel;
/**
* Represents a Java, JSP or class file.
* Represents a Java, JSP or .class file.
*/
public interface PsiJavaFile extends PsiImportHolder, PsiClassOwner {
/**
@@ -91,4 +91,9 @@ public interface PsiJavaFile extends PsiImportHolder, PsiClassOwner {
@Nullable PsiJavaCodeReferenceElement findImportReferenceTo(PsiClass aClass);
@NotNull LanguageLevel getLanguageLevel();
}
/**
* Returns a Java module declaration element, or {@code null} if the file is not a module-info one.
*/
@Nullable PsiJavaModule getModuleDeclaration();
}
@@ -0,0 +1,28 @@
/*
* 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;
import org.jetbrains.annotations.Nullable;
/**
* Represents a Java module declaration.
*
* @since 2016.3
*/
public interface PsiJavaModule extends PsiElement {
@Nullable PsiJavaModuleReference getNameElement();
@Nullable String getModuleName();
}
@@ -0,0 +1,27 @@
/*
* 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;
import org.jetbrains.annotations.NotNull;
/**
* Represents a reference to some module inside a Java module declaration.
*
* @since 2016.3
*/
public interface PsiJavaModuleReference extends PsiElement {
@NotNull String getReferenceText();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package com.intellij.psi;
* Represents a Java keyword. Constants defined in this interface represent all
* keywords of the Java language.
*/
@SuppressWarnings({"HardCodedStringLiteral", "JavaDoc"})
public interface PsiKeyword extends PsiJavaToken {
String ABSTRACT = "abstract";
String ASSERT = "assert";
@@ -75,4 +74,12 @@ public interface PsiKeyword extends PsiJavaToken {
String TRUE = "true";
String FALSE = "false";
String NULL = "null";
}
String MODULE = "module";
String REQUIRES = "requires";
String EXPORTS = "exports";
String USES = "uses";
String PROVIDES = "provides";
String TO = "to";
String WITH = "with";
}
@@ -0,0 +1,24 @@
/*
* 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;
/**
* Represents a {@code provides} statement of a Java module declaration.
*
* @since 2016.3
*/
public interface PsiProvidesStatement extends PsiElement {
}
@@ -0,0 +1,24 @@
/*
* 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;
/**
* Represents a {@code requires} statement of a Java module declaration.
*
* @since 2016.3
*/
public interface PsiRequiresStatement extends PsiElement {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.concurrency;
package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
public interface AsyncFunction<PARAM, RESULT> {
@NotNull
Promise<RESULT> fun(PARAM param);
/**
* Represents a {@code uses} statement of a Java module declaration.
*
* @since 2016.3
*/
public interface PsiUsesStatement extends PsiElement {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@ public abstract class JavaCodeStyleManager {
* file if an Optimize Imports operation was performed on it.
*
* @param file the file to calculate the import list for.
* @return the calculated import list.
* @return the calculated import list, or {@code null} when the file has no import list.
*/
public abstract PsiImportList prepareOptimizeImportsResult(@NotNull PsiJavaFile file);
@@ -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);
}
@@ -16,7 +16,6 @@
package com.intellij.psi.util;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
@@ -24,7 +23,6 @@ import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
@@ -629,7 +627,10 @@ public final class PsiUtil extends PsiUtilCore {
* <code>class Foo&lt;T extends Number&gt;{}</code> types Foo&lt;?&gt; and Foo&lt;? extends Number&gt;
* would be equivalent
*/
public static boolean equalOnEquivalentClasses(PsiClassType thisClassType, @NotNull PsiClass aClass, PsiClassType otherClassType, @NotNull PsiClass bClass) {
public static boolean equalOnEquivalentClasses(PsiClassType thisClassType,
@NotNull PsiClass aClass,
PsiClassType otherClassType,
@NotNull PsiClass bClass) {
final PsiClassType capture1 = !PsiCapturedWildcardType.isCapture()
? thisClassType : (PsiClassType)captureToplevelWildcards(thisClassType, aClass);
final PsiClassType capture2 = !PsiCapturedWildcardType.isCapture()
@@ -641,17 +642,10 @@ public final class PsiUtil extends PsiUtilCore {
return equalOnEquivalentClasses(result1.getSubstitutor(), aClass, result2.getSubstitutor(), bClass);
}
@Deprecated
public static boolean equalOnClass(@NotNull PsiSubstitutor s1, @NotNull PsiSubstitutor s2, @NotNull PsiClass aClass) {
return equalOnEquivalentClasses(s1, aClass, s2, aClass);
}
/**
* @deprecated to remove in v.16
* Checks if substitutors maps are identical. If substitutor map values contain wildcard type, type parameter bounds are IGNORED.
* Please use {@link PsiUtil#equalOnEquivalentClasses(PsiClassType, PsiClass, PsiClassType, PsiClass)} instead.
*/
public static boolean equalOnEquivalentClasses(@NotNull PsiSubstitutor s1, @NotNull PsiClass aClass, @NotNull PsiSubstitutor s2, @NotNull PsiClass bClass) {
private static boolean equalOnEquivalentClasses(@NotNull PsiSubstitutor s1,
@NotNull PsiClass aClass,
@NotNull PsiSubstitutor s2,
@NotNull PsiClass bClass) {
// assume generic class equals to non-generic
if (aClass.hasTypeParameters() != bClass.hasTypeParameters()) return true;
final PsiTypeParameter[] typeParameters1 = aClass.getTypeParameters();
@@ -673,9 +667,8 @@ public final class PsiUtil extends PsiUtilCore {
return containingClass1 == null && containingClass2 == null;
}
/**
* @deprecated use more generic {@link #isCompileTimeConstant(PsiVariable)} instead
*/
/** @deprecated use more generic {@link #isCompileTimeConstant(PsiVariable)} instead */
@SuppressWarnings("unused")
public static boolean isCompileTimeConstant(@NotNull final PsiField field) {
return isCompileTimeConstant((PsiVariable)field);
}
@@ -883,11 +876,6 @@ public final class PsiUtil extends PsiUtilCore {
return psiClass != null && psiClass.isAnnotationType();
}
@PsiModifier.ModifierConstant
public static String getMaximumModifierForMember(final PsiClass aClass) {
return getMaximumModifierForMember(aClass, true);
}
@PsiModifier.ModifierConstant
public static String getMaximumModifierForMember(final PsiClass aClass, boolean allowPublicAbstract) {
String modifier = PsiModifier.PUBLIC;
@@ -1294,281 +1282,7 @@ public final class PsiUtil extends PsiUtilCore {
}
}
public static class NullPsiClass extends NullPsiElement implements PsiClass {
@Nullable
@Override
public ItemPresentation getPresentation() {
throw createException();
}
@Nullable
@Override
public PsiDocComment getDocComment() {
throw createException();
}
@Override
public boolean hasTypeParameters() {
throw createException();
}
@Nullable
@Override
public PsiModifierList getModifierList() {
throw createException();
}
@Nullable
@Override
public String getName() {
throw createException();
}
@Override
public boolean isDeprecated() {
throw createException();
}
@Nullable
@Override
public PsiTypeParameterList getTypeParameterList() {
throw createException();
}
@Override
public void navigate(boolean requestFocus) {
throw createException();
}
@Override
public boolean canNavigate() {
throw createException();
}
@Override
public boolean hasModifierProperty(@PsiModifier.ModifierConstant @NonNls @NotNull String name) {
throw createException();
}
@NotNull
@Override
public PsiTypeParameter[] getTypeParameters() {
throw createException();
}
@Override
public boolean canNavigateToSource() {
throw createException();
}
@Nullable
@Override
public String getQualifiedName() {
throw createException();
}
@Override
public boolean isInterface() {
throw createException();
}
@Override
public boolean isAnnotationType() {
throw createException();
}
@Override
public boolean isEnum() {
throw createException();
}
@Nullable
@Override
public PsiReferenceList getExtendsList() {
throw createException();
}
@Nullable
@Override
public PsiReferenceList getImplementsList() {
throw createException();
}
@NotNull
@Override
public PsiClassType[] getExtendsListTypes() {
throw createException();
}
@NotNull
@Override
public PsiClassType[] getImplementsListTypes() {
throw createException();
}
@Nullable
@Override
public PsiClass getSuperClass() {
throw createException();
}
@Override
public PsiClass[] getInterfaces() {
throw createException();
}
@NotNull
@Override
public PsiClass[] getSupers() {
throw createException();
}
@NotNull
@Override
public PsiClassType[] getSuperTypes() {
throw createException();
}
@NotNull
@Override
public PsiField[] getFields() {
throw createException();
}
@NotNull
@Override
public PsiMethod[] getMethods() {
throw createException();
}
@NotNull
@Override
public PsiMethod[] getConstructors() {
throw createException();
}
@NotNull
@Override
public PsiClass[] getInnerClasses() {
throw createException();
}
@NotNull
@Override
public PsiClassInitializer[] getInitializers() {
throw createException();
}
@NotNull
@Override
public PsiField[] getAllFields() {
throw createException();
}
@NotNull
@Override
public PsiMethod[] getAllMethods() {
throw createException();
}
@NotNull
@Override
public PsiClass[] getAllInnerClasses() {
throw createException();
}
@Nullable
@Override
public PsiField findFieldByName(@NonNls String name, boolean checkBases) {
throw createException();
}
@Nullable
@Override
public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) {
throw createException();
}
@NotNull
@Override
public PsiMethod[] findMethodsBySignature(PsiMethod patternMethod, boolean checkBases) {
throw createException();
}
@NotNull
@Override
public PsiMethod[] findMethodsByName(@NonNls String name, boolean checkBases) {
throw createException();
}
@NotNull
@Override
public List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(@NonNls String name, boolean checkBases) {
throw createException();
}
@NotNull
@Override
public List<Pair<PsiMethod, PsiSubstitutor>> getAllMethodsAndTheirSubstitutors() {
throw createException();
}
@Nullable
@Override
public PsiClass findInnerClassByName(@NonNls String name, boolean checkBases) {
throw createException();
}
@Nullable
@Override
public PsiElement getLBrace() {
throw createException();
}
@Nullable
@Override
public PsiElement getRBrace() {
throw createException();
}
@Nullable
@Override
public PsiIdentifier getNameIdentifier() {
throw createException();
}
@Override
public PsiElement getScope() {
throw createException();
}
@Override
public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
throw createException();
}
@Override
public boolean isInheritorDeep(PsiClass baseClass, @Nullable PsiClass classToByPass) {
throw createException();
}
@Nullable
@Override
public PsiClass getContainingClass() {
throw createException();
}
@NotNull
@Override
public Collection<HierarchicalMethodSignature> getVisibleSignatures() {
throw createException();
}
@Override
public PsiElement setName(@NonNls @NotNull String name) {
throw createException();
}
public static boolean isModuleFile(@NotNull PsiFile file) {
return file instanceof PsiJavaFile && ((PsiJavaFile)file).getModuleDeclaration() != null;
}
public static final PsiClass NULL_PSI_CLASS = new NullPsiClass();
}
}
@@ -7,6 +7,6 @@ jdk.1.5.language.level.description=5.0 - 'enum' keyword, generics, autoboxing et
jdk.1.6.language.level.description=6 - @Override in interfaces
jdk.1.7.language.level.description=7 - Diamonds, ARM, multi-catch etc.
jdk.1.8.language.level.description=8 - Lambdas, type annotations etc.
jdk.1.9.language.level.description=9 - JDK modularization etc.
jdk.1.9.language.level.description=9 - Modules, private methods in interfaces etc.
jdk.X.language.level.description=X - Experimental features
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;
@@ -53,6 +54,11 @@ public class FileParser {
@NotNull final TokenSet importListStoppers,
@NotNull final AbstractBundle bundle,
@NotNull final String errorMessageKey) {
if (PsiKeyword.MODULE.equals(builder.getTokenText())) {
ModuleParser.parseModule(builder);
return;
}
parsePackageStatement(builder);
Pair<PsiBuilder.Marker, Boolean> impListInfo = parseImportList(builder, importListStoppers);
@@ -189,4 +195,4 @@ public class FileParser {
done(statement, type);
return statement;
}
}
}
@@ -0,0 +1,265 @@
/*
* 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.lang.java.parser;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.java.parser.JavaParserUtil.error;
import static com.intellij.lang.java.parser.JavaParserUtil.semicolon;
public class ModuleParser {
public static void parseModule(@NotNull PsiBuilder builder) {
PsiBuilder.Marker module = builder.mark();
mapAndAdvance(builder, JavaTokenType.MODULE_KEYWORD);
if (parseName(builder) == null) {
module.drop();
if (builder.getTokenType() != null) {
parseExtras(builder, JavaErrorMessages.message("expected.module.declaration"));
}
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
return;
}
if (!expect(builder, JavaTokenType.LBRACE)) {
if (builder.getTokenType() != null) {
parseExtras(builder, JavaErrorMessages.message("expected.module.declaration"));
}
else {
error(builder, JavaErrorMessages.message("expected.lbrace"));
}
}
else {
parseModuleContent(builder);
}
module.done(JavaElementType.MODULE);
if (builder.getTokenType() != null) {
parseExtras(builder, JavaErrorMessages.message("unexpected.tokens"));
}
}
private static PsiBuilder.Marker parseName(PsiBuilder builder) {
PsiBuilder.Marker nameElement = builder.mark();
boolean empty = true;
boolean idExpected = true;
while (true) {
IElementType t = builder.getTokenType();
if (t == JavaTokenType.IDENTIFIER) {
if (!idExpected) error(builder, JavaErrorMessages.message("expected.dot"));
idExpected = false;
}
else if (t == JavaTokenType.DOT) {
if (idExpected) error(builder, JavaErrorMessages.message("expected.identifier"));
idExpected = true;
}
else break;
builder.advanceLexer();
empty = false;
}
if (!empty) {
if (idExpected) error(builder, JavaErrorMessages.message("expected.identifier"));
nameElement.done(JavaElementType.MODULE_REFERENCE);
return nameElement;
}
else {
nameElement.drop();
return null;
}
}
private static void parseModuleContent(PsiBuilder builder) {
IElementType token;
PsiBuilder.Marker invalid = null;
while ((token = builder.getTokenType()) != null) {
if (token == JavaTokenType.RBRACE) {
break;
}
if (token == JavaTokenType.SEMICOLON) {
if (invalid != null) {
invalid.error(JavaErrorMessages.message("expected.module.statement"));
invalid = null;
}
builder.advanceLexer();
continue;
}
PsiBuilder.Marker statement = parseStatement(builder);
if (statement == null) {
if (invalid == null) invalid = builder.mark();
builder.advanceLexer();
}
else if (invalid != null) {
invalid.errorBefore(JavaErrorMessages.message("expected.module.statement"), statement);
invalid = null;
}
}
if (invalid != null) {
invalid.error(JavaErrorMessages.message("expected.module.statement"));
}
if (!expect(builder, JavaTokenType.RBRACE) && invalid == null) {
error(builder, JavaErrorMessages.message("expected.rbrace"));
}
}
private static PsiBuilder.Marker parseStatement(PsiBuilder builder) {
String kw = builder.getTokenText();
if (PsiKeyword.REQUIRES.equals(kw)) return parseRequiresStatement(builder);
if (PsiKeyword.EXPORTS.equals(kw)) return parseExportsStatement(builder);
if (PsiKeyword.USES.equals(kw)) return parseUsesStatement(builder);
if (PsiKeyword.PROVIDES.equals(kw)) return parseProvidesStatement(builder);
return null;
}
private static PsiBuilder.Marker parseRequiresStatement(PsiBuilder builder) {
PsiBuilder.Marker statement = builder.mark();
mapAndAdvance(builder, JavaTokenType.REQUIRES_KEYWORD);
expect(builder, JavaTokenType.PUBLIC_KEYWORD);
if (parseNameRef(builder) != null) {
semicolon(builder);
}
else {
expect(builder, JavaTokenType.SEMICOLON);
}
statement.done(JavaElementType.REQUIRES_STATEMENT);
return statement;
}
private static PsiBuilder.Marker parseExportsStatement(PsiBuilder builder) {
PsiBuilder.Marker statement = builder.mark();
boolean hasError = false;
mapAndAdvance(builder, JavaTokenType.EXPORTS_KEYWORD);
if (parseClassOrPackageRef(builder) != null) {
if (PsiKeyword.TO.equals(builder.getTokenText())) {
mapAndAdvance(builder, JavaTokenType.TO_KEYWORD);
while (true) {
PsiBuilder.Marker ref = parseNameRef(builder);
if (!expect(builder, JavaTokenType.COMMA)) {
if (ref == null) hasError = true;
break;
}
}
}
}
else {
error(builder, JavaErrorMessages.message("expected.package.reference"));
hasError = true;
}
if (!hasError) {
semicolon(builder);
}
else {
expect(builder, JavaTokenType.SEMICOLON);
}
statement.done(JavaElementType.EXPORTS_STATEMENT);
return statement;
}
private static PsiBuilder.Marker parseUsesStatement(PsiBuilder builder) {
PsiBuilder.Marker statement = builder.mark();
mapAndAdvance(builder, JavaTokenType.USES_KEYWORD);
if (parseClassOrPackageRef(builder) != null) {
semicolon(builder);
}
else {
error(builder, JavaErrorMessages.message("expected.class.reference"));
expect(builder, JavaTokenType.SEMICOLON);
}
statement.done(JavaElementType.USES_STATEMENT);
return statement;
}
private static PsiBuilder.Marker parseProvidesStatement(PsiBuilder builder) {
PsiBuilder.Marker statement = builder.mark();
boolean hasError = false;
mapAndAdvance(builder, JavaTokenType.PROVIDES_KEYWORD);
if (parseClassOrPackageRef(builder) == null) {
error(builder, JavaErrorMessages.message("expected.class.reference"));
hasError = true;
}
if (PsiKeyword.WITH.equals(builder.getTokenText())) {
mapAndAdvance(builder, JavaTokenType.WITH_KEYWORD);
if (parseClassOrPackageRef(builder) == null) {
error(builder, JavaErrorMessages.message("expected.class.reference"));
hasError = true;
}
}
else if (!hasError) {
error(builder, JavaErrorMessages.message("expected.with"));
hasError = true;
}
if (!hasError) {
semicolon(builder);
}
else {
expect(builder, JavaTokenType.SEMICOLON);
}
statement.done(JavaElementType.PROVIDES_STATEMENT);
return statement;
}
private static PsiBuilder.Marker parseNameRef(PsiBuilder builder) {
PsiBuilder.Marker name = parseName(builder);
if (name == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
return name;
}
private static void mapAndAdvance(PsiBuilder builder, IElementType keyword) {
builder.remapCurrentToken(keyword);
builder.advanceLexer();
}
private static void parseExtras(PsiBuilder builder, String message) {
PsiBuilder.Marker extras = builder.mark();
while (builder.getTokenType() != null) builder.advanceLexer();
extras.error(message);
}
private static PsiBuilder.Marker parseClassOrPackageRef(PsiBuilder builder) {
return JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, true, false, false, false);
}
}
@@ -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
@@ -256,6 +256,12 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
return level;
}
@Nullable
@Override
public PsiJavaModule getModuleDeclaration() {
return null;
}
@Override
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
throw cannotModifyException(this);
@@ -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;
}
@@ -0,0 +1,44 @@
/*
* 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.source;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiExportsStatement;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiExportsStatementImpl extends CompositePsiElement implements PsiExportsStatement {
public PsiExportsStatementImpl() {
super(JavaElementType.EXPORTS_STATEMENT);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitExportsStatement(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiExportsStatement";
}
}
@@ -49,6 +49,7 @@ import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MostlySingularMultiMap;
import com.intellij.util.indexing.IndexingDataKeys;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -107,6 +108,10 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
@Override
public void setPackageName(final String packageName) throws IncorrectOperationException {
if (PsiUtil.isModuleFile(this)) {
throw new IncorrectOperationException("Cannot set package name for module declarations");
}
final PsiPackageStatement packageStatement = getPackageStatement();
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
if (packageStatement != null) {
@@ -118,36 +123,33 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
packageStatement.delete();
}
}
else {
if (!packageName.isEmpty()) {
addBefore(factory.createPackageStatement(packageName), getFirstChild());
}
else if (!packageName.isEmpty()) {
addBefore(factory.createPackageStatement(packageName), getFirstChild());
}
}
@Override
@NotNull
public PsiImportList getImportList() {
StubElement<?> stub = getStub();
if (stub != null) {
PsiImportList[] nodes = stub.getChildrenByType(JavaStubElementTypes.IMPORT_LIST, PsiImportList.ARRAY_FACTORY);
if (nodes.length != 1) {
reportStubAstMismatch(stub + "; " + stub.getChildrenStubs(), getStubTree(), PsiDocumentManager.getInstance(getProject()).getCachedDocument(this));
}
return nodes[0];
if (nodes.length == 1) return nodes[0];
if (nodes.length == 0) return null;
reportStubAstMismatch(stub + "; " + stub.getChildrenStubs(), getStubTree(), PsiDocumentManager.getInstance(getProject()).getCachedDocument(this));
}
ASTNode node = calcTreeElement().findChildByType(JavaElementType.IMPORT_LIST);
assert node != null : getFileType() + ", " + getName();
return SourceTreeToPsiMap.treeToPsiNotNull(node);
return (PsiImportList)SourceTreeToPsiMap.treeElementToPsi(node);
}
@Override
@NotNull
public PsiElement[] getOnDemandImports(boolean includeImplicit, boolean checkIncludes) {
PsiImportList importList = getImportList();
if (importList == null) return EMPTY_ARRAY;
List<PsiElement> array = new ArrayList<PsiElement>();
PsiImportList importList = getImportList();
PsiImportStatement[] statements = importList.getImportStatements();
for (PsiImportStatement statement : statements) {
if (statement.isOnDemand()) {
@@ -174,8 +176,10 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
@Override
@NotNull
public PsiClass[] getSingleClassImports(boolean checkIncludes) {
List<PsiClass> array = new ArrayList<PsiClass>();
PsiImportList importList = getImportList();
if (importList == null) return PsiClass.EMPTY_ARRAY;
List<PsiClass> array = new ArrayList<PsiClass>();
PsiImportStatement[] statements = importList.getImportStatements();
for (PsiImportStatement statement : statements) {
if (!statement.isOnDemand()) {
@@ -191,12 +195,14 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
@Override
public PsiJavaCodeReferenceElement findImportReferenceTo(PsiClass aClass) {
PsiImportList importList = getImportList();
PsiImportStatement[] statements = importList.getImportStatements();
for (PsiImportStatement statement : statements) {
if (!statement.isOnDemand()) {
PsiElement ref = statement.resolve();
if (ref != null && getManager().areElementsEquivalent(ref, aClass)) {
return statement.getImportReference();
if (importList != null) {
PsiImportStatement[] statements = importList.getImportStatements();
for (PsiImportStatement statement : statements) {
if (!statement.isOnDemand()) {
PsiElement ref = statement.resolve();
if (ref != null && getManager().areElementsEquivalent(ref, aClass)) {
return statement.getImportReference();
}
}
}
}
@@ -316,7 +322,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
if (!processor.execute(aClass, state)) return false;
}
final PsiImportStatement[] importStatements = importList.getImportStatements();
final PsiImportStatement[] importStatements = importList != null ? importList.getImportStatements() : PsiImportStatement.EMPTY_ARRAY;
// single-type processing
for (PsiImportStatement statement : importStatements) {
@@ -360,7 +366,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
}
}
final PsiImportStaticStatement[] importStaticStatements = importList.getImportStaticStatements();
final PsiImportStaticStatement[] importStaticStatements = importList != null ? importList.getImportStaticStatements() : PsiImportStaticStatement.EMPTY_ARRAY;
if (importStaticStatements.length > 0) {
final StaticImportFilteringProcessor staticImportProcessor = new StaticImportFilteringProcessor(processor);
@@ -470,6 +476,12 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
return LANGUAGE_LEVEL_KEY.getValue(this);
}
@Nullable
@Override
public PsiJavaModule getModuleDeclaration() {
return null;
}
@Override
public void clearCaches() {
super.clearCaches();
@@ -17,21 +17,33 @@ package com.intellij.psi.impl.source;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PsiJavaFileImpl extends PsiJavaFileBaseImpl {
public PsiJavaFileImpl(FileViewProvider file) {
super(JavaStubElementTypes.JAVA_FILE, JavaStubElementTypes.JAVA_FILE, file);
}
@Override
@NotNull
@Override
public FileType getFileType() {
return JavaFileType.INSTANCE;
}
@Nullable
@Override
public PsiJavaModule getModuleDeclaration() {
PsiElement element = getFirstChild();
if (element instanceof PsiWhiteSpace || element instanceof PsiComment) {
element = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class, PsiComment.class);
}
return element instanceof PsiJavaModule ? (PsiJavaModule)element : null;
}
@Override
public String toString() {
return "PsiJavaFile:" + getName();
@@ -0,0 +1,57 @@
/*
* 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.source;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PsiJavaModuleImpl extends CompositePsiElement implements PsiJavaModule {
public PsiJavaModuleImpl() {
super(JavaElementType.MODULE);
}
@Nullable
@Override
public PsiJavaModuleReference getNameElement() {
return PsiTreeUtil.getChildOfType(this, PsiJavaModuleReference.class);
}
@Nullable
@Override
public String getModuleName() {
PsiJavaModuleReference nameElement = getNameElement();
return nameElement != null ? nameElement.getReferenceText() : null;
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitModule(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiJavaModule:" + getModuleName();
}
}
@@ -0,0 +1,54 @@
/*
* 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.source;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiJavaModuleReferenceImpl extends CompositePsiElement implements PsiJavaModuleReference {
public PsiJavaModuleReferenceImpl() {
super(JavaElementType.MODULE_REFERENCE);
}
@NotNull
@Override
public String getReferenceText() {
StringBuilder sb = new StringBuilder();
for (PsiElement e = getFirstChild(); e != null; e = e.getNextSibling()) {
if (!(e instanceof PsiWhiteSpace) && !(e instanceof PsiComment)) {
sb.append(e.getText());
}
}
return sb.toString();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitModuleReference(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiJavaModuleReference";
}
}
@@ -0,0 +1,44 @@
/*
* 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.source;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiProvidesStatement;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiProvidesStatementImpl extends CompositePsiElement implements PsiProvidesStatement {
public PsiProvidesStatementImpl() {
super(JavaElementType.PROVIDES_STATEMENT);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitProvidesStatement(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiProvidesStatement";
}
}
@@ -0,0 +1,44 @@
/*
* 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.source;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiRequiresStatement;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiRequiresStatementImpl extends CompositePsiElement implements PsiRequiresStatement {
public PsiRequiresStatementImpl() {
super(JavaElementType.REQUIRES_STATEMENT);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitRequiresStatement(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiRequiresStatement";
}
}
@@ -0,0 +1,44 @@
/*
* 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.source;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiUsesStatement;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiUsesStatementImpl extends CompositePsiElement implements PsiUsesStatement {
public PsiUsesStatementImpl() {
super(JavaElementType.USES_STATEMENT);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitUsesStatement(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiUsesStatement";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,8 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
IMPORT_KEYWORD, INSTANCEOF_KEYWORD, INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD,
PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, RETURN_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, STATIC_KEYWORD, STRICTFP_KEYWORD,
SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, THROWS_KEYWORD, TRANSIENT_KEYWORD, TRY_KEYWORD, VOID_KEYWORD,
VOLATILE_KEYWORD, WHILE_KEYWORD);
VOLATILE_KEYWORD, WHILE_KEYWORD,
MODULE_KEYWORD, REQUIRES_KEYWORD, EXPORTS_KEYWORD, USES_KEYWORD, PROVIDES_KEYWORD, TO_KEYWORD, WITH_KEYWORD);
TokenSet LITERAL_BIT_SET = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD);
@@ -139,6 +139,13 @@ public interface JavaElementType {
IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class);
IElementType RECEIVER_PARAMETER = new JavaCompositeElementType("RECEIVER", PsiReceiverParameterImpl.class);
IElementType MODULE = new JavaCompositeElementType("MODULE", PsiJavaModuleImpl.class);
IElementType MODULE_REFERENCE = new JavaCompositeElementType("MODULE_NAME", PsiJavaModuleReferenceImpl.class);
IElementType REQUIRES_STATEMENT = new JavaCompositeElementType("REQUIRES_STATEMENT", PsiRequiresStatementImpl.class);
IElementType EXPORTS_STATEMENT = new JavaCompositeElementType("EXPORTS_STATEMENT", PsiExportsStatementImpl.class);
IElementType USES_STATEMENT = new JavaCompositeElementType("USES_STATEMENT", PsiUsesStatementImpl.class);
IElementType PROVIDES_STATEMENT = new JavaCompositeElementType("PROVIDES_STATEMENT", PsiProvidesStatementImpl.class);
class ICodeBlockElementType extends IErrorCounterReparseableElementType implements ICompositeElementType, ILightLazyParseableElementType {
private ICodeBlockElementType() {
super("CODE_BLOCK", JavaLanguage.INSTANCE);
@@ -91,6 +91,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
boolean doImportStatic;
if (containingFile instanceof PsiJavaFile) {
importList = ((PsiJavaFile)containingFile).getImportList();
assert importList != null : containingFile;
PsiImportStatementBase singleImportStatement = importList.findSingleImportStatement(staticName);
doImportStatic = singleImportStatement == null;
if (singleImportStatement instanceof PsiImportStaticStatement) {
@@ -116,8 +117,8 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
return this;
}
public static void bindToElementViaStaticImport(final PsiClass qualifierClass, final String staticName, final PsiImportList importList)
throws IncorrectOperationException {
public static void bindToElementViaStaticImport(PsiClass qualifierClass, String staticName, PsiImportList importList) throws IncorrectOperationException {
assert importList != null;
final String qualifiedName = qualifierClass.getQualifiedName();
final List<PsiJavaCodeReferenceElement> refs = getImportsFromClass(importList, qualifiedName);
if (refs.size() < JavaCodeStyleSettingsFacade.getInstance(qualifierClass.getProject()).getNamesCountToUseImportOnDemand()) {
@@ -336,6 +336,7 @@ expected.rbracket=']' expected
expected.expression=Expression expected
expected.semicolon=';' expected
expected.class.reference=Class reference expected
expected.package.reference=Package reference expected
expected.lparen='(' expected
expected.rparen=')' expected
expected.eq='=' expected
@@ -351,6 +352,7 @@ expected.type.parameter=Type parameter expected
expected.comma=',' expected
expected.comma.or.rparen=',' or ')' expected
expected.colon=':' expected
expected.dot='.' expected
expected.type=Type expected
expected.lbracket='[' expected
expected.lparen.or.lbracket='(' or '[' expected
@@ -365,6 +367,10 @@ expected.statement=Statement expected
expected.while='while' expected
expected.catch.or.finally='catch' or 'finally' expected
expected.boolean.expression=Boolean expression expected
expected.with='with' expected
expected.module.declaration=Module declaration expected
expected.module.statement=Module statement expected
error.cannot.resolve.class=Cannot resolve class ''{0}''
error.cannot.resolve.class.or.package=Cannot resolve class or package ''{0}''
expected.class.or.package=Expected class or package
@@ -379,11 +385,17 @@ cannot.resolve.package=Cannot resolve package {0}
override.not.allowed.in.interfaces=@Override is not allowed when implementing interface method
wildcard.not.expected=Unexpected wildcard
bound.not.expected=Unexpected bound
declaration.not.allowed=Declaration not allowed here
underscore.identifier.warn=Use of '_' as an identifier might not be supported in releases after Java 8
underscore.identifier.error=As of Java 9, '_' is a keyword, and may not be used as an identifier
underscore.lambda.identifier=Use of '_' as a lambda parameter name is not allowed
module.file.wrong.name=Module declaration should be in a file named 'module-info.java'
module.illegal.name=Illegal module name
module.file.duplicate=Multiple module declarations
module.file.wrong.location=Module declaration should be located in a module's source root
feature.generics=Generics
feature.annotations=Annotations
feature.static.imports=Static imports
@@ -401,5 +413,5 @@ feature.lambda.expressions=Lambda expressions
feature.type.annotations=Type annotations
feature.type.receivers=Receiver parameters
feature.try.with.resources.refs=Resource references
feature.modules=Modules
insufficient.language.level={0} are not supported at this language level
declaration.not.allowed=Declaration not allowed here
@@ -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(){
@@ -5,6 +5,6 @@ public class Main {
protected Object obj = null;
private long e = 4;
public static void main(String[] args) {
public static void main(String[] args) {
}
}
@@ -4,7 +4,7 @@ class C implements A {
interface A {
A a = new C(<error descr="'A.this' cannot be referenced from a static context">this</error>);
A a1 = new C(<error descr="Cannot find symbol variable this">this</error>){};
A a1 = new C(<error descr="'A.this' cannot be referenced from a static context">this</error>){};
class B {
A foo() {
@@ -0,0 +1,17 @@
class A {
public A(Object o) {
}
}
class B {}
class C extends B {
static {
A a = new A(<error descr="'C.this' cannot be referenced from a static context">this</error>) {};
A a1 = new A(<error descr="'C.super' cannot be referenced from a static context">super</error>.clone()) {};
}
{
A a = new A(this);
}
}

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