mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -34,10 +34,13 @@
|
||||
implementationClass="org.intellij.lang.regexp.inspection.SingleCharAlternationInspection"/>
|
||||
<localInspection groupName="RegExp" language="RegExp" shortName="OctalEscape" displayName="Octal escape" enabledByDefault="false"
|
||||
level="WARNING" implementationClass="org.intellij.lang.regexp.inspection.OctalEscapeInspection"/>
|
||||
<localInspection groupName="RegExp" language="RegExp" shortName="ReDoS" displayName="Exponential backtracking" enabledByDefault="true"
|
||||
level="WARNING" implementationClass="org.intellij.lang.regexp.inspection.ReDoSInspection"/>
|
||||
<!--<localInspection groupName="RegExp" language="RegExp" shortName="ReDoS" displayName="Exponential backtracking" enabledByDefault="true"
|
||||
level="WARNING" implementationClass="org.intellij.lang.regexp.inspection.ReDoSInspection"/>-->
|
||||
<localInspection groupName="RegExp" language="RegExp" shortName="DuplicateAlternationBranch"
|
||||
displayName="Duplicate branch in alternation" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.intellij.lang.regexp.inspection.DuplicateAlternationBranchInspection"/>
|
||||
<localInspection groupName="RegExp" language="RegExp" shortName="EscapedMetaCharacter" displayName="Escaped meta character"
|
||||
enabledByDefault="false" level="WARNING"
|
||||
implementationClass="org.intellij.lang.regexp.inspection.EscapedMetaCharacterInspection"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports the escaped meta characters, e.g. <b><code>\.</code></b>.
|
||||
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 <b><code>\d+\.\d+</code></b> would be written as <code>\d+[.]\d+</code>.
|
||||
This inspection does not warn about the meta character <b><code>[</code></b>, <b><code>]</code></b> and <b><code>^</code></b>,
|
||||
because those would need additional escaping inside a character class.
|
||||
<!-- tooltip end -->
|
||||
<p><small>New in 2017.1</small>
|
||||
</body>
|
||||
</html>
|
||||
+115
@@ -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 <code>" + c + "</code>", 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
@@ -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("<warning descr=\"Escaped meta character '.'\">\\.</warning>", "[.]", "Replace with '[.]'");
|
||||
}
|
||||
|
||||
public void testNoWarn() {
|
||||
highlightTest("\\[\\^\\]");
|
||||
}
|
||||
|
||||
public void testHighlighting() {
|
||||
highlightTest("<warning descr=\"Escaped meta character '{'\">\\{</warning>" +
|
||||
"\\}" + // already has redundant character escape warning
|
||||
"<warning descr=\"Escaped meta character '('\">\\(</warning>" +
|
||||
"<warning descr=\"Escaped meta character ')'\">\\)</warning>" +
|
||||
"<warning descr=\"Escaped meta character '.'\">\\.</warning>" +
|
||||
"<warning descr=\"Escaped meta character '*'\">\\*</warning>" +
|
||||
"<warning descr=\"Escaped meta character '+'\">\\+</warning>" +
|
||||
"<warning descr=\"Escaped meta character '?'\">\\?</warning>" +
|
||||
"<warning descr=\"Escaped meta character '|'\">\\|</warning>" +
|
||||
"<warning descr=\"Escaped meta character '$'\">\\$</warning>");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool getInspection() {
|
||||
return new EscapedMetaCharacterInspection();
|
||||
}
|
||||
}
|
||||
@@ -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<DebuggerCommandImpl> 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<DebuggerComma
|
||||
myDisposed = true;
|
||||
}
|
||||
|
||||
private static void waitForTerminateFutureToComplete(@NotNull Future<?> 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<DebuggerComma
|
||||
* if worker thread is still processing the same command
|
||||
* calls terminateCommand
|
||||
*/
|
||||
public void terminateAndInvoke(DebuggerCommandImpl command, int terminateTimeout) {
|
||||
public void terminateAndInvoke(DebuggerCommandImpl command, int terminateTimeoutMillis) {
|
||||
final DebuggerCommandImpl currentCommand = myEvents.getCurrentEvent();
|
||||
|
||||
invoke(command);
|
||||
|
||||
if (currentCommand != null) {
|
||||
AppExecutorUtil.getAppScheduledExecutorService().schedule(
|
||||
final ScheduledFuture<?> 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<DebuggerComma
|
||||
}
|
||||
}
|
||||
}
|
||||
}, terminateTimeout, TimeUnit.MILLISECONDS);
|
||||
}, terminateTimeoutMillis, TimeUnit.MILLISECONDS);
|
||||
|
||||
// register on project instead of this because it would cause significant delays on each session termination otherwise
|
||||
Disposer.register(myProject, () -> waitForTerminateFutureToComplete(future));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +190,7 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerComma
|
||||
}
|
||||
|
||||
|
||||
public void startLongProcessAndFork(Runnable process) {
|
||||
void startLongProcessAndFork(Runnable process) {
|
||||
assertIsManagerThread();
|
||||
startNewWorkerThread();
|
||||
|
||||
@@ -235,7 +251,7 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerComma
|
||||
|
||||
}
|
||||
|
||||
public void restartIfNeeded () {
|
||||
void restartIfNeeded() {
|
||||
if (myEvents.isClosed()) {
|
||||
myEvents.reopen();
|
||||
startNewWorkerThread();
|
||||
|
||||
+3
-3
@@ -20,18 +20,18 @@ import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.debugger.memory.component.InstancesTracker;
|
||||
|
||||
public class EnableBackgroundTrackingAction extends ToggleAction{
|
||||
public class EnableBackgroundTrackingAction extends ToggleAction {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
return project != null && InstancesTracker.getInstance(project).isBackgroundTrackingEnabled();
|
||||
return project != null && !project.isDisposed() && InstancesTracker.getInstance(project).isBackgroundTrackingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
Project project = e.getProject();
|
||||
if (project != null) {
|
||||
if (project != null && !project.isDisposed()) {
|
||||
InstancesTracker.getInstance(project).setBackgroundTackingEnabled(state);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ public class TrackInstancesToggleAction extends ToggleAction {
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
ReferenceType selectedClass = getSelectedClass(e);
|
||||
final Project project = e.getProject();
|
||||
if (project != null && selectedClass != null) {
|
||||
if (project != null && selectedClass != null && !project.isDisposed()) {
|
||||
InstancesTracker tracker = InstancesTracker.getInstance(project);
|
||||
return tracker.isTracked(selectedClass.name());
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class TrackInstancesToggleAction extends ToggleAction {
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
final ReferenceType selectedClass = getSelectedClass(e);
|
||||
final Project project = e.getProject();
|
||||
if (selectedClass != null && project != null) {
|
||||
if (selectedClass != null && project != null && !project.isDisposed()) {
|
||||
InstancesTracker tracker = InstancesTracker.getInstance(project);
|
||||
boolean isAlreadyTracked = tracker.isTracked(selectedClass.name());
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@State(name = "InstancesTracker", storages = @Storage(StoragePathMacros.WORKSPACE_FILE))
|
||||
public class InstancesTracker extends AbstractProjectComponent
|
||||
implements PersistentStateComponent<InstancesTracker.MyState> {
|
||||
implements PersistentStateComponent<InstancesTracker.MyState> {
|
||||
private final EventDispatcher<InstancesTrackerListener> 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<String, TrackingType> classes = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
+8
-2
@@ -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",
|
||||
|
||||
+4
-4
@@ -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) {
|
||||
|
||||
@@ -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<ReferenceType> 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<ObjectReference> instances = ref.instances(limit);
|
||||
return instances == null ? Collections.emptyList() : instances;
|
||||
}, ref.name()).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ReferenceType> 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);
|
||||
|
||||
+24
-18
@@ -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();
|
||||
|
||||
@@ -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<CapturePoint> 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;
|
||||
|
||||
+1
-1
@@ -298,7 +298,7 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunCo
|
||||
if (mainClass != null) {
|
||||
PsiJavaModule mainModule = JavaModuleGraphUtil.findDescriptorByElement(mainClass);
|
||||
if (mainModule != null) {
|
||||
params.setModuleName(mainModule.getModuleName());
|
||||
params.setModuleName(mainModule.getName());
|
||||
PathsList classPath = params.getClassPath(), modulePath = params.getModulePath();
|
||||
modulePath.addAll(classPath.getPathList());
|
||||
classPath.clear();
|
||||
|
||||
@@ -128,7 +128,7 @@ public class JavaModuleInsight extends ModuleInsight {
|
||||
if (javaModule == null) {
|
||||
throw new IncorrectOperationException("Incorrect module declaration '" + file.getPath() + "'");
|
||||
}
|
||||
ModuleInfo info = new ModuleInfo(javaModule.getModuleName());
|
||||
ModuleInfo info = new ModuleInfo(javaModule.getName());
|
||||
javaModule.accept(new ModuleInfoVisitor(info));
|
||||
return info;
|
||||
});
|
||||
|
||||
+3
-2
@@ -429,11 +429,12 @@ public class HighlightMethodUtil {
|
||||
else {
|
||||
PsiReferenceExpression methodExpression = methodCall.getMethodExpression();
|
||||
PsiReferenceParameterList typeArgumentList = methodCall.getTypeArgumentList();
|
||||
PsiSubstitutor applicabilitySubstitutor = candidateInfo.getSubstitutor(false);
|
||||
if (typeArgumentList.getTypeArguments().length == 0 && resolvedMethod.hasTypeParameters()) {
|
||||
highlightInfo = GenericsHighlightUtil.checkInferredTypeArguments(resolvedMethod, methodCall, substitutor);
|
||||
highlightInfo = GenericsHighlightUtil.checkInferredTypeArguments(resolvedMethod, methodCall, applicabilitySubstitutor);
|
||||
}
|
||||
else {
|
||||
highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, substitutor, javaSdkVersion);
|
||||
highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, applicabilitySubstitutor, javaSdkVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -66,7 +66,7 @@ public class JavaModuleGraphUtil {
|
||||
Map<String, Set<String>> exports = CachedValuesManager.getCachedValue(source, () ->
|
||||
Result.create(exportsMap(source), source.getContainingFile()));
|
||||
Set<String> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -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<PsiJavaModule> cycle = JavaModuleGraphUtil.findCycle((PsiJavaModule)target);
|
||||
if (cycle != null && cycle.contains(container)) {
|
||||
Stream<String> stream = cycle.stream().map(PsiJavaModule::getModuleName);
|
||||
Stream<String> 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) {
|
||||
|
||||
+3
-4
@@ -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<PsiRequiresStatement> 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;
|
||||
|
||||
+67
-5
@@ -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<PsiMethodCallExpression, ThreeState> calls,
|
||||
List<PsiExpression> qualifiers) {
|
||||
for (Map.Entry<PsiMethodCallExpression, ThreeState> 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<Pair<NullabilityProblem, PsiElement>, StateInfo> myStateInfos = ContainerUtil.newHashMap();
|
||||
private final Set<Instruction> myCCEInstructions = ContainerUtil.newHashSet();
|
||||
private final Map<MethodCallInstruction, Boolean> myFailingCalls = new HashMap<>();
|
||||
private final Map<PsiMethodCallExpression, ThreeState> myOptionalCalls = new HashMap<>();
|
||||
private final List<PsiExpression> myOptionalQualifiers = new ArrayList<>();
|
||||
private boolean myAlwaysReturnsNotNull = true;
|
||||
|
||||
@Override
|
||||
@@ -912,6 +948,14 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
});
|
||||
}
|
||||
|
||||
Map<PsiMethodCallExpression, ThreeState> getOptionalCalls() {
|
||||
return myOptionalCalls;
|
||||
}
|
||||
|
||||
List<PsiExpression> getOptionalQualifiers() {
|
||||
return myOptionalQualifiers;
|
||||
}
|
||||
|
||||
Collection<PsiCall> 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<MethodContract> contracts = instruction.getContracts();
|
||||
return !contracts.isEmpty() && contracts.stream().allMatch(DataFlowInstructionVisitor::isNonTrivialFailingContract);
|
||||
|
||||
+5
-18
@@ -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<DfaVariableValue> vars = new HashSet<>(copy.getVariableStates().keySet());
|
||||
for (DfaVariableValue value : vars) {
|
||||
copy.flushDependencies(value);
|
||||
}
|
||||
copy.emptyStack();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -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);
|
||||
|
||||
+24
-1
@@ -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<int[]> myIdToEqClassesIndices;
|
||||
private final Stack<DfaValue> myStack;
|
||||
// Closures which correspond to the stack top (do not track other closures for now)
|
||||
private final List<DfaMemoryState> myStackTopClosures = new ArrayList<>();
|
||||
private final TLongHashSet myDistinctClasses;
|
||||
private final LinkedHashMap<DfaVariableValue,DfaVariableState> myVariableStates;
|
||||
private final Map<DfaVariableValue,DfaVariableState> 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<DfaVariableValue> vars = new HashSet<>(copy.getVariableStates().keySet());
|
||||
for (DfaVariableValue value : vars) {
|
||||
copy.flushDependencies(value);
|
||||
}
|
||||
copy.emptyStack();
|
||||
myStackTopClosures.add(copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
List<DfaMemoryState> 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;
|
||||
}
|
||||
});
|
||||
|
||||
+50
-38
@@ -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<String> 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<BinopInstruction> 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<DfaMemoryState> 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<DfaMemoryState> 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<DfaMemoryState> handleOptionalMethods(MethodCallInstruction instruction,
|
||||
DataFlowRunner runner,
|
||||
DfaMemoryState memState,
|
||||
DfaValue qualifierValue, @Nullable DfaValue[] argValues) {
|
||||
private List<DfaMemoryState> 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<DfaMemoryState> 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
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
|
||||
+1
-1
@@ -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<PsiJavaModuleReferenceElement> referenceElements = ContainerUtil.newArrayList(statement.getModuleReferences());
|
||||
for (PsiJavaModuleReferenceElement referenceElement : referenceElements) {
|
||||
if (moduleName.equals(referenceElement.getReferenceText())) {
|
||||
|
||||
+2
-2
@@ -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<PsiRequiresStatement> tempModuleRequires = tempModule.getRequires();
|
||||
PsiRequiresStatement requiresStatement = tempModuleRequires.iterator().next();
|
||||
currentModule.addAfter(requiresStatement, addingPlace);
|
||||
|
||||
+3
-3
@@ -37,7 +37,7 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
|
||||
private List<RequiredModule> 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<String, List<String>> 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<String> toModuleNames = myExportedPackageNames.get(packageName);
|
||||
if (toModuleNames == emptyList) myExportedPackageNames.put(packageName, toModuleNames = new ArrayList<>(1));
|
||||
toModuleNames.add(((PsiJavaModule)moduleElement).getModuleName());
|
||||
toModuleNames.add(((PsiJavaModule)moduleElement).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -324,7 +324,7 @@ public class MarkerType {
|
||||
return null;
|
||||
}
|
||||
|
||||
Comparator<PsiClass> comparator = PsiClassListCellRenderer.INSTANCE.getComparator();
|
||||
Comparator<PsiClass> comparator = new PsiClassListCellRenderer().getComparator();
|
||||
Arrays.sort(subclasses, comparator);
|
||||
|
||||
String start = DaemonBundle.message(aClass.isInterface() ? "interface.is.implemented.by.header" : "class.is.subclassed.by.header");
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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<PsiClass>() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -44,6 +44,6 @@ public abstract class ChooseClassAndDoHighlightRunnable extends ChooseOneOrAllRu
|
||||
|
||||
@Override
|
||||
protected PsiElementListCellRenderer<PsiClass> createRenderer() {
|
||||
return PsiClassListCellRenderer.INSTANCE;
|
||||
return new PsiClassListCellRenderer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+3
-2
@@ -178,9 +178,10 @@ public class ImplementAbstractMethodHandler {
|
||||
}
|
||||
|
||||
private static class MyPsiElementListCellRenderer extends PsiElementListCellRenderer<PsiElement> {
|
||||
private final PsiClassListCellRenderer myRenderer = new PsiClassListCellRenderer();
|
||||
|
||||
void sort(PsiElement[] result) {
|
||||
final Comparator<PsiClass> comparator = PsiClassListCellRenderer.INSTANCE.getComparator();
|
||||
final Comparator<PsiClass> 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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("<pre>module <b>").append(module.getModuleName()).append("</b></pre>");
|
||||
buffer.append("<pre>module <b>").append(module.getName()).append("</b></pre>");
|
||||
|
||||
PsiDocComment comment = module.getDocComment();
|
||||
if (comment != null) {
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<JavadocHtmlLintAnnotator.Info, JavadocHtmlLintAnnotator.Result>() {
|
||||
|
||||
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<Anno>)
|
||||
|
||||
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)
|
||||
|
||||
+2
-10
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.swing.*;
|
||||
|
||||
public class MethodCellRenderer extends PsiElementListCellRenderer<PsiMethod>{
|
||||
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<PsiMethod>{
|
||||
|
||||
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<PsiMethod>{
|
||||
}
|
||||
|
||||
public int getIconFlags() {
|
||||
return PsiClassListCellRenderer.INSTANCE.getIconFlags();
|
||||
return myClassListCellRenderer.getIconFlags();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import javax.swing.*;
|
||||
|
||||
public class MethodOrFunctionalExpressionCellRenderer extends PsiElementListCellRenderer<NavigatablePsiElement> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiClassListCellRenderer extends PsiElementListCellRenderer<PsiClass> {
|
||||
/**
|
||||
* Should not be used, as it can result in memory leaks
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PsiClassListCellRenderer INSTANCE = new PsiClassListCellRenderer();
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 "";
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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<PsiClass>() {
|
||||
@Override
|
||||
|
||||
@@ -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<PsiClass>() {
|
||||
NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass aClass) {
|
||||
AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, aClass);
|
||||
|
||||
+1
-1
@@ -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<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass psiClass) {
|
||||
|
||||
+1
-1
@@ -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")
|
||||
|
||||
@@ -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<PsiRequiresStatement> getRequires();
|
||||
@NotNull Iterable<PsiPackageAccessibilityStatement> getExports();
|
||||
|
||||
@@ -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 { }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<PsiClassHolderFileStub>
|
||||
}
|
||||
|
||||
return CachedValuesManager.getCachedValue(this, new CachedValueProvider<PsiElement>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<PsiElement> compute() {
|
||||
PsiElement target = JavaPsiImplementationHelper.getInstance(getProject()).getClsFileNavigationElement(ClsFileImpl.this);
|
||||
|
||||
@@ -41,18 +41,6 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
myReference = new ClsJavaModuleReferenceElementImpl(this, stub.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaModuleReferenceElement getNameElement() {
|
||||
return myReference;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return myReference.getReferenceText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<PsiRequiresStatement> getRequires() {
|
||||
@@ -85,7 +73,7 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
|
||||
@Override
|
||||
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
|
||||
buffer.append("module ").append(getModuleName()).append(" {\n");
|
||||
buffer.append("module ").append(getName()).append(" {\n");
|
||||
|
||||
int newIndentLevel = indentLevel + getIndentSize();
|
||||
|
||||
@@ -106,7 +94,7 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
PsiJavaModule mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
|
||||
|
||||
setMirrorCheckingType(element, JavaElementType.MODULE);
|
||||
setMirror(getNameElement(), mirror.getNameElement());
|
||||
setMirror(getNameIdentifier(), mirror.getNameIdentifier());
|
||||
|
||||
setMirrors(newArrayList(getStub().getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)),
|
||||
newArrayList(mirror.getRequires()));
|
||||
@@ -115,9 +103,16 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
newArrayList(mirror.getExports()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaModuleReferenceElement getNameIdentifier() {
|
||||
return myReference;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getModuleName();
|
||||
return myReference.getReferenceText();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +134,7 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return getNameElement();
|
||||
return getNameIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,6 +149,6 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiJavaModule:" + getModuleName();
|
||||
return "PsiJavaModule:" + getName();
|
||||
}
|
||||
}
|
||||
@@ -55,18 +55,6 @@ public class LightJavaModule extends LightElement implements PsiJavaModule {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaModuleReferenceElement getNameElement() {
|
||||
return myRefElement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return myRefElement.getReferenceText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<PsiRequiresStatement> 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 {
|
||||
|
||||
@@ -54,24 +54,6 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> 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<PsiRequiresStatement> getRequires() {
|
||||
@@ -120,16 +102,29 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> 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<PsiJavaModuleStub> imp
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return getNameElement();
|
||||
return getNameIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,6 +157,6 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> imp
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiJavaModule:" + getModuleName();
|
||||
return "PsiJavaModule:" + getName();
|
||||
}
|
||||
}
|
||||
@@ -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<PsiJavaModuleR
|
||||
throw new IncorrectOperationException(JavaCoreBundle.message("psi.error.attempt.to.edit.class.file", element.getContainingFile()));
|
||||
}
|
||||
PsiElementFactory factory = PsiElementFactory.SERVICE.getInstance(element.getProject());
|
||||
PsiJavaModuleReferenceElement newElement = factory.createModuleFromText("module " + newName + " {}").getNameElement();
|
||||
PsiJavaModuleReferenceElement newElement = factory.createModuleFromText("module " + newName + " {}").getNameIdentifier();
|
||||
return element.replace(newElement);
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -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.
|
||||
@@ -36,10 +36,9 @@ public class JavaModulePresentationProvider implements ItemPresentationProvider<
|
||||
@Override
|
||||
public ItemPresentation getPresentation(@NotNull final PsiJavaModule item) {
|
||||
return new ItemPresentation() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return item.getModuleName();
|
||||
return item.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
class Test {
|
||||
|
||||
public static void main(Builder<Beta> gammaBuilder) {
|
||||
<error descr="Inferred type 'B' for type parameter 'B' is not within its bound; should extend 'Test.Builder<Test.Alfa>'">a(Test::c, name -> gammaBuilder)</error>;
|
||||
}
|
||||
|
||||
|
||||
private static <T extends Alfa, B extends Builder<T>> void a(final Function<B, String> f1,
|
||||
final Function<String, B> f2) {
|
||||
|
||||
}
|
||||
|
||||
private static String c(final Builder<? extends Beta> builder) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static class Alfa {}
|
||||
private static class Beta extends Alfa {}
|
||||
|
||||
static class Builder<T> {}
|
||||
}
|
||||
+11
@@ -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<String> list) {
|
||||
for(String l : li<caret>st) {
|
||||
TEST:
|
||||
}
|
||||
}
|
||||
}
|
||||
+92
-17
@@ -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<String> o, OptionalDouble od, OptionalInt oi, OptionalLong ol) {
|
||||
System.out.println(o.<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>());
|
||||
System.out.println(oi.<warning descr="'OptionalInt.getAsInt()' without 'isPresent()' check">getAsInt</warning>());
|
||||
System.out.println(ol.<warning descr="'OptionalLong.getAsLong()' without 'isPresent()' check">getAsLong</warning>());
|
||||
System.out.println(od.<warning descr="'OptionalDouble.getAsDouble()' without 'isPresent()' check">getAsDouble</warning>());
|
||||
}
|
||||
|
||||
{
|
||||
System.out.println(getIntegerOptional().<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>());
|
||||
}
|
||||
|
||||
void testWhile() {
|
||||
Optional<String> o = Optional.empty();
|
||||
while (!o.isPresent()) {
|
||||
o = Optional.of("");
|
||||
}
|
||||
System.out.println(o.get());
|
||||
}
|
||||
|
||||
void testWhile2() {
|
||||
Optional<Integer> o = getIntegerOptional();
|
||||
while (o.isPresent()) {
|
||||
System.out.println(o.get());
|
||||
}
|
||||
}
|
||||
|
||||
public void testPolyadicExpression(Optional<String> value) {
|
||||
boolean flag = value.isPresent() && "Yes".equals(value.get());
|
||||
}
|
||||
|
||||
boolean testPolyadicExpression2(Optional<String> o) {
|
||||
return !o.isPresent() || o.get().equals("j");
|
||||
}
|
||||
|
||||
String testPolyadicExpression3() {
|
||||
Optional<String> o = getOptional();
|
||||
if (o == null || !o.isPresent()) {
|
||||
return "";
|
||||
}
|
||||
return o.get();
|
||||
}
|
||||
|
||||
void testNested(Optional<String> 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<Integer> maybe) {
|
||||
if (!!!maybe.isPresent()) {
|
||||
maybe = getIntegerOptional();
|
||||
@@ -29,9 +84,9 @@ class OptionalWithoutIsPresent {
|
||||
maybe = Optional.empty();
|
||||
System.out.println(maybe.<warning descr="'Optional.get()' will definitely fail as Optional is empty here">get</warning>());
|
||||
}
|
||||
boolean b = ((maybe.isPresent())) && maybe.get() == 1;
|
||||
boolean c = (!maybe.isPresent()) || maybe.get() == 1;
|
||||
Integer value = !maybe.isPresent() ? 0 : maybe.get();
|
||||
boolean b = <warning descr="Condition '((maybe.isPresent()))' is always 'false'">((maybe.isPresent()))</warning> && maybe.get() == 1;
|
||||
boolean c = <warning descr="Condition '(!maybe.isPresent())' is always 'true'">(!maybe.isPresent())</warning> || maybe.get() == 1;
|
||||
Integer value = <warning descr="Condition '!maybe.isPresent()' is always 'true'">!maybe.isPresent()</warning> ? 0 : maybe.get();
|
||||
}
|
||||
|
||||
Optional<Integer> getIntegerOptional() {
|
||||
@@ -42,7 +97,7 @@ class OptionalWithoutIsPresent {
|
||||
Optional<String> optional = Optional.empty();
|
||||
final boolean present = optional.isPresent();
|
||||
// optional = Optional.empty();
|
||||
if (present) {
|
||||
if (<warning descr="Condition 'present' is always 'false'">present</warning>) {
|
||||
final String string = optional.get();
|
||||
System.out.println(string);
|
||||
}
|
||||
@@ -52,7 +107,7 @@ class OptionalWithoutIsPresent {
|
||||
Optional<String> optional = Optional.empty();
|
||||
final boolean present = optional.isPresent();
|
||||
optional = Optional.empty();
|
||||
if (present) {
|
||||
if (<warning descr="Condition 'present' is always 'false'">present</warning>) {
|
||||
final String string = optional.get();
|
||||
System.out.println(string);
|
||||
}
|
||||
@@ -101,7 +156,7 @@ class OptionalWithoutIsPresent {
|
||||
|
||||
private void checkAsserts2() {
|
||||
Optional<String> o3 = Optional.empty();
|
||||
org.testng.Assert.assertTrue(o3.isPresent());
|
||||
org.testng.Assert.<warning descr="The call to assertTrue always fails, according to its method contracts">assertTrue</warning>(o3.isPresent());
|
||||
System.out.println(o3.get());
|
||||
}
|
||||
|
||||
@@ -131,16 +186,16 @@ class OptionalWithoutIsPresent {
|
||||
|
||||
private void checkOfNullable(String value) {
|
||||
System.out.println(Optional.ofNullable(value).<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>());
|
||||
System.out.println(Optional.ofNullable(value+"a").get());
|
||||
System.out.println(Optional.ofNullable("xyz").get());
|
||||
System.out.println(Optional.ofNullable(<warning descr="Passing a non-null argument to 'Optional'">value+"a"</warning>).get());
|
||||
System.out.println(Optional.ofNullable(<warning descr="Passing a non-null argument to 'Optional'">"xyz"</warning>).get());
|
||||
}
|
||||
|
||||
public static String demo() {
|
||||
Optional<String> holder = Optional.empty();
|
||||
|
||||
if (! holder.isPresent()) {
|
||||
if (<warning descr="Condition '! holder.isPresent()' is always 'true'">! holder.isPresent()</warning>) {
|
||||
holder = Optional.of("hello world");
|
||||
if (!holder.isPresent()) {
|
||||
if (<warning descr="Condition '!holder.isPresent()' is always 'false'">!holder.isPresent()</warning>) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -171,9 +226,10 @@ class OptionalWithoutIsPresent {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
//void order(Optional<String> order) {
|
||||
// order.ifPresent(o -> System.out.println(order.get()));
|
||||
//}
|
||||
void order(Optional<String> order, boolean b) {
|
||||
order.ifPresent(o -> System.out.println(order.get()));
|
||||
System.out.println(order.orElseGet(() -> order.<warning descr="'Optional.get()' will definitely fail as Optional is empty here">get</warning>().trim()));
|
||||
}
|
||||
|
||||
public static void two(Optional<Object> o1,Optional<Object> o2) {
|
||||
if (!o1.isPresent() && !o2.isPresent()) {
|
||||
@@ -210,7 +266,7 @@ class OptionalWithoutIsPresent {
|
||||
opt2.get();
|
||||
}
|
||||
|
||||
static final class Range {
|
||||
class Range {
|
||||
Optional<Integer> min = Optional.of(1);
|
||||
Optional<Integer> max = Optional.of(2);
|
||||
|
||||
@@ -243,7 +299,7 @@ class OptionalWithoutIsPresent {
|
||||
}
|
||||
|
||||
void shortIf(Optional<String> o) {
|
||||
if (true || o.isPresent()) {
|
||||
if (<warning descr="Condition 'true || o.isPresent()' is always 'true'">true || o.isPresent()</warning>) {
|
||||
o.<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>();
|
||||
}
|
||||
}
|
||||
@@ -257,6 +313,25 @@ class OptionalWithoutIsPresent {
|
||||
}
|
||||
|
||||
String f(Optional<String> optional, Optional<String> opt2) {
|
||||
return optional.isPresent() ? opt2.<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>() : null;
|
||||
return optional.isPresent() ? opt2.<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>() : "";
|
||||
}
|
||||
|
||||
void guavaTest(com.google.common.base.Optional<String> opt, String s) {
|
||||
System.out.println(opt.<warning descr="'Optional.get()' without 'isPresent()' check">get</warning>());
|
||||
if(opt.isPresent()) {
|
||||
System.out.println(opt.get());
|
||||
}
|
||||
opt = com.google.common.base.Optional.fromNullable(s);
|
||||
if(opt.isPresent()) {
|
||||
System.out.println(opt.get());
|
||||
}
|
||||
opt = com.google.common.base.Optional.of(s);
|
||||
if(<warning descr="Condition 'opt.isPresent()' is always 'true'">opt.isPresent()</warning>) {
|
||||
System.out.println(opt.get());
|
||||
}
|
||||
opt = com.google.common.base.Optional.absent();
|
||||
if(<warning descr="Condition 'opt.isPresent()' is always 'false'">opt.isPresent()</warning>) {
|
||||
System.out.println(opt.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -517,6 +517,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testApplicabilityErrorVisibleWhenConstraintsFromFunctionalExpressionsProvideValidSubstitutor() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testMethodReferenceSecondSearchDontInfluenceTopSiteSubstitutor() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -18,18 +18,29 @@ package com.intellij.codeInspection;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
|
||||
private static final DefaultLightProjectDescriptor PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() {
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return PsiTestUtil.addJdkAnnotations(IdeaTestUtil.getMockJdk18());
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_8;
|
||||
return PROJECT_DESCRIPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,8 +57,30 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
|
||||
public void testNullableVoidLambda() { doTest(); }
|
||||
public void testNullableForeachVariable() { doTestWithCustomAnnotations(); }
|
||||
public void testGenericParameterNullity() { doTestWithCustomAnnotations(); }
|
||||
|
||||
public void testOptionalOfNullable() { doTest(); }
|
||||
public void testOptionalIsPresent() { doTest(); }
|
||||
public void testOptionalGetWithoutIsPresent() {
|
||||
myFixture.addClass("package org.junit;" +
|
||||
"public class Assert {" +
|
||||
" public static void assertTrue(boolean b) {}" +
|
||||
"}");
|
||||
myFixture.addClass("package org.testng;" +
|
||||
"public class Assert {" +
|
||||
" public static void assertTrue(boolean b) {}" +
|
||||
"}");
|
||||
myFixture.addClass("package com.google.common.base;\n" +
|
||||
"\n" +
|
||||
"public abstract class Optional<T> {\n" +
|
||||
" public static <T> Optional<T> absent() {}\n" +
|
||||
" public static <T> Optional<T> of(T ref) {}\n" +
|
||||
" public static <T> Optional<T> fromNullable(T ref) {}\n" +
|
||||
" public abstract T get();\n" +
|
||||
" public abstract boolean isPresent();\n" +
|
||||
"}");
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPrimitiveInVoidLambda() { doTest(); }
|
||||
public void testNotNullLambdaParameter() { doTest(); }
|
||||
public void testNotNullOptionalLambdaParameter() { doTest(); }
|
||||
|
||||
@@ -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.
|
||||
@@ -423,7 +423,7 @@ public class ClsPsiTest extends LightIdeaTestCase {
|
||||
|
||||
PsiJavaModule module = file.getModuleDeclaration();
|
||||
assertNotNull(module);
|
||||
assertEquals("M.N", module.getModuleName());
|
||||
assertEquals("M.N", module.getName());
|
||||
|
||||
assertNull(file.getPackageStatement());
|
||||
assertEquals(0, file.getClasses().length);
|
||||
|
||||
@@ -37,4 +37,13 @@ public class ConstantEvaluatorTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
assertEquals(MyEnum.Foo, result);
|
||||
}
|
||||
|
||||
public void testPrefixExpressionEvaluation() throws Exception {
|
||||
PsiJavaFile file = (PsiJavaFile)myFixture.configureByText("A.java", "class A {public static final int VALUE = ~0 >>> 1;}");
|
||||
PsiClass aClass = file.getClasses()[0];
|
||||
PsiField vField = aClass.getFields()[0];
|
||||
Object result = JavaPsiFacade.getInstance(getProject()).getConstantEvaluationHelper().computeConstantExpression(vField.getInitializer());
|
||||
|
||||
assertEquals(2147483647, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,4 +76,14 @@ public abstract class ExternalAnnotator<InitialInfoType, AnnotationResultType> {
|
||||
*/
|
||||
public void apply(@NotNull PsiFile file, AnnotationResultType annotationResult, @NotNull AnnotationHolder holder) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return inspection which should run in batch mode.
|
||||
* When inspection with short name is disabled, then annotator won't run in the editor via {@link com.intellij.codeInsight.daemon.impl.ExternalToolPass}.
|
||||
* Implementing {@link com.intellij.codeInspection.ex.ExternalAnnotatorBatchInspection} and extending {@link com.intellij.codeInspection.LocalInspectionTool} would
|
||||
* provide implementation for a batch tool which would run without read action, according to the {@link #doAnnotate(Object)} documentation
|
||||
*/
|
||||
public String getPairedBatchInspectionShortName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -21,6 +21,7 @@ import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.ExternalAnnotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
@@ -58,21 +59,23 @@ public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor {
|
||||
public static <Init,Result> ProblemDescriptor[] checkFileWithExternalAnnotator(@NotNull PsiFile file,
|
||||
@NotNull InspectionManager manager,
|
||||
boolean isOnTheFly,
|
||||
@NotNull ExternalAnnotator<Init,Result> annotator) {
|
||||
@NotNull ExternalAnnotator<Init, Result> annotator) {
|
||||
if (isOnTheFly) {
|
||||
// ExternalAnnotator does this work
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
Init info = annotator.collectInformation(file);
|
||||
Init info = ReadAction.compute(() -> annotator.collectInformation(file));
|
||||
if (info != null) {
|
||||
Result annotationResult = annotator.doAnnotate(info);
|
||||
if (annotationResult == null) {
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
AnnotationHolderImpl annotationHolder = new AnnotationHolderImpl(new AnnotationSession(file));
|
||||
annotator.apply(file, annotationResult, annotationHolder);
|
||||
return convertToProblemDescriptors(annotationHolder, manager, file);
|
||||
return ReadAction.compute(() -> {
|
||||
AnnotationHolderImpl annotationHolder = new AnnotationHolderImpl(new AnnotationSession(file));
|
||||
annotator.apply(file, annotationResult, annotationHolder);
|
||||
return convertToProblemDescriptors(annotationHolder, manager, file);
|
||||
});
|
||||
}
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 com.intellij.codeInspection.ex;
|
||||
|
||||
import com.intellij.codeInspection.ExternalAnnotatorInspectionVisitor;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.lang.ExternalLanguageAnnotators;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.annotation.ExternalAnnotator;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ExternalAnnotatorBatchInspection extends PairedUnfairLocalInspectionTool {
|
||||
@NotNull
|
||||
String getShortName();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
default String getInspectionForBatchShortName() {
|
||||
return getShortName();
|
||||
}
|
||||
|
||||
default ProblemDescriptor[] checkFile(PsiFile file, InspectionManager manager) {
|
||||
final String shortName = getShortName();
|
||||
final FileViewProvider viewProvider = file.getViewProvider();
|
||||
final Set<Language> relevantLanguages = viewProvider.getLanguages();
|
||||
for (Language language : relevantLanguages) {
|
||||
PsiFile psiRoot = viewProvider.getPsi(language);
|
||||
final List<ExternalAnnotator> externalAnnotators = ExternalLanguageAnnotators.allForFile(language, psiRoot);
|
||||
|
||||
for (ExternalAnnotator annotator : externalAnnotators) {
|
||||
if (shortName.equals(annotator.getPairedBatchInspectionShortName())) {
|
||||
return ExternalAnnotatorInspectionVisitor.checkFileWithExternalAnnotator(file, manager, false, annotator);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,21 @@ package com.intellij.configurationStore
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.util.loadElement
|
||||
import com.intellij.util.xmlb.XmlSerializer
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import org.junit.Test
|
||||
|
||||
private class AState : BaseState() {
|
||||
internal class AState : BaseState() {
|
||||
@get:Attribute("customName")
|
||||
var languageLevel by storedProperty<String?>()
|
||||
|
||||
var property2 by storedProperty(0)
|
||||
|
||||
var floatProperty by storedProperty(0.3)
|
||||
|
||||
var nestedComplex by storedProperty<NestedState?>()
|
||||
}
|
||||
|
||||
private class NestedState : BaseState() {
|
||||
internal class NestedState : BaseState() {
|
||||
var childProperty by storedProperty<String?>()
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ class StoredPropertyStateTest {
|
||||
|
||||
assertThat(state).isNotEqualTo(AState())
|
||||
|
||||
assertThat(XmlSerializer.serialize(state)).isEqualTo("""<AState customName="foo" />""")
|
||||
assertThat(state.serialize()).isEqualTo("""<AState customName="foo" />""")
|
||||
assertThat(loadElement("""<AState customName="foo" />""").deserialize(AState::class.java).languageLevel).isEqualTo("foo")
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.configurationStore.xml
|
||||
|
||||
import com.intellij.configurationStore.AState
|
||||
import com.intellij.configurationStore.deserialize
|
||||
import com.intellij.util.loadElement
|
||||
import com.intellij.util.xmlb.annotations.MapAnnotation
|
||||
@@ -38,6 +39,16 @@ class KotlinXmlSerializerTest {
|
||||
</bean>""", data)
|
||||
}
|
||||
|
||||
@Test fun floatProperty() {
|
||||
val state = AState()
|
||||
state.floatProperty = 3.4
|
||||
doSerializerTest("""
|
||||
<AState>
|
||||
<option name="floatProperty" value="3.4" />
|
||||
</AState>
|
||||
""", state)
|
||||
}
|
||||
|
||||
@Test fun nullInMap() {
|
||||
@Tag("bean")
|
||||
class Foo {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.configurationStore.xml
|
||||
|
||||
import com.intellij.configurationStore.StoredPropertyStateTest
|
||||
import com.intellij.configurationStore.deserialize
|
||||
import com.intellij.configurationStore.serialize
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
@@ -39,6 +40,7 @@ import java.util.*
|
||||
XmlSerializerTest::class,
|
||||
XmlSerializerMapTest::class,
|
||||
XmlSerializerCollectionTest::class,
|
||||
StoredPropertyStateTest::class,
|
||||
KotlinXmlSerializerTest::class
|
||||
)
|
||||
class XmlSerializerTestSuite
|
||||
@@ -240,7 +242,7 @@ internal class XmlSerializerTest {
|
||||
bean.INT_V = 987
|
||||
bean.STRING_V = "1234"
|
||||
|
||||
val element = bean.serialize(null)
|
||||
val element = bean.serialize()
|
||||
|
||||
val node = element.children.get(0)
|
||||
element.removeContent(node)
|
||||
@@ -642,7 +644,7 @@ internal class XmlSerializerTest {
|
||||
private val XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
|
||||
internal fun assertSerializer(bean: Any, expected: String, filter: SerializationFilter?, description: String = "Serialization failure"): Element {
|
||||
val element = bean.serialize(filter)
|
||||
val element = bean.serialize<Any>(filter)
|
||||
var actual = JDOMUtil.writeElement(element, "\n").trim()
|
||||
if (!expected.startsWith(XML_PREFIX) && actual.startsWith(XML_PREFIX)) {
|
||||
actual = actual.substring(XML_PREFIX.length).trim()
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.intellij.configurationStore.xml;
|
||||
|
||||
import com.intellij.configurationStore.XmlSerializer;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.xmlb.SerializationFilter;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import junit.framework.TestCase;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public class XmlSerializerWithDefaultJDOMExternalizerCompatibilityTest extends TestCase {
|
||||
public void testCompatibility() throws Exception {
|
||||
final MyBean bean = new MyBean();
|
||||
assertCompatibleSerialization(bean, "MyBean");
|
||||
}
|
||||
|
||||
private static void assertCompatibleSerialization(final Object data, final String rootTagName) throws Exception {
|
||||
assertEquals(serializeWithJDom(data, rootTagName), serializeWithXmlSerializer(data));
|
||||
}
|
||||
|
||||
private static String serializeWithXmlSerializer(final Object data) throws Exception {
|
||||
Element element = serialize(data, null);
|
||||
|
||||
String s = JDOMUtil.writeElement(element, "\n");
|
||||
return StringUtil.trimStart(s, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>").trim();
|
||||
}
|
||||
|
||||
private static String serializeWithJDom(final Object data, String rootTagName) throws Exception {
|
||||
final Element jDomRoot = new Element(rootTagName);
|
||||
|
||||
if (data instanceof com.intellij.openapi.util.JDOMExternalizable) {
|
||||
((com.intellij.openapi.util.JDOMExternalizable)data).writeExternal(jDomRoot);
|
||||
}
|
||||
else {
|
||||
com.intellij.openapi.util.DefaultJDOMExternalizer.writeExternal(data, jDomRoot);
|
||||
}
|
||||
|
||||
return JDOMUtil.writeElement(jDomRoot, "\n").trim();
|
||||
}
|
||||
|
||||
private static Element serialize(Object bean, @Nullable SerializationFilter filter) {
|
||||
return XmlSerializer.serialize(bean, filter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class MyBean {
|
||||
public int intField = 0;
|
||||
public int intField2 = 1;
|
||||
public boolean booleanField = false;
|
||||
public boolean booleanField2 = true;
|
||||
public String stringField;
|
||||
public String stringField2 = "a";
|
||||
public float floatField;
|
||||
public float floatField2 = 1;
|
||||
public transient int transientField;
|
||||
@Transient
|
||||
public int transientField2;
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -22,6 +21,5 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author yole
|
||||
*/
|
||||
public interface PsiNameIdentifierOwner extends PsiNamedElement {
|
||||
@Nullable
|
||||
PsiElement getNameIdentifier();
|
||||
}
|
||||
@Nullable PsiElement getNameIdentifier();
|
||||
}
|
||||
@@ -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.
|
||||
@@ -16,14 +16,13 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A PSI element which has a name and can be renamed (for example, a class or a method).
|
||||
*/
|
||||
public interface PsiNamedElement extends PsiElement{
|
||||
public interface PsiNamedElement extends PsiElement {
|
||||
/**
|
||||
* The empty array of PSI named elements which can be reused to avoid unnecessary allocations.
|
||||
*/
|
||||
@@ -34,7 +33,7 @@ public interface PsiNamedElement extends PsiElement{
|
||||
*
|
||||
* @return the element name.
|
||||
*/
|
||||
@Nullable @NonNls String getName();
|
||||
@Nullable String getName();
|
||||
|
||||
/**
|
||||
* Renames the element.
|
||||
@@ -44,5 +43,5 @@ public interface PsiNamedElement extends PsiElement{
|
||||
* or a different element if the rename caused the element to be replaced).
|
||||
* @throws IncorrectOperationException if the modification is not supported or not possible for some reason.
|
||||
*/
|
||||
PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException;
|
||||
}
|
||||
PsiElement setName(@NotNull String name) throws IncorrectOperationException;
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.WalkingState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -30,12 +31,17 @@ public abstract class PsiWalkingState extends WalkingState<PsiElement> {
|
||||
private static class PsiTreeGuide implements TreeGuide<PsiElement> {
|
||||
@Override
|
||||
public PsiElement getNextSibling(@NotNull PsiElement element) {
|
||||
return element.getNextSibling();
|
||||
return checkSanity(element, element.getNextSibling());
|
||||
}
|
||||
|
||||
private static PsiElement checkSanity(PsiElement element, PsiElement sibling) {
|
||||
if (sibling == PsiUtilCore.NULL_PSI_ELEMENT) throw new PsiInvalidElementAccessException(element, "Sibling of "+element+" is NULL_PSI_ELEMENT");
|
||||
return sibling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getPrevSibling(@NotNull PsiElement element) {
|
||||
return element.getPrevSibling();
|
||||
return checkSanity(element, element.getPrevSibling());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -192,7 +192,9 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
checkMax(false);
|
||||
|
||||
if (!affected.isEmpty()) {
|
||||
for (IntervalNode<T> node : affected) {
|
||||
// reverse direction to visit leaves first - it's cheaper to compute maxEndOf for them first
|
||||
for (int i = affected.size() - 1; i >= 0; i--) {
|
||||
IntervalNode<T> node = affected.get(i);
|
||||
// assumption: interval.getEndOffset() will never be accessed during remove()
|
||||
int startOffset = node.intervalStart();
|
||||
int endOffset = node.intervalEnd();
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi.roots.impl;
|
||||
|
||||
import com.intellij.openapi.util.LowMemoryWatcher;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.VolatileNotNullLazyValue;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
@@ -35,18 +34,15 @@ public class PackageDirectoryCache {
|
||||
private final MultiMap<String, VirtualFile> myRootsByPackagePrefix;
|
||||
private final Map<String, PackageInfo> myDirectoriesByPackageNameCache = ContainerUtil.newConcurrentMap();
|
||||
private final Set<String> myNonExistentPackages = ContainerUtil.newConcurrentSet();
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myNonExistentPackages.clear();
|
||||
}
|
||||
});
|
||||
|
||||
public PackageDirectoryCache(MultiMap<String, VirtualFile> rootsByPackagePrefix) {
|
||||
public PackageDirectoryCache(@NotNull MultiMap<String, VirtualFile> rootsByPackagePrefix) {
|
||||
myRootsByPackagePrefix = rootsByPackagePrefix;
|
||||
}
|
||||
|
||||
public void onLowMemory() {
|
||||
myNonExistentPackages.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VirtualFile> getDirectoriesByPackageName(@NotNull final String packageName) {
|
||||
PackageInfo info = getPackageInfo(packageName);
|
||||
@@ -120,8 +116,8 @@ public class PackageDirectoryCache {
|
||||
};
|
||||
|
||||
PackageInfo(String qname, List<VirtualFile> packageDirectories) {
|
||||
this.myQname = qname;
|
||||
this.myPackageDirectories = packageDirectories;
|
||||
myQname = qname;
|
||||
myPackageDirectories = packageDirectories;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/*
|
||||
* Copyright 2000-2014 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.
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class CachedValueBase<T> {
|
||||
|
||||
@Nullable
|
||||
private synchronized Data<T> cacheOrGetData(@Nullable Data<T> expected, @Nullable Data<T> updatedValue) {
|
||||
if (expected != getData()) return null;
|
||||
if (expected != getRawData()) return null;
|
||||
|
||||
if (updatedValue != null) {
|
||||
myData = new SoftReference<Data<T>>(updatedValue);
|
||||
@@ -67,7 +67,7 @@ public abstract class CachedValueBase<T> {
|
||||
}
|
||||
|
||||
private synchronized boolean compareAndClearData(Data<T> expected) {
|
||||
if (getData() == expected) {
|
||||
if (getRawData() == expected) {
|
||||
myData = null;
|
||||
return true;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ public abstract class CachedValueBase<T> {
|
||||
|
||||
@Nullable
|
||||
private Data<T> getUpToDateOrNull(boolean dispose) {
|
||||
final Data<T> data = getData();
|
||||
final Data<T> data = getRawData();
|
||||
|
||||
if (data != null) {
|
||||
if (isUpToDate(data)) {
|
||||
@@ -115,7 +115,7 @@ public abstract class CachedValueBase<T> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Data<T> getData() {
|
||||
final Data<T> getRawData() {
|
||||
return SoftReference.dereference(myData);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ public abstract class CachedValueBase<T> {
|
||||
|
||||
if (stamp.mayCacheNow()) {
|
||||
while (true) {
|
||||
Data<T> alreadyComputed = getData();
|
||||
Data<T> alreadyComputed = getRawData();
|
||||
boolean reuse = alreadyComputed != null && isUpToDate(alreadyComputed);
|
||||
Data<T> toReturn = cacheOrGetData(alreadyComputed, reuse ? null : data);
|
||||
if (toReturn != null) {
|
||||
|
||||
@@ -86,7 +86,11 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
|
||||
|
||||
private boolean isOutdated(CachedValue<?> value) {
|
||||
return value instanceof CachedValueBase &&
|
||||
(!((CachedValueBase)value).isFromMyProject(myProject) || !value.hasUpToDateValue());
|
||||
(!((CachedValueBase)value).isFromMyProject(myProject) || hasOutdatedValue((CachedValueBase)value));
|
||||
}
|
||||
|
||||
private static boolean hasOutdatedValue(CachedValueBase base) {
|
||||
return !base.hasUpToDateValue() && base.getRawData() != null;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.LowMemoryWatcher;
|
||||
import com.intellij.util.containers.WeakList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -34,15 +35,20 @@ public class SofterReference<T> {
|
||||
private volatile Reference<T> myRef;
|
||||
private static final WeakList<SofterReference> ourRegistry = new WeakList<SofterReference>();
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private static final LowMemoryWatcher ourWatcher = LowMemoryWatcher.register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (SofterReference reference : ourRegistry.copyAndClear()) {
|
||||
reference.weaken();
|
||||
}
|
||||
private static void onLowMemory() {
|
||||
for (SofterReference reference : ourRegistry.copyAndClear()) {
|
||||
reference.weaken();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static {
|
||||
LowMemoryWatcher.register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLowMemory();
|
||||
}
|
||||
}, ApplicationManager.getApplication());
|
||||
}
|
||||
|
||||
public SofterReference(@NotNull T referent) {
|
||||
ourRegistry.add(this);
|
||||
|
||||
+3
-4
@@ -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.
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import org.jdom.Element;
|
||||
@@ -65,8 +64,8 @@ public class MultilanguageDuplocatorSettings implements PersistentStateComponent
|
||||
|
||||
SkipDefaultValuesSerializationFilters filter = new SkipDefaultValuesSerializationFilters();
|
||||
for (String name : mySettingsMap.keySet()) {
|
||||
Element child = XmlSerializer.serialize(mySettingsMap.get(name), filter);
|
||||
if (!JDOMUtil.isEmpty(child)) {
|
||||
Element child = XmlSerializer.serializeIfNotDefault(mySettingsMap.get(name), filter);
|
||||
if (child != null) {
|
||||
child.setName("object");
|
||||
child.setAttribute("language", name);
|
||||
state.addContent(child);
|
||||
|
||||
@@ -388,18 +388,21 @@ public class BranchActionGroupPopup extends FlatSpeedSearchPopup {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@Nullable private final String mySettingName;
|
||||
private final boolean myDefaultExpandValue;
|
||||
private boolean myIsExpanded;
|
||||
@NotNull private final String myToCollapseText;
|
||||
@NotNull private final String myToExpandText;
|
||||
|
||||
public MoreAction(@NotNull Project project, int numberOfHiddenNodes, @Nullable String settingName) {
|
||||
public MoreAction(@NotNull Project project, int numberOfHiddenNodes, @Nullable String settingName, boolean defaultExpandValue) {
|
||||
super();
|
||||
myProject = project;
|
||||
mySettingName = settingName;
|
||||
myDefaultExpandValue = defaultExpandValue;
|
||||
assert numberOfHiddenNodes > 0;
|
||||
myToExpandText = "Show " + numberOfHiddenNodes + " More...";
|
||||
myToCollapseText = "Show Only Favorites";
|
||||
setExpanded(settingName != null && PropertiesComponent.getInstance(project).getBoolean(settingName, false));
|
||||
setExpanded(
|
||||
settingName != null ? PropertiesComponent.getInstance(project).getBoolean(settingName, defaultExpandValue) : defaultExpandValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -430,7 +433,7 @@ public class BranchActionGroupPopup extends FlatSpeedSearchPopup {
|
||||
|
||||
public void saveState() {
|
||||
if (mySettingName != null) {
|
||||
PropertiesComponent.getInstance(myProject).setValue(mySettingName, myIsExpanded);
|
||||
PropertiesComponent.getInstance(myProject).setValue(mySettingName, myIsExpanded, myDefaultExpandValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,8 +459,14 @@ public class BranchActionGroupPopup extends FlatSpeedSearchPopup {
|
||||
public static void wrapWithMoreActionIfNeeded(@NotNull Project project,
|
||||
@NotNull DefaultActionGroup parentGroup, @NotNull List<? extends ActionGroup> actionList,
|
||||
int maxIndex, @Nullable String settingName) {
|
||||
wrapWithMoreActionIfNeeded(project, parentGroup, actionList, maxIndex, settingName, false);
|
||||
}
|
||||
|
||||
public static void wrapWithMoreActionIfNeeded(@NotNull Project project,
|
||||
@NotNull DefaultActionGroup parentGroup, @NotNull List<? extends ActionGroup> actionList,
|
||||
int maxIndex, @Nullable String settingName, boolean defaultExpandValue) {
|
||||
if (actionList.size() > maxIndex) {
|
||||
MoreAction moreAction = new MoreAction(project, actionList.size() - maxIndex, settingName);
|
||||
MoreAction moreAction = new MoreAction(project, actionList.size() - maxIndex, settingName, defaultExpandValue);
|
||||
for (int i = 0; i < actionList.size(); i++) {
|
||||
parentGroup.add(i < maxIndex ? actionList.get(i) : new HideableActionGroup(actionList.get(i), moreAction));
|
||||
}
|
||||
|
||||
@@ -98,6 +98,18 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
@Transient
|
||||
var PRESENTATION_MODE = false
|
||||
|
||||
@Suppress("unused")
|
||||
@Deprecated("Use overrideLafFonts", replaceWith = ReplaceWith("overrideLafFonts"))
|
||||
@JvmField
|
||||
@Transient
|
||||
var OVERRIDE_NONIDEA_LAF_FONTS = false
|
||||
|
||||
@Suppress("unused")
|
||||
@Deprecated("Use presentationModeFontSize", replaceWith = ReplaceWith("presentationModeFontSize"))
|
||||
@JvmField
|
||||
@Transient
|
||||
var PRESENTATION_MODE_FONT_SIZE = 24
|
||||
|
||||
@get:OptionTag("REUSE_NOT_MODIFIED_TABS") var reuseNotModifiedTabs by storedProperty(false)
|
||||
@get:OptionTag("ANIMATE_WINDOWS") var animateWindows by storedProperty(true)
|
||||
@get:OptionTag("SHOW_TOOL_WINDOW_NUMBERS") var showToolWindowsNumbers by storedProperty(true)
|
||||
@@ -117,36 +129,36 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
@get:OptionTag("HIDE_TABS_IF_NEED") var hideTabsIfNeed by storedProperty(true)
|
||||
@get:OptionTag("SHOW_CLOSE_BUTTON") var showCloseButton by storedProperty(true)
|
||||
@get:OptionTag("EDITOR_TAB_PLACEMENT") var editorTabPlacement by storedProperty(1)
|
||||
|
||||
@JvmField var HIDE_KNOWN_EXTENSION_IN_TABS = false
|
||||
@JvmField var SHOW_ICONS_IN_QUICK_NAVIGATION = true
|
||||
@JvmField var CLOSE_NON_MODIFIED_FILES_FIRST = false
|
||||
@JvmField var ACTIVATE_MRU_EDITOR_ON_CLOSE = false
|
||||
@JvmField var ACTIVATE_RIGHT_EDITOR_ON_CLOSE = false
|
||||
@get:OptionTag("HIDE_KNOWN_EXTENSION_IN_TABS") var hdeKnownExtensionInTabs by storedProperty(false)
|
||||
@get:OptionTag("SHOW_ICONS_IN_QUICK_NAVIGATION") var showIconInQuickNavigation by storedProperty(true)
|
||||
@get:OptionTag("CLOSE_NON_MODIFIED_FILES_FIRST") var closeNonModifiedFilesFirst by storedProperty(false)
|
||||
@get:OptionTag("ACTIVATE_MRU_EDITOR_ON_CLOSE") var activeMruEditorOnClose by storedProperty(false)
|
||||
@get:OptionTag("ACTIVATE_RIGHT_EDITOR_ON_CLOSE") var activeRigtEditorOnClose by storedProperty(false)
|
||||
@get:OptionTag("IDE_AA_TYPE") var ideAAType by storedProperty(AntialiasingType.SUBPIXEL)
|
||||
@get:OptionTag("EDITOR_AA_TYPE") var editorAAType by storedProperty(AntialiasingType.SUBPIXEL)
|
||||
@JvmField var COLOR_BLINDNESS: ColorBlindness? = null
|
||||
@JvmField var MOVE_MOUSE_ON_DEFAULT_BUTTON = false
|
||||
@JvmField var ENABLE_ALPHA_MODE = false
|
||||
@JvmField var ALPHA_MODE_DELAY = 1500
|
||||
@JvmField var ALPHA_MODE_RATIO = 0.5f
|
||||
@JvmField var MAX_CLIPBOARD_CONTENTS = 5
|
||||
@JvmField var OVERRIDE_NONIDEA_LAF_FONTS = false
|
||||
@JvmField var SHOW_ICONS_IN_MENUS = true
|
||||
@JvmField var DISABLE_MNEMONICS = SystemInfo.isMac // IDEADEV-33409, should be disabled by default on MacOS
|
||||
@JvmField var DISABLE_MNEMONICS_IN_CONTROLS = false
|
||||
@JvmField var USE_SMALL_LABELS_ON_TABS = SystemInfo.isMac
|
||||
@JvmField var MAX_LOOKUP_WIDTH2 = 500
|
||||
@JvmField var MAX_LOOKUP_LIST_HEIGHT = 11
|
||||
@JvmField var HIDE_NAVIGATION_ON_FOCUS_LOSS = true
|
||||
@JvmField var DND_WITH_PRESSED_ALT_ONLY = false
|
||||
@JvmField var DEFAULT_AUTOSCROLL_TO_SOURCE = false
|
||||
@get:OptionTag("MOVE_MOUSE_ON_DEFAULT_BUTTON") var moveMouseOnDefaultButton by storedProperty(false)
|
||||
@get:OptionTag("ENABLE_ALPHA_MODE") var enableAlphaMode by storedProperty(false)
|
||||
@get:OptionTag("ALPHA_MODE_DELAY") var alphaModeDelay by storedProperty(1500)
|
||||
@get:OptionTag("ALPHA_MODE_RATIO") var alphaModeRatio by storedProperty(0.5f)
|
||||
@get:OptionTag("MAX_CLIPBOARD_CONTENTS") var maxClipboardContents by storedProperty(5)
|
||||
@get:OptionTag("OVERRIDE_NONIDEA_LAF_FONTS") var overrideLafFonts by storedProperty(false)
|
||||
@get:OptionTag("SHOW_ICONS_IN_MENUS") var showIconsInMenus by storedProperty(true)
|
||||
// IDEADEV-33409, should be disabled by default on MacOS
|
||||
@get:OptionTag("DISABLE_MNEMONICS") var disableMnemonics by storedProperty(SystemInfo.isMac)
|
||||
@get:OptionTag("DISABLE_MNEMONICS_IN_CONTROLS") var disableMnemonicsInControls by storedProperty(false)
|
||||
@get:OptionTag("USE_SMALL_LABELS_ON_TABS") var useSmallLabelsOnTabs by storedProperty(SystemInfo.isMac)
|
||||
@get:OptionTag("MAX_LOOKUP_WIDTH2") var maxLookupWidth by storedProperty(500)
|
||||
@get:OptionTag("MAX_LOOKUP_LIST_HEIGHT") var maxLookupListHeight by storedProperty(11)
|
||||
@get:OptionTag("HIDE_NAVIGATION_ON_FOCUS_LOSS") var hideNavigationOnFocusLoss by storedProperty(true)
|
||||
@get:OptionTag("DND_WITH_PRESSED_ALT_ONLY") var dndWithPressedAltOnly by storedProperty(false)
|
||||
@get:OptionTag("DEFAULT_AUTOSCROLL_TO_SOURCE") var defaultAutoScrollToSource by storedProperty(false)
|
||||
@Transient var presentationMode = false
|
||||
@JvmField var PRESENTATION_MODE_FONT_SIZE = 24
|
||||
@JvmField var MARK_MODIFIED_TABS_WITH_ASTERISK = false
|
||||
@JvmField var SHOW_TABS_TOOLTIPS = true
|
||||
@JvmField var SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true
|
||||
@JvmField var NAVIGATE_TO_PREVIEW = false
|
||||
@get:OptionTag("PRESENTATION_MODE_FONT_SIZE") var presentationModeFontSize by storedProperty(24)
|
||||
@get:OptionTag("MARK_MODIFIED_TABS_WITH_ASTERISK") var markModifiedTabsWithAsterisk by storedProperty(false)
|
||||
@get:OptionTag("SHOW_TABS_TOOLTIPS") var showTabsTooltips by storedProperty(true)
|
||||
@get:OptionTag("SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES") var showDirectoryForNonUniqueFilenames by storedProperty(true)
|
||||
@get:OptionTag("NAVIGATE_TO_PREVIEW") var navigateToPreview by storedProperty(false)
|
||||
|
||||
private val myTreeDispatcher = ComponentTreeEventDispatcher.create(UISettingsListener::class.java)
|
||||
|
||||
@@ -162,9 +174,8 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
init {
|
||||
tweakPlatformDefaults()
|
||||
|
||||
val scrollToSource = WelcomeWizardUtil.getAutoScrollToSource()
|
||||
if (scrollToSource != null) {
|
||||
DEFAULT_AUTOSCROLL_TO_SOURCE = scrollToSource
|
||||
WelcomeWizardUtil.getAutoScrollToSource()?.let {
|
||||
defaultAutoScrollToSource = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,8 +188,8 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
// TODO[anton] consider making all IDEs use the same settings
|
||||
if (PlatformUtils.isAppCode()) {
|
||||
scrollTabLayoutInEditor = true
|
||||
ACTIVATE_RIGHT_EDITOR_ON_CLOSE = true
|
||||
SHOW_ICONS_IN_MENUS = false
|
||||
activeRigtEditorOnClose = true
|
||||
showIconsInMenus = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +226,8 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
SHOW_CLOSE_BUTTON = showCloseButton
|
||||
EDITOR_AA_TYPE = editorAAType
|
||||
PRESENTATION_MODE = presentationMode
|
||||
OVERRIDE_NONIDEA_LAF_FONTS = overrideLafFonts
|
||||
PRESENTATION_MODE_FONT_SIZE = presentationModeFontSize
|
||||
}
|
||||
|
||||
private fun initDefFont() {
|
||||
@@ -253,11 +266,11 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
}
|
||||
|
||||
// Check that alpha delay and ratio are valid
|
||||
if (ALPHA_MODE_DELAY < 0) {
|
||||
ALPHA_MODE_DELAY = 1500
|
||||
if (alphaModeDelay < 0) {
|
||||
alphaModeDelay = 1500
|
||||
}
|
||||
if (ALPHA_MODE_RATIO < 0.0f || ALPHA_MODE_RATIO > 1.0f) {
|
||||
ALPHA_MODE_RATIO = 0.5f
|
||||
if (alphaModeRatio < 0.0f || alphaModeRatio > 1.0f) {
|
||||
alphaModeRatio = 0.5f
|
||||
}
|
||||
|
||||
if (FONT_SCALE <= 0) {
|
||||
@@ -292,8 +305,8 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
|
||||
}
|
||||
}
|
||||
|
||||
if (MAX_CLIPBOARD_CONTENTS <= 0) {
|
||||
MAX_CLIPBOARD_CONTENTS = 5
|
||||
if (maxClipboardContents <= 0) {
|
||||
maxClipboardContents = 5
|
||||
}
|
||||
|
||||
fireUISettingsChanged()
|
||||
|
||||
@@ -80,14 +80,14 @@ public abstract class AnAction implements PossiblyDumbAware {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new action with its text, description and icon set to <code>null</code>.
|
||||
* Creates a new action with its text, description and icon set to {@code null}.
|
||||
*/
|
||||
public AnAction(){
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new action with <code>icon</code> provided. Its text, description set to <code>null</code>.
|
||||
* Creates a new action with {@code icon} provided. Its text, description set to {@code null}.
|
||||
*
|
||||
* @param icon Default icon to appear in toolbars and menus (Note some platform don't have icons in menu).
|
||||
*/
|
||||
@@ -97,7 +97,7 @@ public abstract class AnAction implements PossiblyDumbAware {
|
||||
|
||||
/**
|
||||
* Creates a new action with the specified text. Description and icon are
|
||||
* set to <code>null</code>.
|
||||
* set to {@code null}.
|
||||
*
|
||||
* @param text Serves as a tooltip when the presentation is a button and the name of the
|
||||
* menu item when the presentation is a menu item.
|
||||
@@ -167,12 +167,7 @@ public abstract class AnAction implements PossiblyDumbAware {
|
||||
}
|
||||
|
||||
if (parentDisposable != null) {
|
||||
Disposer.register(parentDisposable, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
unregisterCustomShortcutSet(component);
|
||||
}
|
||||
});
|
||||
Disposer.register(parentDisposable, () -> unregisterCustomShortcutSet(component));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +179,9 @@ public abstract class AnAction implements PossiblyDumbAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies template presentation and shortcuts set from <code>sourceAction</code>.
|
||||
* Copies template presentation and shortcuts set from {@code sourceAction}.
|
||||
*
|
||||
* @param sourceAction cannot be <code>null</code>
|
||||
* @param sourceAction cannot be {@code null}
|
||||
*/
|
||||
public final void copyFrom(@NotNull AnAction sourceAction){
|
||||
Presentation sourcePresentation = sourceAction.getTemplatePresentation();
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi.actionSystem;
|
||||
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -32,7 +31,7 @@ public final class CustomShortcutSet implements ShortcutSet {
|
||||
private final Shortcut[] myShortcuts;
|
||||
|
||||
/**
|
||||
* Creates <code>CustomShortcutSet</code> which contains only one
|
||||
* Creates {@code CustomShortcutSet} which contains only one
|
||||
* single stroke keyboard shortcut.
|
||||
*/
|
||||
public CustomShortcutSet(@NotNull KeyStroke keyStroke){
|
||||
@@ -40,7 +39,7 @@ public final class CustomShortcutSet implements ShortcutSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>CustomShortcutSet</code> which contains specified keyboard and
|
||||
* Creates {@code CustomShortcutSet} which contains specified keyboard and
|
||||
* mouse shortcuts.
|
||||
*
|
||||
* @param shortcuts keyboard shortcuts
|
||||
@@ -49,7 +48,7 @@ public final class CustomShortcutSet implements ShortcutSet {
|
||||
myShortcuts = shortcuts.length == 0 ? Shortcut.EMPTY_ARRAY : shortcuts.clone();
|
||||
}
|
||||
|
||||
public CustomShortcutSet(Integer... keyCodes) {
|
||||
public CustomShortcutSet(@NotNull Integer... keyCodes) {
|
||||
myShortcuts = ContainerUtil.map(keyCodes, integer -> new KeyboardShortcut(KeyStroke.getKeyStroke(integer, 0), null), Shortcut.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -137,7 +137,7 @@ public final class Presentation implements Cloneable {
|
||||
if (i >= text.length()) break;
|
||||
ch = text.charAt(i);
|
||||
if (ch != '_' && ch != '&') {
|
||||
if (UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS) {
|
||||
if (UISettings.getInstance().getDisableMnemonicsInControls()) {
|
||||
myMnemonic = 0;
|
||||
myDisplayedMnemonicIndex = -1;
|
||||
}
|
||||
|
||||
+3
-2
@@ -219,9 +219,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
|
||||
@Override
|
||||
public Font getFont(EditorFontType key) {
|
||||
if (UISettings.getInstance().getPresentationMode()) {
|
||||
UISettings uiSettings = UISettings.getInstance();
|
||||
if (uiSettings.getPresentationMode()) {
|
||||
final Font font = myFonts.get(key);
|
||||
return new Font(font.getName(), font.getStyle(), UISettings.getInstance().PRESENTATION_MODE_FONT_SIZE);
|
||||
return new Font(font.getName(), font.getStyle(), uiSettings.getPresentationModeFontSize());
|
||||
}
|
||||
return myFonts.get(key);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Action for grouping items in a runtime dashboard tree.
|
||||
* Action for grouping items in a run dashboard tree.
|
||||
*
|
||||
* @author konstantin.aleev
|
||||
*/
|
||||
public interface DashboardGroupingRule extends TreeAction {
|
||||
ExtensionPointName<DashboardGroupingRule> EP_NAME = ExtensionPointName.create("com.intellij.runtimeDashboardGroupingRule");
|
||||
ExtensionPointName<DashboardGroupingRule> EP_NAME = ExtensionPointName.create("com.intellij.runDashboardGroupingRule");
|
||||
|
||||
Comparator<DashboardGroupingRule> PRIORITY_COMPARATOR = (o1, o2) -> {
|
||||
final int res = o2.getPriority() - o1.getPriority();
|
||||
|
||||
+3
-3
@@ -25,11 +25,11 @@ import javax.swing.*;
|
||||
*/
|
||||
public class DashboardRunConfigurationStatus {
|
||||
public static final DashboardRunConfigurationStatus STARTED = new DashboardRunConfigurationStatus(
|
||||
ExecutionBundle.message("runtime.dashboard.started.group.name"), AllIcons.Toolwindows.ToolWindowRun);
|
||||
ExecutionBundle.message("run.dashboard.started.group.name"), AllIcons.Toolwindows.ToolWindowRun);
|
||||
public static final DashboardRunConfigurationStatus STOPPED = new DashboardRunConfigurationStatus(
|
||||
ExecutionBundle.message("runtime.dashboard.stopped.group.name"), AllIcons.Actions.Suspend);
|
||||
ExecutionBundle.message("run.dashboard.stopped.group.name"), AllIcons.Actions.Suspend);
|
||||
public static final DashboardRunConfigurationStatus FAILED = new DashboardRunConfigurationStatus(
|
||||
ExecutionBundle.message("runtime.dashboard.failed.group.name"), AllIcons.General.Error);
|
||||
ExecutionBundle.message("run.dashboard.failed.group.name"), AllIcons.General.Error);
|
||||
|
||||
private final String myName;
|
||||
private final Icon myIcon;
|
||||
|
||||
+7
-7
@@ -24,18 +24,18 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* In order to show run configurations of the specific configuration type in Runtime Dashboard tool window,
|
||||
* In order to show run configurations of the specific configuration type in Run Dashboard tool window,
|
||||
* one should register this extension.
|
||||
*
|
||||
* @author konstantin.aleev
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public abstract class RuntimeDashboardContributor {
|
||||
public static final ExtensionPointName<RuntimeDashboardContributor> EP_NAME = ExtensionPointName.create("com.intellij.runtimeDashboardContributor");
|
||||
public abstract class RunDashboardContributor {
|
||||
public static final ExtensionPointName<RunDashboardContributor> EP_NAME = ExtensionPointName.create("com.intellij.runDashboardContributor");
|
||||
|
||||
private final ConfigurationType myType;
|
||||
|
||||
protected RuntimeDashboardContributor(ConfigurationType type) {
|
||||
protected RunDashboardContributor(ConfigurationType type) {
|
||||
myType = type;
|
||||
}
|
||||
|
||||
@@ -74,13 +74,13 @@ public abstract class RuntimeDashboardContributor {
|
||||
return DashboardRunConfigurationStatus.FAILED;
|
||||
}
|
||||
|
||||
public static RuntimeDashboardContributor getContributor(ConfigurationType type) {
|
||||
if (!Registry.is("ide.runtime.dashboard")) {
|
||||
public static RunDashboardContributor getContributor(ConfigurationType type) {
|
||||
if (!Registry.is("ide.run.dashboard")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
for (RuntimeDashboardContributor contributor : EP_NAME.getExtensions()) {
|
||||
for (RunDashboardContributor contributor : EP_NAME.getExtensions()) {
|
||||
if (type.equals(contributor.getType())) {
|
||||
return contributor;
|
||||
}
|
||||
+4
-4
@@ -25,12 +25,12 @@ import javax.swing.*;
|
||||
/**
|
||||
* @author konstantin.aleev
|
||||
*/
|
||||
public interface RuntimeDashboardManager {
|
||||
public interface RunDashboardManager {
|
||||
Topic<DashboardListener> DASHBOARD_TOPIC =
|
||||
Topic.create("runtime dashboard", DashboardListener.class, Topic.BroadcastDirection.TO_PARENT);
|
||||
Topic.create("run dashboard", DashboardListener.class, Topic.BroadcastDirection.TO_PARENT);
|
||||
|
||||
static RuntimeDashboardManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, RuntimeDashboardManager.class);
|
||||
static RunDashboardManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, RunDashboardManager.class);
|
||||
}
|
||||
|
||||
ContentManager getDashboardContentManager();
|
||||
@@ -71,7 +71,7 @@
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="51007" class="javax.swing.JLabel">
|
||||
<component id="51007" class="javax.swing.JLabel" binding="myAutoInsertLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
@@ -156,9 +156,6 @@
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<clientProperties>
|
||||
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
|
||||
</clientProperties>
|
||||
<border type="none" title-resource-bundle="messages/ApplicationBundle" title-key="title.parameter.info"/>
|
||||
<children>
|
||||
<component id="c7fb5" class="javax.swing.JCheckBox" binding="myCbParameterInfoPopup">
|
||||
|
||||
@@ -43,6 +43,7 @@ public class CodeCompletionPanel {
|
||||
private JCheckBox myCbAutopopupJavaDoc;
|
||||
private JTextField myAutopopupJavaDocField;
|
||||
|
||||
private JLabel myAutoInsertLabel;
|
||||
private JCheckBox myCbOnCodeCompletion;
|
||||
private JCheckBox myCbOnSmartTypeCompletion;
|
||||
|
||||
@@ -101,6 +102,9 @@ public class CodeCompletionPanel {
|
||||
);
|
||||
|
||||
hideOption(myCbOnSmartTypeCompletion, OptionId.COMPLETION_SMART_TYPE);
|
||||
hideOption(myCbOnCodeCompletion, OptionId.AUTOCOMPLETE_ON_BASIC_CODE_COMPLETION);
|
||||
if(!myCbOnSmartTypeCompletion.isVisible() && !myCbOnCodeCompletion.isVisible())
|
||||
myAutoInsertLabel.setVisible(false);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user