+Reports the escaped meta characters, e.g. \..
+Some RegExp coding styles specify that meta characters should be placed inside a character class,
+to make the regular expression easier to understand.
+For example the regex \d+\.\d+ would be written as \d+[.]\d+.
+This inspection does not warn about the meta character [, ] and ^,
+because those would need additional escaping inside a character class.
+
+
New in 2017.1
+
+
\ No newline at end of file
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspection.java b/RegExpSupport/src/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspection.java
new file mode 100644
index 000000000000..78f0d79f6594
--- /dev/null
+++ b/RegExpSupport/src/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspection.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.inspection;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import org.intellij.lang.regexp.RegExpTT;
+import org.intellij.lang.regexp.psi.RegExpBranch;
+import org.intellij.lang.regexp.psi.RegExpChar;
+import org.intellij.lang.regexp.psi.RegExpElementVisitor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class EscapedMetaCharacterInspection extends LocalInspectionTool {
+
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
+ return new EscapedMetaCharacterVisitor(holder);
+ }
+
+ private static class EscapedMetaCharacterVisitor extends RegExpElementVisitor {
+
+ private final ProblemsHolder myHolder;
+
+ public EscapedMetaCharacterVisitor(ProblemsHolder holder) {
+ myHolder = holder;
+ }
+
+ @Override
+ public void visitRegExpChar(RegExpChar ch) {
+ if (ch.getType() != RegExpChar.Type.CHAR) {
+ return;
+ }
+ final String text = ch.getUnescapedText();
+ if (text.length() != 2 || text.charAt(0) != '\\') {
+ return;
+ }
+ final char c = text.charAt(1);
+ switch (c) {
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ case '.':
+ case '*':
+ case '+':
+ case '?':
+ case '|':
+ case '$':
+ final ASTNode node = ch.getNode().getFirstChildNode();
+ if (node != null && node.getElementType() == RegExpTT.REDUNDANT_ESCAPE) {
+ return;
+ }
+ myHolder.registerProblem(ch, "Escaped meta character " + c + "", new EscapedMetaCharacterFix(c));
+ break;
+ }
+ }
+ }
+
+ private static class EscapedMetaCharacterFix implements LocalQuickFix {
+
+ private final char myC;
+
+ EscapedMetaCharacterFix(char c) {
+ myC = c;
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getName() {
+ return "Replace with '[" + myC + "]'";
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Replace with character inside class";
+ }
+
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ if (!(element instanceof RegExpChar)) {
+ return;
+ }
+ final RegExpBranch branch = RegExpFactory.createBranchFromText("[" + myC + ']', element);
+ element.replace(branch.getFirstChild());
+ }
+ }
+}
diff --git a/RegExpSupport/test/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspectionTest.java b/RegExpSupport/test/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspectionTest.java
new file mode 100644
index 000000000000..ac69291ad304
--- /dev/null
+++ b/RegExpSupport/test/org/intellij/lang/regexp/inspection/EscapedMetaCharacterInspectionTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.intellij.lang.regexp.inspection;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class EscapedMetaCharacterInspectionTest extends RegExpInspectionTestCase {
+
+ public void testSimple() {
+ quickfixTest("\\.", "[.]", "Replace with '[.]'");
+ }
+
+ public void testNoWarn() {
+ highlightTest("\\[\\^\\]");
+ }
+
+ public void testHighlighting() {
+ highlightTest("\\{" +
+ "\\}" + // already has redundant character escape warning
+ "\\(" +
+ "\\)" +
+ "\\." +
+ "\\*" +
+ "\\+" +
+ "\\?" +
+ "\\|" +
+ "\\$");
+ }
+
+ @NotNull
+ @Override
+ protected LocalInspectionTool getInspection() {
+ return new EscapedMetaCharacterInspection();
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
index 9143d38890b7..52f48bc28bf4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
@@ -34,14 +34,14 @@ import com.sun.jdi.VMDisconnectedException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
/**
* @author lex
*/
public class DebuggerManagerThreadImpl extends InvokeAndWaitThread implements DebuggerManagerThread, Disposable {
private static final Logger LOG = Logger.getInstance(DebuggerManagerThreadImpl.class);
- public static final int COMMAND_TIMEOUT = 3000;
+ static final int COMMAND_TIMEOUT = 3000;
private volatile boolean myDisposed;
@@ -55,6 +55,19 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread future) {
+ try {
+ LOG.debug("Waiting for " + future);
+ future.get(1, TimeUnit.MINUTES);
+ }
+ catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ catch (TimeoutException e) {
+ throw new RuntimeException("Termination request is still pending", e);
+ }
+ }
+
@TestOnly
public static DebuggerManagerThreadImpl createTestInstance(@NotNull Disposable parent, Project project) {
return new DebuggerManagerThreadImpl(parent, project);
@@ -106,13 +119,13 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread future = AppExecutorUtil.getAppScheduledExecutorService().schedule(
() -> {
if (currentCommand == myEvents.getCurrentEvent()) {
// if current command is still in progress, cancel it
@@ -131,7 +144,10 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread waitForTerminateFutureToComplete(future));
}
}
@@ -174,7 +190,7 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread {
+ implements PersistentStateComponent {
private final EventDispatcher myDispatcher =
- EventDispatcher.create(InstancesTrackerListener.class);
+ EventDispatcher.create(InstancesTrackerListener.class);
private MyState myState = new MyState();
public InstancesTracker(Project project) {
@@ -84,7 +84,7 @@ public class InstancesTracker extends AbstractProjectComponent
public void setBackgroundTackingEnabled(boolean state) {
boolean oldState = myState.isBackgroundTrackingEnabled;
- if(state != oldState) {
+ if (state != oldState) {
myState.isBackgroundTrackingEnabled = state;
myDispatcher.getMulticaster().backgroundTrackingValueChanged(state);
}
@@ -104,7 +104,6 @@ public class InstancesTracker extends AbstractProjectComponent
static class MyState {
boolean isBackgroundTrackingEnabled = false;
- @NotNull
@AbstractCollection(surroundWithTag = false, elementTypes = {Map.Entry.class})
final Map classes = new ConcurrentHashMap<>();
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewComponent.java b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewComponent.java
index cc57dffe746e..fc9c91f31257 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewComponent.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewComponent.java
@@ -51,13 +51,19 @@ public class MemoryViewComponent extends AbstractProjectComponent {
@Override
public void processStarted(@NotNull XDebugProcess debugProcess) {
final XDebugSession session = debugProcess.getSession();
+ final Project project = session.getProject();
final DebugProcess javaProcess =
- DebuggerManager.getInstance(session.getProject()).getDebugProcess(debugProcess.getProcessHandler());
+ DebuggerManager.getInstance(project).getDebugProcess(debugProcess.getProcessHandler());
if (javaProcess instanceof DebugProcessImpl) {
final DebugProcessImpl processImpl = (DebugProcessImpl)javaProcess;
ApplicationManager.getApplication().invokeLater(() -> {
+ if (project.isDisposed()) {
+ return;
+ }
+
+ final InstancesTracker tracker = InstancesTracker.getInstance(project);
final RunnerLayoutUi ui = session.getUI();
- final ClassesFilteredView classesFilteredView = new ClassesFilteredView(session, processImpl);
+ final ClassesFilteredView classesFilteredView = new ClassesFilteredView(session, processImpl, tracker);
classesFilteredView.setActive(true);
final Content memoryViewContent =
ui.createContent(MEMORY_VIEW_CONTENT_ID, classesFilteredView, "Memory View",
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/tracking/ConstructorInstancesTracker.java b/java/debugger/impl/src/com/intellij/debugger/memory/tracking/ConstructorInstancesTracker.java
index 0ba28d87c153..4899b1ee74fe 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/tracking/ConstructorInstancesTracker.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/tracking/ConstructorInstancesTracker.java
@@ -69,16 +69,16 @@ public class ConstructorInstancesTracker implements TrackerForNewInstances, Disp
private volatile boolean myIsBackgroundTrackingEnabled;
public ConstructorInstancesTracker(@NotNull ReferenceType ref,
- @NotNull XDebugSession debugSession) {
+ @NotNull XDebugSession debugSession,
+ @NotNull InstancesTracker instancesTracker) {
myReference = ref;
myProject = debugSession.getProject();
- myIsBackgroundTrackingEnabled = InstancesTracker.getInstance(myProject)
- .isBackgroundTrackingEnabled();
+ myIsBackgroundTrackingEnabled = instancesTracker.isBackgroundTrackingEnabled();
final DebugProcessImpl debugProcess = (DebugProcessImpl)DebuggerManager.getInstance(myProject)
.getDebugProcess(debugSession.getDebugProcess().getProcessHandler());
- InstancesTracker.getInstance(myProject).addTrackerListener(new InstancesTrackerListener() {
+ instancesTracker.addTrackerListener(new InstancesTrackerListener() {
@Override
public void backgroundTrackingValueChanged(boolean newState) {
if (myIsBackgroundTrackingEnabled != newState) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java
index fa090419063a..08c03e639a5e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java
@@ -62,6 +62,7 @@ import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -104,12 +105,14 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable
*/
private boolean myIsActive;
- public ClassesFilteredView(@NotNull XDebugSession debugSession, @NotNull DebugProcessImpl debugProcess) {
+ public ClassesFilteredView(@NotNull XDebugSession debugSession,
+ @NotNull DebugProcessImpl debugProcess,
+ @NotNull InstancesTracker tracker) {
super();
myProject = debugSession.getProject();
- myInstancesTracker = InstancesTracker.getInstance(myProject);
+ myInstancesTracker = tracker;
final InstancesTrackerListener instancesTrackerListener = new InstancesTrackerListener() {
@Override
public void classChanged(@NotNull String name, @NotNull TrackingType type) {
@@ -147,7 +150,7 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable
@Override
protected void action() throws Exception {
final boolean activated = myIsTrackersActivated.get();
- myInstancesTracker.getTrackedClasses().forEach((className, type) -> {
+ tracker.getTrackedClasses().forEach((className, type) -> {
List classes = debugProcess.getVirtualMachineProxy().classesByName(className);
if (classes.isEmpty()) {
new ClassPreparedListener(className, debugSession) {
@@ -164,14 +167,14 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable
}
});
- myInstancesTracker.addTrackerListener(instancesTrackerListener, ClassesFilteredView.this);
+ tracker.addTrackerListener(instancesTrackerListener, ClassesFilteredView.this);
}
});
final MemoryViewManagerState memoryViewManagerState = MemoryViewManager.getInstance().getState();
- myTable = new ClassesTable(debugSession, memoryViewManagerState.isShowWithDiffOnly,
- memoryViewManagerState.isShowWithInstancesOnly, memoryViewManagerState.isShowTrackedOnly, this);
+ myTable = new ClassesTable(tracker, this, memoryViewManagerState.isShowWithDiffOnly,
+ memoryViewManagerState.isShowWithInstancesOnly, memoryViewManagerState.isShowTrackedOnly);
myTable.getEmptyText().setText(EMPTY_TABLE_CONTENT_WHEN_RUNNING);
Disposer.register(this, myTable);
@@ -286,7 +289,7 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable
return;
}
- final ConstructorInstancesTracker tracker = new ConstructorInstancesTracker(ref, debugSession);
+ final ConstructorInstancesTracker tracker = new ConstructorInstancesTracker(ref, debugSession, myInstancesTracker);
tracker.setBackgroundMode(!myIsActive);
if (isTrackerEnabled) {
tracker.enable();
@@ -303,7 +306,10 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable
private void handleClassSelection(@Nullable ReferenceType ref) {
final XDebugSession debugSession = XDebuggerManager.getInstance(myProject).getCurrentSession();
if (ref != null && debugSession != null && debugSession.isSuspended()) {
- new InstancesWindow(debugSession, limit -> ref.instances(limit), ref.name()).show();
+ new InstancesWindow(debugSession, limit -> {
+ final List instances = ref.instances(limit);
+ return instances == null ? Collections.emptyList() : instances;
+ }, ref.name()).show();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java
index b363f7990fec..e024d4492c61 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java
@@ -37,7 +37,6 @@ import com.intellij.ui.table.JBTable;
import com.intellij.util.containers.FList;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBUI;
-import com.intellij.xdebugger.XDebugSession;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import org.jetbrains.annotations.NonNls;
@@ -79,14 +78,15 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable {
private volatile List myItems = Collections.unmodifiableList(new ArrayList<>());
- ClassesTable(@NotNull XDebugSession session, boolean onlyWithDiff, boolean onlyWithInstances,
- boolean onlyTracked, @NotNull ClassesFilteredView parent) {
+ public ClassesTable(@NotNull InstancesTracker tracker, @NotNull ClassesFilteredView parent, boolean onlyWithDiff,
+ boolean onlyWithInstances,
+ boolean onlyTracked) {
setModel(myModel);
myOnlyWithDiff = onlyWithDiff;
myOnlyWithInstances = onlyWithInstances;
myOnlyTracked = onlyTracked;
- myInstancesTracker = InstancesTracker.getInstance(session.getProject());
+ myInstancesTracker = tracker;
myParent = parent;
TableColumn classesColumn = getColumnModel().getColumn(DiffViewTableModel.CLASSNAME_COLUMN_INDEX);
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/ui/InstancesWithStackFrameView.java b/java/debugger/impl/src/com/intellij/debugger/memory/ui/InstancesWithStackFrameView.java
index 4fc5b098e06f..a04795139ca8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/ui/InstancesWithStackFrameView.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/ui/InstancesWithStackFrameView.java
@@ -24,6 +24,7 @@ import com.intellij.debugger.memory.utils.StackFrameItem;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.project.Project;
import com.intellij.ui.JBSplitter;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBScrollPane;
@@ -49,9 +50,10 @@ class InstancesWithStackFrameView {
private boolean myIsHided = false;
InstancesWithStackFrameView(@NotNull XDebugSession debugSession, @NotNull InstancesTree tree,
- @NotNull StackFrameList list, String className) {
+ @NotNull StackFrameList list, @NotNull String className) {
mySplitter.setFirstComponent(new JBScrollPane(tree));
+ final Project project = debugSession.getProject();
list.setEmptyText(EMPTY_TEXT_WHEN_ITEM_NOT_SELECTED);
JLabel stackTraceLabel;
if (isArrayType(className)) {
@@ -63,8 +65,10 @@ class InstancesWithStackFrameView {
new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
- InstancesTracker.getInstance(debugSession.getProject())
- .add(className, TrackingType.CREATION);
+ final Project project = e.getProject();
+ if (project != null && !project.isDisposed()) {
+ InstancesTracker.getInstance(project).add(className, TrackingType.CREATION);
+ }
}
});
@@ -77,30 +81,32 @@ class InstancesWithStackFrameView {
JComponent stackComponent = new JBScrollPane(list);
- InstancesTracker instancesTracker = InstancesTracker.getInstance(debugSession.getProject());
- instancesTracker.addTrackerListener(new InstancesTrackerListener() {
- @Override
- public void classChanged(@NotNull String name, @NotNull TrackingType type) {
- if (Objects.equals(className, name) && type == TrackingType.CREATION) {
- mySplitter.setSecondComponent(stackComponent);
+ if (!project.isDisposed()) {
+ final InstancesTracker tracker = InstancesTracker.getInstance(project);
+ tracker.addTrackerListener(new InstancesTrackerListener() {
+ @Override
+ public void classChanged(@NotNull String name, @NotNull TrackingType type) {
+ if (Objects.equals(className, name) && type == TrackingType.CREATION) {
+ mySplitter.setSecondComponent(stackComponent);
+ }
}
- }
- @Override
- public void classRemoved(@NotNull String name) {
- if (Objects.equals(name, className)) {
- mySplitter.setSecondComponent(stackTraceLabel);
+ @Override
+ public void classRemoved(@NotNull String name) {
+ if (Objects.equals(name, className)) {
+ mySplitter.setSecondComponent(stackTraceLabel);
+ }
}
- }
- }, tree);
+ }, tree);
- mySplitter.setSecondComponent(instancesTracker.isTracked(className) ? stackComponent : stackTraceLabel);
+ mySplitter.setSecondComponent(tracker.isTracked(className) ? stackComponent : stackTraceLabel);
+ }
mySplitter.setHonorComponentsMinimumSize(false);
myHidedProportion = DEFAULT_SPLITTER_PROPORTION;
final MemoryViewDebugProcessData data =
- DebuggerManager.getInstance(debugSession.getProject()).getDebugProcess(debugSession.getDebugProcess().getProcessHandler())
+ DebuggerManager.getInstance(project).getDebugProcess(debugSession.getDebugProcess().getProcessHandler())
.getUserData(MemoryViewDebugProcessData.KEY);
tree.addTreeSelectionListener(e -> {
ObjectReference ref = tree.getSelectedReference();
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java
index 9513b9691f6f..60a31c993ca8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java
@@ -17,6 +17,7 @@ package com.intellij.debugger.settings;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserFactory;
@@ -31,8 +32,11 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
+import com.intellij.util.PlatformIcons;
import com.intellij.util.ui.ItemRemovable;
import com.intellij.util.xmlb.XmlSerializer;
+import one.util.streamex.IntStreamEx;
+import one.util.streamex.StreamEx;
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.Nls;
@@ -48,6 +52,8 @@ import java.util.List;
* @author egor
*/
public class CaptureConfigurable implements SearchableConfigurable {
+ private static final Logger LOG = Logger.getInstance(CaptureConfigurable.class);
+
private MyTableModel myTableModel;
@NotNull
@@ -93,6 +99,26 @@ public class CaptureConfigurable implements SearchableConfigurable {
}
});
+ decorator.addExtraAction(new DumbAwareActionButton("Duplicate", "Duplicate", PlatformIcons.COPY_ICON) {
+ @Override
+ public boolean isEnabled() {
+ return table.getSelectedRowCount() == 1;
+ }
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ selectedCapturePoints(table).forEach(c -> {
+ try {
+ myTableModel.add(c.clone());
+ table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1);
+ }
+ catch (CloneNotSupportedException ex) {
+ LOG.error(ex);
+ }
+ });
+ }
+ });
+
decorator.addExtraAction(new DumbAwareActionButton("Import", "Import", AllIcons.Actions.Install) {
@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
@@ -136,16 +162,16 @@ public class CaptureConfigurable implements SearchableConfigurable {
if (wrapper == null) return;
Element rootElement = new Element("capture-points");
- for (int row : table.getSelectedRows()) {
- CapturePoint c = myTableModel.get(table.convertRowIndexToModel(row));
+ selectedCapturePoints(table).forEach(c -> {
try {
CapturePoint clone = c.clone();
clone.myEnabled = false;
rootElement.addContent(XmlSerializer.serialize(clone));
}
- catch (CloneNotSupportedException ignore) {
+ catch (CloneNotSupportedException ex) {
+ LOG.error(ex);
}
- }
+ });
try {
JDOMUtil.writeDocument(new Document(rootElement), wrapper.getFile(), "\n");
}
@@ -164,6 +190,10 @@ public class CaptureConfigurable implements SearchableConfigurable {
return decorator.createPanel();
}
+ private StreamEx selectedCapturePoints(JBTable table) {
+ return IntStreamEx.of(table.getSelectedRows()).map(table::convertRowIndexToModel).mapToObj(myTableModel::get);
+ }
+
private static class MyTableModel extends AbstractTableModel implements ItemRemovable {
public static final int ENABLED_COLUMN = 0;
public static final int CLASS_COLUMN = 1;
diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
index b2fbc479fd4a..99376e50e1ec 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
@@ -298,7 +298,7 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration> exports = CachedValuesManager.getCachedValue(source, () ->
Result.create(exportsMap(source), source.getContainingFile()));
Set targets = exports.get(packageName);
- return targets != null && (targets.isEmpty() || targets.contains(target.getModuleName()));
+ return targets != null && (targets.isEmpty() || targets.contains(target.getName()));
}
public static boolean reads(@NotNull PsiJavaModule source, @NotNull PsiJavaModule destination) {
@@ -178,7 +178,7 @@ public class JavaModuleGraphUtil {
}
public static String key(PsiJavaModule module, PsiJavaModule exporter) {
- return module.getModuleName() + '/' + exporter.getModuleName();
+ return module.getName() + '/' + exporter.getName();
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java
index 13625596af71..7f8030f7d531 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java
@@ -223,13 +223,13 @@ public class ModuleHighlightUtil {
return moduleResolveError(refElement, ref);
}
else if (target == container) {
- String message = JavaErrorMessages.message("module.cyclic.dependence", container.getModuleName());
+ String message = JavaErrorMessages.message("module.cyclic.dependence", container.getName());
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).description(message).create();
}
else {
Collection cycle = JavaModuleGraphUtil.findCycle((PsiJavaModule)target);
if (cycle != null && cycle.contains(container)) {
- Stream stream = cycle.stream().map(PsiJavaModule::getModuleName);
+ Stream stream = cycle.stream().map(PsiJavaModule::getName);
if (ApplicationManager.getApplication().isUnitTestMode()) stream = stream.sorted();
String message = JavaErrorMessages.message("module.cyclic.dependence", stream.collect(Collectors.joining(", ")));
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).description(message).create();
@@ -373,8 +373,8 @@ public class ModuleHighlightUtil {
return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create();
}
- String refModuleName = refModule.getModuleName();
- String requiredName = targetModule.getModuleName();
+ String refModuleName = refModule.getName();
+ String requiredName = targetModule.getName();
if (!(targetModule instanceof LightJavaModule || JavaModuleGraphUtil.exports(targetModule, packageName, refModule))) {
String message = JavaErrorMessages.message("module.package.not.exported", requiredName, packageName, refModuleName);
return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create();
@@ -421,7 +421,7 @@ public class ModuleHighlightUtil {
private static TextRange range(PsiJavaModule module) {
PsiKeyword kw = PsiTreeUtil.getChildOfType(module, PsiKeyword.class);
- return new TextRange(kw != null ? kw.getTextOffset() : module.getTextOffset(), module.getNameElement().getTextRange().getEndOffset());
+ return new TextRange(kw != null ? kw.getTextOffset() : module.getTextOffset(), module.getNameIdentifier().getTextRange().getEndOffset());
}
private static PsiElement range(PsiJavaCodeReferenceElement refElement) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddRequiredModuleFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddRequiredModuleFix.java
index 27fce6ec163b..1f41b4ac15e1 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddRequiredModuleFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddRequiredModuleFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,8 +66,7 @@ public class AddRequiredModuleFix implements IntentionAction {
if (module == null) return;
PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(project).getParserFacade();
- PsiJavaModule tempModule =
- parserFacade.createModuleFromText("module " + module.getModuleName() + " { requires " + myRequiredName + "; }");
+ PsiJavaModule tempModule = parserFacade.createModuleFromText("module " + module.getName() + " { requires " + myRequiredName + "; }");
Iterable tempModuleRequires = tempModule.getRequires();
PsiRequiresStatement requiresStatement = tempModuleRequires.iterator().next();
@@ -90,7 +89,7 @@ public class AddRequiredModuleFix implements IntentionAction {
@Nullable
private static PsiElement getLBrace(@NotNull PsiJavaModule module) {
- PsiJavaModuleReferenceElement nameElement = module.getNameElement();
+ PsiJavaModuleReferenceElement nameElement = module.getNameIdentifier();
for (PsiElement element = nameElement.getNextSibling(); element != null; element = element.getNextSibling()) {
if (PsiUtil.isJavaToken(element, JavaTokenType.LBRACE)) {
return element;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
index 29942e804e9d..46129774dc11 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.quickfix.SimplifyBooleanExpressionFix;
import com.intellij.codeInsight.intention.impl.AddNotNullAnnotationFix;
@@ -48,12 +49,10 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.extractMethod.ExtractMethodUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.ArrayUtilRt;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
+import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
+import com.siyeh.ig.psiutils.TypeUtils;
import one.util.streamex.StreamEx;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -73,6 +72,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
public boolean REPORT_CONSTANT_REFERENCE_VALUES = true;
public boolean REPORT_NULLS_PASSED_TO_NOT_NULL_PARAMETER = true;
public boolean REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL = true;
+ public boolean REPORT_UNCHECKED_OPTIONALS = true;
@Override
public JComponent createOptionsPanel() {
@@ -98,6 +98,9 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
if (!REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL) {
node.addContent(new Element("option").setAttribute("name", "REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL").setAttribute("value", "false"));
}
+ if (!REPORT_UNCHECKED_OPTIONALS) {
+ node.addContent(new Element("option").setAttribute("name", "REPORT_UNCHECKED_OPTIONALS").setAttribute("value", "false"));
+ }
}
@Override
@@ -338,6 +341,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
reportOptionalOfNullableImprovements(holder, reportedAnchors, runner.getInstructions());
+ reportUncheckedOptionalGet(holder, visitor.getOptionalCalls(), visitor.getOptionalQualifiers());
if (REPORT_CONSTANT_REFERENCE_VALUES) {
reportConstantReferenceValues(holder, visitor, reportedAnchors);
@@ -348,6 +352,36 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
}
}
+ private void reportUncheckedOptionalGet(ProblemsHolder holder,
+ Map calls,
+ List qualifiers) {
+ for (Map.Entry entry : calls.entrySet()) {
+ ThreeState state = entry.getValue();
+ if (state == ThreeState.YES || state == ThreeState.UNSURE && !REPORT_UNCHECKED_OPTIONALS) {
+ continue;
+ }
+ PsiMethodCallExpression call = entry.getKey();
+ PsiMethod method = call.resolveMethod();
+ if (method == null) continue;
+ PsiClass optionalClass = method.getContainingClass();
+ if (optionalClass == null) continue;
+ if (state == ThreeState.NO) {
+ holder.registerProblem(getElementToHighlight(call),
+ InspectionsBundle.message("dataflow.message.optional.get.definitely.absent", optionalClass.getName()));
+ } else if (state == ThreeState.UNSURE) {
+ PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(call.getMethodExpression().getQualifierExpression());
+ if (qualifier instanceof PsiMethodCallExpression &&
+ qualifiers.stream().anyMatch(q -> PsiEquivalenceUtil.areElementsEquivalent(q, qualifier))) {
+ // Conservatively do not report methodCall().get() cases if methodCall().isPresent() was found in the same method
+ // without deep correspondence analysis
+ continue;
+ }
+ holder.registerProblem(getElementToHighlight(call),
+ InspectionsBundle.message("dataflow.message.optional.get.without.is.present", optionalClass.getName()));
+ }
+ }
+ }
+
private static void reportAlwaysReturnsNotNull(ProblemsHolder holder, PsiElement scope) {
if (!(scope.getParent() instanceof PsiMethod)) return;
@@ -895,6 +929,8 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
private final Map, StateInfo> myStateInfos = ContainerUtil.newHashMap();
private final Set myCCEInstructions = ContainerUtil.newHashSet();
private final Map myFailingCalls = new HashMap<>();
+ private final Map myOptionalCalls = new HashMap<>();
+ private final List myOptionalQualifiers = new ArrayList<>();
private boolean myAlwaysReturnsNotNull = true;
@Override
@@ -912,6 +948,14 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
});
}
+ Map getOptionalCalls() {
+ return myOptionalCalls;
+ }
+
+ List getOptionalQualifiers() {
+ return myOptionalQualifiers;
+ }
+
Collection getAlwaysFailingCalls() {
return StreamEx.ofKeys(myFailingCalls, v -> v).map(MethodCallInstruction::getCallExpression).toList();
}
@@ -924,6 +968,20 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
public DfaInstructionState[] visitMethodCall(MethodCallInstruction instruction,
DataFlowRunner runner,
DfaMemoryState memState) {
+ PsiMethodCallExpression call = ObjectUtils.tryCast(instruction.getCallExpression(), PsiMethodCallExpression.class);
+ if (call != null) {
+ String methodName = call.getMethodExpression().getReferenceName();
+ PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(call.getMethodExpression().getQualifierExpression());
+ if (qualifier != null && TypeUtils.isOptional(qualifier.getType())) {
+ if ("isPresent".equals(methodName) && qualifier instanceof PsiMethodCallExpression) {
+ myOptionalQualifiers.add(qualifier);
+ }
+ else if (isOptionalGetMethodName(methodName)) {
+ ThreeState state = memState.checkOptional(memState.peek());
+ myOptionalCalls.merge(call, state, (s1, s2) -> s1 == s2 ? s1 : ThreeState.UNSURE);
+ }
+ }
+ }
DfaInstructionState[] states = super.visitMethodCall(instruction, runner, memState);
if (hasNonTrivialFailingContracts(instruction)) {
boolean allFail = Arrays.stream(states).allMatch(s -> s.getMemoryState().peek() == runner.getFactory().getConstFactory().getContractFail());
@@ -932,6 +990,10 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
return states;
}
+ private static boolean isOptionalGetMethodName(String name) {
+ return "get".equals(name) || "getAsDouble".equals(name) || "getAsInt".equals(name) || "getAsLong".equals(name);
+ }
+
private static boolean hasNonTrivialFailingContracts(MethodCallInstruction instruction) {
List contracts = instruction.getContracts();
return !contracts.isEmpty() && contracts.stream().allMatch(DataFlowInstructionVisitor::isNonTrivialFailingContract);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
index 567161a3e08b..aa08cf6ebede 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
-import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
@@ -286,14 +285,14 @@ public class DataFlowRunner {
for (PsiMethod method : nestedClass.getMethods()) {
PsiCodeBlock body = method.getBody();
if (body != null) {
- myNestedClosures.putValue(body, createClosureState(state));
+ myNestedClosures.putValue(body, state.createClosureState());
}
}
for (PsiClassInitializer initializer : nestedClass.getInitializers()) {
- myNestedClosures.putValue(initializer.getBody(), createClosureState(state));
+ myNestedClosures.putValue(initializer.getBody(), state.createClosureState());
}
for (PsiField field : nestedClass.getFields()) {
- myNestedClosures.putValue(field, createClosureState(state));
+ myNestedClosures.putValue(field, state.createClosureState());
}
}
@@ -301,7 +300,7 @@ public class DataFlowRunner {
DfaMemoryState state = instructionState.getMemoryState();
PsiElement body = expr.getBody();
if (body != null) {
- myNestedClosures.putValue(body, createClosureState(state));
+ myNestedClosures.putValue(body, state.createClosureState());
}
}
@@ -359,16 +358,4 @@ public class DataFlowRunner {
return Pair.create(trueSet, falseSet);
}
-
- @NotNull
- private static DfaMemoryStateImpl createClosureState(@NotNull DfaMemoryState memState) {
- DfaMemoryStateImpl copy = (DfaMemoryStateImpl)memState.createCopy();
- copy.flushFields();
- Set vars = new HashSet<>(copy.getVariableStates().keySet());
- for (DfaVariableValue value : vars) {
- copy.flushDependencies(value);
- }
- copy.emptyStack();
- return copy;
- }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
index f78f66a45858..33997bbfdf07 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,9 @@ public interface DfaMemoryState {
@NotNull
DfaMemoryState createCopy();
+ @NotNull
+ DfaMemoryState createClosureState();
+
DfaValue pop();
DfaValue peek();
void push(@NotNull DfaValue value);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
index e37f3130f3d9..e34694d07798 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
@@ -53,6 +53,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
// dfa value id -> indices in myEqClasses list of the classes which contain the id (or wrapped)
private final TIntObjectHashMap myIdToEqClassesIndices;
private final Stack myStack;
+ // Closures which correspond to the stack top (do not track other closures for now)
+ private final List myStackTopClosures = new ArrayList<>();
private final TLongHashSet myDistinctClasses;
private final LinkedHashMap myVariableStates;
private final Map myDefaultVariableStates;
@@ -106,6 +108,24 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return new DfaMemoryStateImpl(this);
}
+ @NotNull
+ @Override
+ public DfaMemoryStateImpl createClosureState() {
+ DfaMemoryStateImpl copy = createCopy();
+ copy.flushFields();
+ Set vars = new HashSet<>(copy.getVariableStates().keySet());
+ for (DfaVariableValue value : vars) {
+ copy.flushDependencies(value);
+ }
+ copy.emptyStack();
+ myStackTopClosures.add(copy);
+ return copy;
+ }
+
+ List getStackTopClosures() {
+ return new ArrayList<>(myStackTopClosures);
+ }
+
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof DfaMemoryStateImpl)) return false;
@@ -221,6 +241,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public DfaValue pop() {
myCachedHash = null;
+ myStackTopClosures.clear();
return myStack.pop();
}
@@ -232,12 +253,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public void push(@NotNull DfaValue value) {
myCachedHash = null;
+ myStackTopClosures.clear();
myStack.push(value);
}
@Override
public void emptyStack() {
myCachedHash = null;
+ myStackTopClosures.clear();
while (!myStack.isEmpty() && !(myStack.peek() instanceof DfaControlTransferValue)) {
myStack.pop();
}
@@ -1116,7 +1139,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public boolean execute(int id, int[] set) {
DfaValue value = myFactory.getValue(id);
- s.append(value + " -> " + Arrays.toString(set) + ", ");
+ s.append(value).append(" -> ").append(Arrays.toString(set)).append(", ");
return true;
}
});
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index 5bad45e3d83c..6d0130b73580 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,9 @@ import static com.intellij.psi.JavaTokenType.*;
* @author peter
*/
public class StandardInstructionVisitor extends InstructionVisitor {
+ private static final Set OPTIONAL_METHOD_NAMES =
+ ContainerUtil.set("isPresent", "of", "ofNullable", "fromNullable", "empty", "absent",
+ "or", "orElseGet", "ifPresent", "map", "flatMap", "filter", "transform");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.StandardInstructionVisitor");
private static final Object ANY_VALUE = new Object();
private final Set myReachable = new THashSet<>();
@@ -180,13 +183,13 @@ public class StandardInstructionVisitor extends InstructionVisitor {
@Override
public DfaInstructionState[] visitMethodCall(final MethodCallInstruction instruction, final DataFlowRunner runner, final DfaMemoryState memState) {
- DfaValue[] argValues = popCallArguments(instruction, runner, memState);
- final DfaValue qualifier = popQualifier(instruction, runner, memState);
-
Set finalStates = ContainerUtil.newLinkedHashSet();
- finalStates.addAll(handleOptionalMethods(instruction, runner, memState, qualifier, argValues));
+ finalStates.addAll(handleOptionalMethods(instruction, runner, memState));
if (finalStates.isEmpty()) {
+ DfaValue[] argValues = popCallArguments(instruction, runner, memState);
+ final DfaValue qualifier = popQualifier(instruction, runner, memState);
+
LinkedHashSet currentStates = ContainerUtil.newLinkedHashSet(memState);
if (argValues != null) {
for (MethodContract contract : instruction.getContracts()) {
@@ -219,54 +222,63 @@ public class StandardInstructionVisitor extends InstructionVisitor {
}
@NotNull
- private static List handleOptionalMethods(MethodCallInstruction instruction,
- DataFlowRunner runner,
- DfaMemoryState memState,
- DfaValue qualifierValue, @Nullable DfaValue[] argValues) {
+ private List handleOptionalMethods(MethodCallInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
PsiMethodCallExpression call = ObjectUtils.tryCast(instruction.getCallExpression(), PsiMethodCallExpression.class);
if (call == null) return Collections.emptyList();
String methodName = call.getMethodExpression().getReferenceName();
- if ("isPresent".equals(methodName)) {
- PsiMethod method = call.resolveMethod();
- if (method != null && TypeUtils.isOptional(method.getContainingClass())) {
- ThreeState state = memState.checkOptional(qualifierValue);
+ if (methodName == null || !OPTIONAL_METHOD_NAMES.contains(methodName)) return Collections.emptyList();
+ PsiMethod method = call.resolveMethod();
+ if (method == null || !TypeUtils.isOptional(method.getContainingClass())) return Collections.emptyList();
+ List closures = ((DfaMemoryStateImpl)memState).getStackTopClosures();
+ DfaValue[] argValues = popCallArguments(instruction, runner, memState);
+ final DfaValue qualifier = popQualifier(instruction, runner, memState);
+ switch (methodName) {
+ case "isPresent": {
+ ThreeState state = memState.checkOptional(qualifier);
DfaConstValue.Factory constFactory = runner.getFactory().getConstFactory();
if (state == ThreeState.UNSURE) {
DfaMemoryState falseState = memState.createCopy();
memState.push(constFactory.getTrue());
- memState.applyIsPresentCheck(true, qualifierValue);
+ memState.applyIsPresentCheck(true, qualifier);
falseState.push(constFactory.getFalse());
- falseState.applyIsPresentCheck(false, qualifierValue);
+ falseState.applyIsPresentCheck(false, qualifier);
return Arrays.asList(memState, falseState);
}
else {
- DfaValue result = state == ThreeState.YES ? constFactory.getTrue() : constFactory.getFalse();
- memState.push(result);
- return Collections.singletonList(memState);
+ memState.push(state == ThreeState.YES ? constFactory.getTrue() : constFactory.getFalse());
}
+ break;
}
- }
- if ("of".equals(methodName)) {
- PsiMethod method = call.resolveMethod();
- if (method != null && TypeUtils.isOptional(method.getContainingClass())) {
- memState.push(runner.getFactory().getOptionalFactory().getOptional(true));
- return Collections.singletonList(memState);
- }
- }
- if (DfaOptionalSupport.resolveOfNullable(call) != null) {
- if (argValues != null && argValues.length == 1 && memState.isNotNull(argValues[0])) {
- memState.push(runner.getFactory().getOptionalFactory().getOptional(true));
- return Collections.singletonList(memState);
- }
- }
- if ("empty".equals(methodName) || "absent".equals(methodName)) {
- PsiMethod method = call.resolveMethod();
- if (method != null && TypeUtils.isOptional(method.getContainingClass())) {
+ case "of":
+ case "ofNullable":
+ case "fromNullable":
+ if ("of".equals(methodName) || (argValues != null && argValues.length == 1 && memState.isNotNull(argValues[0]))) {
+ memState.push(runner.getFactory().getOptionalFactory().getOptional(true));
+ } else {
+ memState.push(getMethodResultValue(instruction, qualifier, runner.getFactory()));
+ }
+ break;
+ case "empty":
+ case "absent":
memState.push(runner.getFactory().getOptionalFactory().getOptional(false));
- return Collections.singletonList(memState);
- }
+ break;
+ case "filter":
+ case "flatMap":
+ case "ifPresent":
+ case "map":
+ case "or":
+ case "orElseGet":
+ case "transform":
+ for (DfaMemoryState closure : closures) {
+ closure.applyIsPresentCheck(!methodName.startsWith("or"), qualifier);
+ }
+ memState.push(getMethodResultValue(instruction, qualifier, runner.getFactory()));
+ break;
+ default:
+ memState.push(getMethodResultValue(instruction, qualifier, runner.getFactory()));
+ break;
}
- return Collections.emptyList();
+ return Collections.singletonList(memState);
}
@Nullable
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValue.java
index c78bfb149d6a..61e95a85876d 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValue.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInspection.dataFlow.value;
-public class DfaValue {
+public abstract class DfaValue {
private final int myID;
protected final DfaValueFactory myFactory;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleExportsPackageToItselfInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleExportsPackageToItselfInspection.java
index 0f21c0896fe2..e8629149d6d4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleExportsPackageToItselfInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleExportsPackageToItselfInspection.java
@@ -55,7 +55,7 @@ public class Java9ModuleExportsPackageToItselfInspection extends BaseJavaLocalIn
super.visitExportsStatement(statement);
PsiJavaModule javaModule = PsiTreeUtil.getParentOfType(statement, PsiJavaModule.class);
if (javaModule != null) {
- String moduleName = javaModule.getModuleName();
+ String moduleName = javaModule.getName();
List referenceElements = ContainerUtil.newArrayList(statement.getModuleReferences());
for (PsiJavaModuleReferenceElement referenceElement : referenceElements) {
if (moduleName.equals(referenceElement.getReferenceText())) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9RedundantRequiresStatementInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9RedundantRequiresStatementInspection.java
index 4b986c7651ef..c758ca7427f4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9RedundantRequiresStatementInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9RedundantRequiresStatementInspection.java
@@ -173,7 +173,7 @@ public class Java9RedundantRequiresStatementInspection extends GlobalJavaBatchIn
return StreamEx.of(transitiveModules)
.filter(transitiveModule -> isReexported(currentModule, transitiveModule))
- .map(transitiveModule -> transitiveModule.getModuleName())
+ .map(transitiveModule -> transitiveModule.getName())
.toSet();
}
@@ -204,7 +204,7 @@ public class Java9RedundantRequiresStatementInspection extends GlobalJavaBatchIn
PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(currentModule.getProject()).getParserFacade();
for (String dependencyName : reexportedDependencies) {
PsiJavaModule tempModule =
- parserFacade.createModuleFromText("module " + currentModule.getModuleName() + " { requires " + dependencyName + "; }");
+ parserFacade.createModuleFromText("module " + currentModule.getName() + " { requires " + dependencyName + "; }");
Iterable tempModuleRequires = tempModule.getRequires();
PsiRequiresStatement requiresStatement = tempModuleRequires.iterator().next();
currentModule.addAfter(requiresStatement, addingPlace);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
index 25c23a6daf54..7ce412404b56 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
@@ -37,7 +37,7 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
private List myRequiredModules;
public RefJavaModuleImpl(@NotNull PsiJavaModule javaModule, @NotNull RefManagerImpl manager) {
- super(javaModule.getModuleName(), javaModule, manager);
+ super(javaModule.getName(), javaModule, manager);
myRefModule = manager.getRefModule(ModuleUtilCore.findModuleForPsiElement(javaModule));
}
@@ -91,7 +91,7 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
PsiJavaModule requiredModule = (PsiJavaModule)element;
Map> packagesExportedByModule = getPackagesExportedByModule(requiredModule);
if (myRequiredModules == null) myRequiredModules = new ArrayList<>(1);
- myRequiredModules.add(new RequiredModule(requiredModule.getModuleName(), packagesExportedByModule, statement.isPublic()));
+ myRequiredModules.add(new RequiredModule(requiredModule.getName(), packagesExportedByModule, statement.isPublic()));
}
}
}
@@ -110,7 +110,7 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
if (packageName != null && moduleElement instanceof PsiJavaModule) {
List toModuleNames = myExportedPackageNames.get(packageName);
if (toModuleNames == emptyList) myExportedPackageNames.put(packageName, toModuleNames = new ArrayList<>(1));
- toModuleNames.add(((PsiJavaModule)moduleElement).getModuleName());
+ toModuleNames.add(((PsiJavaModule)moduleElement).getName());
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java
index 4a216a3923c0..363bd2030287 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java
@@ -92,7 +92,7 @@ class JavaModuleCompletion {
if (!(statement instanceof PsiJavaModule)) {
PsiElement host = statement.getParent();
if (host instanceof PsiJavaModule) {
- String hostName = ((PsiJavaModule)host).getModuleName();
+ String hostName = ((PsiJavaModule)host).getName();
Project project = context.getProject();
JavaModuleNameIndex index = JavaModuleNameIndex.getInstance();
GlobalSearchScope scope = ProjectScope.getAllScope(project);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
index fc25b0cd595b..580244b0b882 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
@@ -324,7 +324,7 @@ public class MarkerType {
return null;
}
- Comparator comparator = PsiClassListCellRenderer.INSTANCE.getComparator();
+ Comparator comparator = new PsiClassListCellRenderer().getComparator();
Arrays.sort(subclasses, comparator);
String start = DaemonBundle.message(aClass.isInterface() ? "interface.is.implemented.by.header" : "class.is.subclassed.by.header");
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
index e9eb75590573..65599ebc2921 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
@@ -125,7 +125,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
final Project project = firstClass.getProject();
final JList list = new JBList(classes);
- PsiElementListCellRenderer renderer = PsiClassListCellRenderer.INSTANCE;
+ PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(renderer);
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java
index 291d07a00a48..3e64d4761f28 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java
@@ -109,7 +109,7 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
final Project project = classes[0].getProject();
final JList list = new JBList(classes);
- PsiElementListCellRenderer renderer = PsiClassListCellRenderer.INSTANCE;
+ PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(renderer);
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java
index dbfb5d678fc6..4aa4d023d1e4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java
@@ -99,7 +99,7 @@ public class PullAsAbstractUpFix extends LocalQuickFixAndIntentionActionOnPsiEle
pullUp(method, containingClass, classesToPullUp.iterator().next());
}
else if (editor != null) {
- NavigationUtil.getPsiElementPopup(classesToPullUp.toArray(new PsiClass[classesToPullUp.size()]), PsiClassListCellRenderer.INSTANCE,
+ NavigationUtil.getPsiElementPopup(classesToPullUp.toArray(new PsiClass[classesToPullUp.size()]), new PsiClassListCellRenderer(),
"Choose super class",
new PsiElementProcessor() {
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java
index 5bba2cdf80bf..419414d442fa 100644
--- a/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java
+++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java
@@ -44,6 +44,6 @@ public abstract class ChooseClassAndDoHighlightRunnable extends ChooseOneOrAllRu
@Override
protected PsiElementListCellRenderer createRenderer() {
- return PsiClassListCellRenderer.INSTANCE;
+ return new PsiClassListCellRenderer();
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java
index a7c8780f95f3..0385c79a4313 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java
@@ -28,6 +28,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -62,7 +63,7 @@ public class ShowSiblingsAction extends ShowImplementationsAction {
final boolean isMethod = superElements[0] instanceof PsiMethod;
NavigatablePsiElement[] navigatablePsiElements = ContainerUtil.findAllAsArray(superElements, NavigatablePsiElement.class);
final JBPopup popup = PsiElementListNavigator.navigateOrCreatePopup(navigatablePsiElements, "Choose super " + (isMethod ? "method" : "class or interface"), "Super " + (isMethod ? "methods" : "classes/interfaces"),
- isMethod ? new MethodCellRenderer(false) : PsiClassListCellRenderer.INSTANCE, null,
+ isMethod ? new MethodCellRenderer(false) : new PsiClassListCellRenderer(), null,
objects -> showSiblings(invokedByShortcut, project, editor, file, editor != null, (PsiElement)objects[0]));
if (popup != null) {
if (editor != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java
index 46851f0fc1a5..960db5832fc4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java
@@ -178,9 +178,10 @@ public class ImplementAbstractMethodHandler {
}
private static class MyPsiElementListCellRenderer extends PsiElementListCellRenderer {
+ private final PsiClassListCellRenderer myRenderer = new PsiClassListCellRenderer();
void sort(PsiElement[] result) {
- final Comparator comparator = PsiClassListCellRenderer.INSTANCE.getComparator();
+ final Comparator comparator = myRenderer.getComparator();
Arrays.sort(result, (o1, o2) -> {
if (o1 instanceof PsiEnumConstant && o2 instanceof PsiEnumConstant) {
return ((PsiEnumConstant)o1).getName().compareTo(((PsiEnumConstant)o2).getName());
@@ -193,7 +194,7 @@ public class ImplementAbstractMethodHandler {
@Override
public String getElementText(PsiElement element) {
- return element instanceof PsiClass ? PsiClassListCellRenderer.INSTANCE.getElementText((PsiClass)element)
+ return element instanceof PsiClass ? myRenderer.getElementText((PsiClass)element)
: ((PsiEnumConstant)element).getName();
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
index 2f65188e2b87..1442af2ce1b5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
+++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -729,7 +729,7 @@ public class JavaDocInfoGenerator {
private void generateModuleJavaDoc(StringBuilder buffer, PsiJavaModule module, boolean generatePrologueAndEpilogue) {
if (generatePrologueAndEpilogue) generatePrologue(buffer);
- buffer.append("
module ").append(module.getModuleName()).append("
");
+ buffer.append("
module ").append(module.getName()).append("
");
PsiDocComment comment = module.getDocComment();
if (comment != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoTargetRendererProvider.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoTargetRendererProvider.java
index 8b133fe38d85..6bf0a7fe4172 100644
--- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoTargetRendererProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoTargetRendererProvider.java
@@ -35,7 +35,7 @@ public class JavaGotoTargetRendererProvider implements GotoTargetRendererProvide
return new MethodCellRenderer(gotoData.hasDifferentNames());
}
else if (element instanceof PsiClass) {
- return PsiClassListCellRenderer.INSTANCE;
+ return new PsiClassListCellRenderer();
}
else if (element instanceof PsiFunctionalExpression) {
return new PsiClassOrFunctionalExpressionListCellRenderer();
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
index 901d43106b8a..8a102e458e5a 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
@@ -76,6 +76,7 @@ public class DataFlowInspection extends DataFlowInspectionBase {
private final JCheckBox myTreatUnknownMembersAsNullable;
private final JCheckBox myReportNullArguments;
private final JCheckBox myReportNullableMethodsReturningNotNull;
+ private final JCheckBox myReportUncheckedOptionals;
private OptionsPanel() {
super(new GridBagLayout());
@@ -151,6 +152,15 @@ public class DataFlowInspection extends DataFlowInspectionBase {
}
});
+ myReportUncheckedOptionals = new JCheckBox("Report Optional.get() calls without previous isPresent check");
+ myReportUncheckedOptionals.setSelected(REPORT_UNCHECKED_OPTIONALS);
+ myReportUncheckedOptionals.getModel().addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ REPORT_UNCHECKED_OPTIONALS = myReportUncheckedOptionals.isSelected();
+ }
+ });
+
gc.insets = JBUI.emptyInsets();
gc.gridy = 0;
add(mySuggestNullables, gc);
@@ -182,6 +192,9 @@ public class DataFlowInspection extends DataFlowInspectionBase {
gc.gridy++;
add(myReportNullableMethodsReturningNotNull, gc);
+
+ gc.gridy++;
+ add(myReportUncheckedOptionals, gc);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintAnnotator.kt b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintAnnotator.kt
index 066db18f3ad7..8c534ddaef10 100644
--- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintAnnotator.kt
+++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintAnnotator.kt
@@ -38,7 +38,6 @@ import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.pom.java.LanguageLevel
-import com.intellij.profile.codeInspection.InspectionProjectProfileManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiJavaFile
@@ -47,15 +46,17 @@ import com.intellij.psi.util.PsiTreeUtil
import com.sun.tools.doclint.DocLint
import java.io.File
-class JavadocHtmlLintAnnotator(private val manual: Boolean = false) :
+class JavadocHtmlLintAnnotator() :
ExternalAnnotator() {
data class Info(val file: PsiFile)
data class Anno(val row: Int, val col: Int, val error: Boolean, val message: String)
data class Result(val annotations: List)
+ override fun getPairedBatchInspectionShortName() = JavadocHtmlLintInspection.SHORT_NAME
+
override fun collectInformation(file: PsiFile): Info? =
- if (isJava8SourceFile(file) && "/**" in file.text && isToolEnabled(file)) Info(file) else null
+ if (isJava8SourceFile(file) && "/**" in file.text) Info(file) else null
override fun doAnnotate(collectedInfo: Info): Result? {
val file = collectedInfo.file.virtualFile!!
@@ -122,9 +123,6 @@ class JavadocHtmlLintAnnotator(private val manual: Boolean = false) :
file is PsiJavaFile && file.languageLevel.isAtLeast(LanguageLevel.JDK_1_8) &&
file.virtualFile != null && ProjectFileIndex.SERVICE.getInstance(file.project).isInSourceContent(file.virtualFile)
- private fun isToolEnabled(file: PsiFile) =
- manual || InspectionProjectProfileManager.getInstance(file.project).currentProfile.isToolEnabled(key.value, file)
-
private fun createTempFile(bytes: ByteArray): File {
val tempFile = FileUtil.createTempFile(File(PathManager.getTempPath()), "javadocHtmlLint", ".java")
tempFile.writeBytes(bytes)
diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintInspection.kt b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintInspection.kt
index 4663c136a8f1..a174ec94b592 100644
--- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintInspection.kt
+++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocHtmlLintInspection.kt
@@ -15,23 +15,15 @@
*/
package com.intellij.codeInspection.javaDoc
-import com.intellij.codeInspection.ExternalAnnotatorInspectionVisitor
import com.intellij.codeInspection.LocalInspectionTool
-import com.intellij.codeInspection.ProblemsHolder
import com.intellij.codeInspection.SuppressQuickFix
-import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool
+import com.intellij.codeInspection.ex.ExternalAnnotatorBatchInspection
import com.intellij.psi.PsiElement
-class JavadocHtmlLintInspection : LocalInspectionTool(), PairedUnfairLocalInspectionTool {
+class JavadocHtmlLintInspection : LocalInspectionTool(), ExternalAnnotatorBatchInspection {
companion object {
val SHORT_NAME = "JavadocHtmlLint"
}
- private val annotator = lazy { JavadocHtmlLintAnnotator(true) }
-
- override fun buildVisitor(holder: ProblemsHolder, onTheFly: Boolean) = ExternalAnnotatorInspectionVisitor(holder, annotator.value, onTheFly)
-
override fun getBatchSuppressActions(element: PsiElement?) = SuppressQuickFix.EMPTY_ARRAY
-
- override fun getInspectionForBatchShortName() = SHORT_NAME
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/TerminalBlock.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/TerminalBlock.java
index 546d95a8795e..326102070a43 100644
--- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/TerminalBlock.java
+++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/TerminalBlock.java
@@ -59,7 +59,8 @@ class TerminalBlock {
if(statements.length == 1 && statements[0] instanceof PsiBlockStatement) {
statements = ((PsiBlockStatement)statements[0]).getCodeBlock().getStatements();
} else if(statements.length == 1 && statements[0] instanceof PsiLabeledStatement) {
- statements = new PsiStatement[] {((PsiLabeledStatement)statements[0]).getStatement()};
+ PsiStatement statement = ((PsiLabeledStatement)statements[0]).getStatement();
+ statements = statement == null ? PsiStatement.EMPTY_ARRAY : new PsiStatement[] {statement};
} else break;
}
myStatements = statements;
diff --git a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
index d0e9d102cbd1..ffff324f2850 100644
--- a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
+++ b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
}
if (element instanceof PsiJavaModule) {
- return ((PsiJavaModule)element).getModuleName();
+ return ((PsiJavaModule)element).getName();
}
if (element instanceof PsiJavaModuleReferenceElement) {
@@ -74,7 +74,7 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
if (reference != null) {
PsiElement target = reference.resolve();
if (target instanceof PsiJavaModule) {
- return ((PsiJavaModule)target).getModuleName();
+ return ((PsiJavaModule)target).getName();
}
}
}
diff --git a/java/java-impl/src/com/intellij/ide/util/MethodCellRenderer.java b/java/java-impl/src/com/intellij/ide/util/MethodCellRenderer.java
index 10a140bec5a4..72fcbda6979c 100644
--- a/java/java-impl/src/com/intellij/ide/util/MethodCellRenderer.java
+++ b/java/java-impl/src/com/intellij/ide/util/MethodCellRenderer.java
@@ -23,6 +23,7 @@ import javax.swing.*;
public class MethodCellRenderer extends PsiElementListCellRenderer{
private final boolean myShowMethodNames;
+ private final PsiClassListCellRenderer myClassListCellRenderer = new PsiClassListCellRenderer();
@PsiFormatUtil.FormatMethodOptions
private final int myOptions;
@@ -36,7 +37,7 @@ public class MethodCellRenderer extends PsiElementListCellRenderer{
public String getElementText(PsiMethod element) {
final PsiNamedElement container = fetchContainer(element);
- String text = container instanceof PsiClass ? PsiClassListCellRenderer.INSTANCE.getElementText((PsiClass)container) : container.getName();
+ String text = container instanceof PsiClass ? myClassListCellRenderer.getElementText((PsiClass)container) : container.getName();
if (myShowMethodNames) {
text += "."+PsiFormatUtil.formatMethod(element, PsiSubstitutor.EMPTY, myOptions, PsiFormatUtilBase.SHOW_TYPE);
}
@@ -57,6 +58,6 @@ public class MethodCellRenderer extends PsiElementListCellRenderer{
}
public int getIconFlags() {
- return PsiClassListCellRenderer.INSTANCE.getIconFlags();
+ return myClassListCellRenderer.getIconFlags();
}
}
diff --git a/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java b/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java
index 6b298e6c04a0..4c4020a6c33f 100644
--- a/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java
+++ b/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java
@@ -26,6 +26,7 @@ import com.intellij.psi.util.PsiFormatUtilBase;
import javax.swing.*;
public class MethodOrFunctionalExpressionCellRenderer extends PsiElementListCellRenderer {
+ private final PsiClassListCellRenderer myClassListCellRenderer = new PsiClassListCellRenderer();
private final MethodCellRenderer myMethodCellRenderer;
public MethodOrFunctionalExpressionCellRenderer(boolean showMethodNames) {
@@ -50,6 +51,6 @@ public class MethodOrFunctionalExpressionCellRenderer extends PsiElementListCell
}
public int getIconFlags() {
- return PsiClassListCellRenderer.INSTANCE.getIconFlags();
+ return myClassListCellRenderer.getIconFlags();
}
}
diff --git a/java/java-impl/src/com/intellij/ide/util/PsiClassListCellRenderer.java b/java/java-impl/src/com/intellij/ide/util/PsiClassListCellRenderer.java
index 76260aefe4f6..22fb5eda7daa 100644
--- a/java/java-impl/src/com/intellij/ide/util/PsiClassListCellRenderer.java
+++ b/java/java-impl/src/com/intellij/ide/util/PsiClassListCellRenderer.java
@@ -20,6 +20,10 @@ import com.intellij.psi.presentation.java.ClassPresentationUtil;
import org.jetbrains.annotations.Nullable;
public class PsiClassListCellRenderer extends PsiElementListCellRenderer {
+ /**
+ * Should not be used, as it can result in memory leaks
+ */
+ @Deprecated
public static final PsiClassListCellRenderer INSTANCE = new PsiClassListCellRenderer();
@Override
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
index ab4061cef53e..73baaf5f8fbd 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
@@ -384,7 +384,7 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement
VirtualFile file = PsiImplUtil.getModuleVirtualFile(module);
generateOrderEntryInfo(sb, file, module.getProject());
- sb.append(LangBundle.message("java.terms.module")).append(' ').append(module.getModuleName());
+ sb.append(LangBundle.message("java.terms.module")).append(' ').append(module.getName());
return sb.toString();
}
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
index 84951dce2bcd..933b5ad5369d 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -194,7 +194,7 @@ public class JavaFindUsagesProvider implements FindUsagesProvider {
return element.getText();
}
if (element instanceof PsiJavaModule) {
- return ((PsiJavaModule)element).getModuleName();
+ return ((PsiJavaModule)element).getName();
}
return "";
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
index f5c39ee75d24..588aff781120 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
@@ -1529,7 +1529,7 @@ public class ExtractMethodProcessor implements MatchProvider {
if (classes.size() > 1) {
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes.keySet(), psiClasses[0]);
- NavigationUtil.getPsiElementPopup(psiClasses, PsiClassListCellRenderer.INSTANCE, "Choose Destination Class", processor, preselection)
+ NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose Destination Class", processor, preselection)
.showInBestPositionFor(myEditor);
return true;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
index e2dcd2fddfee..a9d2f934cab9 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
@@ -134,7 +134,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
else if (!classes.isEmpty()){
PsiClass selection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, myParentClass);
- NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), PsiClassListCellRenderer.INSTANCE,
+ NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(),
"Choose class to introduce " + (myIsConstant ? "constant" : "field"),
new PsiElementProcessor() {
@Override
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
index d40e6681a2e0..dac9b3a81954 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
@@ -94,7 +94,7 @@ public abstract class LocalToFieldHandler {
final boolean isStatic = tempIsStatic;
final PsiClass firstClass = classes.get(0);
final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, firstClass);
- NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), PsiClassListCellRenderer.INSTANCE, "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor() {
+ NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor() {
@Override
public boolean execute(@NotNull PsiClass aClass) {
AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, aClass);
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java
index 8e35192ce418..9cbb79d2cf0d 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java
@@ -586,7 +586,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
final PsiType returnType = emptyMethod.getReturnType();
LOG.assertTrue(returnType != null);
final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
- NavigationUtil.getPsiElementPopup(psiClasses, PsiClassListCellRenderer.INSTANCE, title,
+ NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title,
new PsiElementProcessor() {
@Override
public boolean execute(@NotNull PsiClass psiClass) {
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/GenerateMissedTestsAction.java b/java/java-impl/src/com/intellij/testIntegration/createTest/GenerateMissedTestsAction.java
index 34848382a06c..bad914cb1451 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/GenerateMissedTestsAction.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/GenerateMissedTestsAction.java
@@ -85,7 +85,7 @@ public class GenerateMissedTestsAction extends PsiElementBaseIntentionAction {
}
final JBList list = new JBList(testClasses);
- list.setCellRenderer(PsiClassListCellRenderer.INSTANCE);
+ list.setCellRenderer(new PsiClassListCellRenderer());
JBPopupFactory.getInstance().createListPopupBuilder(list)
.setItemChoosenCallback(() -> generateMissedTests((PsiClass)list.getSelectedValue(), srcClass, editor))
.setTitle("Choose Test")
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
index 67c7ec7ff2f5..56741435f18d 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
@@ -22,14 +22,14 @@ import org.jetbrains.annotations.NotNull;
*
* @since 2016.3
*/
-public interface PsiJavaModule extends NavigatablePsiElement, PsiNamedElement, PsiJavaDocumentedElement {
+public interface PsiJavaModule extends NavigatablePsiElement, PsiNameIdentifierOwner, PsiJavaDocumentedElement {
String MODULE_INFO_CLASS = "module-info";
String MODULE_INFO_FILE = MODULE_INFO_CLASS + ".java";
String MODULE_INFO_CLS_FILE = MODULE_INFO_CLASS + ".class";
String JAVA_BASE = "java.base";
- @NotNull PsiJavaModuleReferenceElement getNameElement();
- @NotNull String getModuleName();
+ @Override @NotNull PsiJavaModuleReferenceElement getNameIdentifier();
+ @Override @NotNull String getName();
@NotNull Iterable getRequires();
@NotNull Iterable getExports();
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiModifier.java b/java/java-psi-api/src/com/intellij/psi/PsiModifier.java
index 4d59a6c9b23d..c0e7a86495a5 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiModifier.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiModifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,27 +16,26 @@
package com.intellij.psi;
import org.intellij.lang.annotations.MagicConstant;
-import org.jetbrains.annotations.NonNls;
/**
* Provides a list of possible modifier keywords for Java classes, methods and fields.
*/
public interface PsiModifier {
- @NonNls String PUBLIC = "public";
- @NonNls String PROTECTED = "protected";
- @NonNls String PRIVATE = "private";
- @NonNls String PACKAGE_LOCAL = "packageLocal";
- @NonNls String STATIC = "static";
- @NonNls String ABSTRACT = "abstract";
- @NonNls String FINAL = "final";
- @NonNls String NATIVE = "native";
- @NonNls String SYNCHRONIZED = "synchronized";
- @NonNls String STRICTFP = "strictfp";
- @NonNls String TRANSIENT = "transient";
- @NonNls String VOLATILE = "volatile";
- @NonNls String DEFAULT = "default";
+ String PUBLIC = "public";
+ String PROTECTED = "protected";
+ String PRIVATE = "private";
+ String PACKAGE_LOCAL = "packageLocal";
+ String STATIC = "static";
+ String ABSTRACT = "abstract";
+ String FINAL = "final";
+ String NATIVE = "native";
+ String SYNCHRONIZED = "synchronized";
+ String STRICTFP = "strictfp";
+ String TRANSIENT = "transient";
+ String VOLATILE = "volatile";
+ String DEFAULT = "default";
- @NonNls String[] MODIFIERS = {
+ String[] MODIFIERS = {
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT
};
@@ -44,4 +43,4 @@ public interface PsiModifier {
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT, PACKAGE_LOCAL
})
@interface ModifierConstant { }
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
index d84025793fc1..569f86691a9c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
+++ b/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
@@ -18,6 +18,7 @@ package com.intellij.psi;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.PackageDirectoryCache;
+import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -52,7 +53,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
private final PsiManager myManager;
private final String[] myFileExtensions;
- public NonClasspathClassFinder(Project project, String... fileExtensions) {
+ public NonClasspathClassFinder(@NotNull Project project, @NotNull String... fileExtensions) {
myProject = project;
myManager = PsiManager.getInstance(myProject);
myFileExtensions = ArrayUtil.append(fileExtensions, "class");
@@ -63,6 +64,12 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
clearCache();
}
});
+ LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ clearCache();
+ }
+ }, project);
}
@NotNull
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/ConstantExpressionVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/ConstantExpressionVisitor.java
index 6b634abca4ef..0cf597853b75 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/ConstantExpressionVisitor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/ConstantExpressionVisitor.java
@@ -483,9 +483,12 @@ class ConstantExpressionVisitor extends JavaElementVisitor implements PsiConstan
else if (tokenType == JavaTokenType.TILDE) {
if (operandValue instanceof Character) operandValue = Integer.valueOf(((Character)operandValue).charValue());
if (isIntegral(operandValue)) {
- value = operandValue instanceof Long
- ? Long.valueOf(~((Number)operandValue).longValue())
- : Integer.valueOf(~((Number)operandValue).intValue());
+ if (operandValue instanceof Long) {
+ value = Long.valueOf(~((Number)operandValue).longValue());
+ }
+ else {
+ value = Integer.valueOf(~((Number)operandValue).intValue());
+ }
}
}
else if (tokenType == JavaTokenType.EXCL) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
index d938d7a2743a..d262db6e0d75 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -370,7 +370,6 @@ public class ClsFileImpl extends ClsRepositoryPsiElement
}
return CachedValuesManager.getCachedValue(this, new CachedValueProvider() {
- @Nullable
@Override
public Result compute() {
PsiElement target = JavaPsiImplementationHelper.getInstance(getProject()).getClsFileNavigationElement(ClsFileImpl.this);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java
index b93b2b03384a..b0d3ade10e88 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java
@@ -41,18 +41,6 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement getRequires() {
@@ -85,7 +73,7 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement getRequires() {
@@ -97,9 +85,16 @@ public class LightJavaModule extends LightElement implements PsiJavaModule {
return Collections.emptyList();
}
+ @NotNull
+ @Override
+ public PsiJavaModuleReferenceElement getNameIdentifier() {
+ return myRefElement;
+ }
+
+ @NotNull
@Override
public String getName() {
- return getModuleName();
+ return myRefElement.getReferenceText();
}
@Override
@@ -125,12 +120,12 @@ public class LightJavaModule extends LightElement implements PsiJavaModule {
@Override
public int hashCode() {
- return getModuleName().hashCode() * 31 + getManager().hashCode();
+ return getName().hashCode() * 31 + getManager().hashCode();
}
@Override
public String toString() {
- return "PsiJavaModule:" + getModuleName();
+ return "PsiJavaModule:" + getName();
}
private static class LightJavaModuleReferenceElement extends LightElement implements PsiJavaModuleReferenceElement {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
index fafc6311bdfe..4f25c9f6ac80 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
@@ -54,24 +54,6 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp
super(node);
}
- @NotNull
- @Override
- public PsiJavaModuleReferenceElement getNameElement() {
- return PsiTreeUtil.getRequiredChildOfType(this, PsiJavaModuleReferenceElement.class);
- }
-
- @NotNull
- @Override
- public String getModuleName() {
- PsiJavaModuleStub stub = getGreenStub();
- if (stub != null) {
- return stub.getName();
- }
- else {
- return getNameElement().getReferenceText();
- }
- }
-
@NotNull
@Override
public Iterable getRequires() {
@@ -120,16 +102,29 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp
return psiTraverser().children(this).filter(PsiProvidesStatement.class);
}
+ @NotNull
+ @Override
+ public PsiJavaModuleReferenceElement getNameIdentifier() {
+ return PsiTreeUtil.getRequiredChildOfType(this, PsiJavaModuleReferenceElement.class);
+ }
+
+ @NotNull
@Override
public String getName() {
- return getModuleName();
+ PsiJavaModuleStub stub = getGreenStub();
+ if (stub != null) {
+ return stub.getName();
+ }
+ else {
+ return getNameIdentifier().getReferenceText();
+ }
}
@Override
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
PsiElementFactory factory = PsiElementFactory.SERVICE.getInstance(getProject());
- PsiJavaModuleReferenceElement newName = factory.createModuleFromText("module " + name + " {}").getNameElement();
- getNameElement().replace(newName);
+ PsiJavaModuleReferenceElement newName = factory.createModuleFromText("module " + name + " {}").getNameIdentifier();
+ getNameIdentifier().replace(newName);
return this;
}
@@ -147,7 +142,7 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp
@NotNull
@Override
public PsiElement getNavigationElement() {
- return getNameElement();
+ return getNameIdentifier();
}
@Override
@@ -162,6 +157,6 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp
@Override
public String toString() {
- return "PsiJavaModule:" + getModuleName();
+ return "PsiJavaModule:" + getName();
}
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
index b8d7772baa70..95d606d4dbef 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly gammaBuilder) {
+ a(Test::c, name -> gammaBuilder);
+ }
+
+
+ private static > void a(final Function f1,
+ final Function f2) {
+
+ }
+
+ private static String c(final Builder extends Beta> builder) {
+ return "";
+ }
+
+ static class Alfa {}
+ private static class Beta extends Alfa {}
+
+ static class Builder {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeIncompleteLabel.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeIncompleteLabel.java
new file mode 100644
index 000000000000..59552d348464
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeIncompleteLabel.java
@@ -0,0 +1,11 @@
+// "Fix all 'Loop can be collapsed with Stream API' problems in file" "false"
+
+import java.util.List;
+
+public class Main {
+ void test(List list) {
+ for(String l : list) {
+ TEST:
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/optional_get_without_is_present/OptionalGetWithoutIsPresent.java b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalGetWithoutIsPresent.java
similarity index 62%
rename from plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/optional_get_without_is_present/OptionalGetWithoutIsPresent.java
rename to java/java-tests/testData/inspection/dataFlow/fixture/OptionalGetWithoutIsPresent.java
index f4f8c2610bc7..b57953ada07b 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/optional_get_without_is_present/OptionalGetWithoutIsPresent.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalGetWithoutIsPresent.java
@@ -13,10 +13,65 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import java.util.Optional;
+import java.util.*;
class OptionalWithoutIsPresent {
+ void testSimple(Optional o, OptionalDouble od, OptionalInt oi, OptionalLong ol) {
+ System.out.println(o.get());
+ System.out.println(oi.getAsInt());
+ System.out.println(ol.getAsLong());
+ System.out.println(od.getAsDouble());
+ }
+
+ {
+ System.out.println(getIntegerOptional().get());
+ }
+
+ void testWhile() {
+ Optional o = Optional.empty();
+ while (!o.isPresent()) {
+ o = Optional.of("");
+ }
+ System.out.println(o.get());
+ }
+
+ void testWhile2() {
+ Optional o = getIntegerOptional();
+ while (o.isPresent()) {
+ System.out.println(o.get());
+ }
+ }
+
+ public void testPolyadicExpression(Optional value) {
+ boolean flag = value.isPresent() && "Yes".equals(value.get());
+ }
+
+ boolean testPolyadicExpression2(Optional o) {
+ return !o.isPresent() || o.get().equals("j");
+ }
+
+ String testPolyadicExpression3() {
+ Optional o = getOptional();
+ if (o == null || !o.isPresent()) {
+ return "";
+ }
+ return o.get();
+ }
+
+ void testNested(Optional opt, String action) {
+ if (!opt.isPresent()) {
+ throw new IllegalArgumentException();
+ }
+ switch (action) {
+ case "case":
+ System.out.println(opt.get());
+ break;
+ default:
+ System.err.println(opt.get());
+ }
+ }
+
void m(Optional maybe) {
if (!!!maybe.isPresent()) {
maybe = getIntegerOptional();
@@ -29,9 +84,9 @@ class OptionalWithoutIsPresent {
maybe = Optional.empty();
System.out.println(maybe.get());
}
- boolean b = ((maybe.isPresent())) && maybe.get() == 1;
- boolean c = (!maybe.isPresent()) || maybe.get() == 1;
- Integer value = !maybe.isPresent() ? 0 : maybe.get();
+ boolean b = ((maybe.isPresent())) && maybe.get() == 1;
+ boolean c = (!maybe.isPresent()) || maybe.get() == 1;
+ Integer value = !maybe.isPresent() ? 0 : maybe.get();
}
Optional getIntegerOptional() {
@@ -42,7 +97,7 @@ class OptionalWithoutIsPresent {
Optional optional = Optional.empty();
final boolean present = optional.isPresent();
// optional = Optional.empty();
- if (present) {
+ if (present) {
final String string = optional.get();
System.out.println(string);
}
@@ -52,7 +107,7 @@ class OptionalWithoutIsPresent {
Optional optional = Optional.empty();
final boolean present = optional.isPresent();
optional = Optional.empty();
- if (present) {
+ if (present) {
final String string = optional.get();
System.out.println(string);
}
@@ -101,7 +156,7 @@ class OptionalWithoutIsPresent {
private void checkAsserts2() {
Optional o3 = Optional.empty();
- org.testng.Assert.assertTrue(o3.isPresent());
+ org.testng.Assert.assertTrue(o3.isPresent());
System.out.println(o3.get());
}
@@ -131,16 +186,16 @@ class OptionalWithoutIsPresent {
private void checkOfNullable(String value) {
System.out.println(Optional.ofNullable(value).get());
- System.out.println(Optional.ofNullable(value+"a").get());
- System.out.println(Optional.ofNullable("xyz").get());
+ System.out.println(Optional.ofNullable(value+"a").get());
+ System.out.println(Optional.ofNullable("xyz").get());
}
public static String demo() {
Optional holder = Optional.empty();
- if (! holder.isPresent()) {
+ if (! holder.isPresent()) {
holder = Optional.of("hello world");
- if (!holder.isPresent()) {
+ if (!holder.isPresent()) {
return null;
}
}
@@ -171,9 +226,10 @@ class OptionalWithoutIsPresent {
return Optional.empty();
}
- //void order(Optional order) {
- // order.ifPresent(o -> System.out.println(order.get()));
- //}
+ void order(Optional order, boolean b) {
+ order.ifPresent(o -> System.out.println(order.get()));
+ System.out.println(order.orElseGet(() -> order.get().trim()));
+ }
public static void two(Optional