diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 3edcc63abd3c..2fbced0c112b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -272,7 +272,8 @@ public class StandardInstructionVisitor extends InstructionVisitor { if (methodType == MethodCallInstruction.MethodType.CAST) { if (qualifierValue instanceof DfaConstValue) { - return factory.getConstFactory().createFromValue(castConstValue((DfaConstValue)qualifierValue), type, ((DfaConstValue)qualifierValue).getConstant()); + Object casted = TypeConversionUtil.computeCastTo(((DfaConstValue)qualifierValue).getValue(), type); + return factory.getConstFactory().createFromValue(casted, type, ((DfaConstValue)qualifierValue).getConstant()); } return qualifierValue; } @@ -283,19 +284,6 @@ public class StandardInstructionVisitor extends InstructionVisitor { return DfaUnknownValue.getInstance(); } - private static Object castConstValue(DfaConstValue constValue) { - Object o = constValue.getValue(); - if (o instanceof Double || o instanceof Float) { - double dbVal = o instanceof Double ? ((Double)o).doubleValue() : ((Float)o).doubleValue(); - // 5.0f == 5 - if (Math.floor(dbVal) != dbVal) { - return o; - } - } - - return TypeConversionUtil.computeCastTo(o, PsiType.LONG); - } - protected boolean checkNotNullable(DfaMemoryState state, DfaValue value, NullabilityProblem problem, PsiElement anchor) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FloatEquality.java b/java/java-tests/testData/inspection/dataFlow/fixture/FloatEquality.java new file mode 100644 index 000000000000..62b1f980e337 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FloatEquality.java @@ -0,0 +1,7 @@ +class Fun { + public static void main(String[] args) throws Exception { + float f = 1f; + int x = f == 1f ? 1 : 2; + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 22407dc7f661..e9bc54b2d5ce 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -182,6 +182,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testMethodCallFlushesField() { doTest(); } public void testUnknownFloatMayBeNaN() { doTest(); } + public void testFloatEquality() { doTest(); } public void testLastConstantConditionInAnd() { doTest(); } public void testTransientFinalField() { doTest(); } diff --git a/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java b/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java index 83ebd0d28942..1a8828aaa92d 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java +++ b/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java @@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,11 +27,13 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +@SuppressWarnings("ForLoopReplaceableByForEach") public class CompositeFilter implements Filter, FilterMixin { private static final Logger LOG = Logger.getInstance(CompositeFilter.class); private final List myFilters = new ArrayList(); private boolean myIsAnyHeavy; + private boolean forceUseAllFilters = true; private final DumbService myDumbService; public CompositeFilter(@NotNull Project project) { @@ -47,53 +50,78 @@ public class CompositeFilter implements Filter, FilterMixin { final boolean dumb = myDumbService.isDumb(); List filters = myFilters; int count = filters.size(); - //noinspection ForLoopReplaceableByForEach - Result finalResult = null; + + List resultItems = null; for (int i = 0; i < count; i++) { Filter filter = filters.get(i); if (!dumb || DumbService.isDumbAware(filter)) { long t0 = System.currentTimeMillis(); - Result result = null; + + Result result; try { result = filter.applyFilter(line, entireLength); } catch (Throwable t) { - throw new RuntimeException("Error while applying " + filter + " to '"+line+"'", t); + throw new RuntimeException("Error while applying " + filter + " to '" + line + "'", t); } - finalResult = merge(finalResult, result); + resultItems = merge(resultItems, result); + t0 = System.currentTimeMillis() - t0; if (t0 > 1000) { LOG.warn(filter.getClass().getSimpleName() + ".applyFilter() took " + t0 + " ms on '''" + line + "'''"); } - if (finalResult != null && finalResult.getNextAction() == NextAction.EXIT) { - return finalResult; + if (shouldStopFiltering(result)) { + break; } } } - return finalResult; + return createFinalResult(resultItems); } - protected Result merge(@Nullable Result finalResult, @Nullable Result result) { - if (result != null) { - if (finalResult == null) { - finalResult = result; + @Nullable + private static Result createFinalResult(@Nullable List resultItems) { + if (resultItems == null) { + return null; + } + return new Result(resultItems); + } + + private boolean shouldStopFiltering(@Nullable Result result) { + return result != null && result.getNextAction() == NextAction.EXIT && !forceUseAllFilters; + } + + @Nullable + protected List merge(@Nullable List resultItems, @Nullable Result newResult) { + if (newResult != null) { + if (resultItems == null) { + resultItems = new ArrayList(); } - else { - finalResult = new Result(mergeResultItems(finalResult, result)); - finalResult.setNextAction(result.getNextAction()); + List newItems = newResult.getResultItems(); + for (int i = 0; i < newItems.size(); i++) { + ResultItem item = newItems.get(i); + if (item.hyperlinkInfo == null || !intersects(resultItems, item)) { + resultItems.add(item); + } } } - return finalResult; + return resultItems; } - private List mergeResultItems(Result finalResult, Result result) { - List finalResultResultItems = finalResult.getResultItems(); - List resultItems = result.getResultItems(); + protected boolean intersects(List items, ResultItem newItem) { + TextRange newItemTextRange = null; - List mergedList = new ArrayList(finalResultResultItems.size() + resultItems.size()); - mergedList.addAll(finalResultResultItems); - mergedList.addAll(resultItems); - return mergedList; + for (int i = 0; i < items.size(); i++) { + ResultItem item = items.get(i); + if (item.hyperlinkInfo != null) { + if (newItemTextRange == null) { + newItemTextRange = new TextRange(newItem.highlightStartOffset, newItem.highlightEndOffset); + } + if (newItemTextRange.intersectsStrict(item.highlightStartOffset, item.highlightEndOffset)) { + return true; + } + } + } + return false; } @Override @@ -109,12 +137,12 @@ public class CompositeFilter implements Filter, FilterMixin { final boolean dumb = myDumbService.isDumb(); List filters = myFilters; int count = filters.size(); - //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < count; i++) { Filter filter = filters.get(i); - if (! (filter instanceof FilterMixin) || !((FilterMixin)filter).shouldRunHeavy()) continue; + if (!(filter instanceof FilterMixin) || !((FilterMixin)filter).shouldRunHeavy()) continue; if (!dumb || DumbService.isDumbAware(filter)) { - ((FilterMixin) filter).applyHeavyFilter(copiedFragment, startOffset, startLineNumber, consumer); + ((FilterMixin)filter).applyHeavyFilter(copiedFragment, startOffset, startLineNumber, consumer); } } } @@ -125,7 +153,7 @@ public class CompositeFilter implements Filter, FilterMixin { List filters = myFilters; final List updateMessage = new ArrayList(); int count = filters.size(); - //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < count; i++) { Filter filter = filters.get(i); @@ -149,4 +177,9 @@ public class CompositeFilter implements Filter, FilterMixin { myFilters.add(filter); myIsAnyHeavy |= filter instanceof FilterMixin; } + + public void setForceUseAllFilters(boolean forceUseAllFilters) { + this.forceUseAllFilters = forceUseAllFilters; + } + } diff --git a/platform/lang-api/src/com/intellij/execution/filters/Filter.java b/platform/lang-api/src/com/intellij/execution/filters/Filter.java index 06dfbadc79fb..1e375acaeb8c 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/Filter.java +++ b/platform/lang-api/src/com/intellij/execution/filters/Filter.java @@ -32,7 +32,7 @@ public interface Filter { class Result extends ResultItem { protected NextAction myNextAction = NextAction.EXIT; - protected List myResultItems; + protected final List myResultItems; public Result(final int highlightStartOffset, final int highlightEndOffset, final HyperlinkInfo hyperlinkInfo) { this(highlightStartOffset, highlightEndOffset, hyperlinkInfo, null); @@ -40,6 +40,7 @@ public interface Filter { public Result(final int highlightStartOffset, final int highlightEndOffset, final HyperlinkInfo hyperlinkInfo, final TextAttributes highlightAttributes) { super(highlightStartOffset, highlightEndOffset, hyperlinkInfo, highlightAttributes); + myResultItems = null; } public Result(@NotNull List resultItems) { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 58200941b385..5fc2fe2cccea 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -249,8 +249,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo private final Set myCurrentRequests = new HashSet(); - protected final CompositeFilter myPredefinedMessageFilter; - protected final CompositeFilter myCustomFilter; + protected final CompositeFilter myFilters; @Nullable private final InputFilter myInputMessageFilter; @@ -287,20 +286,19 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myPsiDisposedCheck = new DisposedPsiManagerCheck(project); myProject = project; - myCustomFilter = new CompositeFilter(project); - myPredefinedMessageFilter = new CompositeFilter(project); + myFilters = new CompositeFilter(project); if (usePredefinedMessageFilter) { for (ConsoleFilterProvider eachProvider : Extensions.getExtensions(ConsoleFilterProvider.FILTER_PROVIDERS)) { Filter[] filters = eachProvider instanceof ConsoleFilterProviderEx ? ((ConsoleFilterProviderEx)eachProvider).getDefaultFilters(project, searchScope) : eachProvider.getDefaultFilters(project); for (Filter filter : filters) { - myPredefinedMessageFilter.addFilter(filter); + myFilters.addFilter(filter); } } } myHeavyUpdateTicket = 0; - myHeavyAlarm = myPredefinedMessageFilter.isAnyHeavy() ? new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this) : null; + myHeavyAlarm = myFilters.isAnyHeavy() ? new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this) : null; ConsoleInputFilterProvider[] inputFilters = Extensions.getExtensions(ConsoleInputFilterProvider.INPUT_FILTER_PROVIDERS); @@ -475,7 +473,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo public JComponent getComponent() { if (myMainPanel == null) { myMainPanel = new JPanel(new BorderLayout()); - myJLayeredPane = new MyDiffContainer(myMainPanel, myPredefinedMessageFilter.getUpdateMessage()); + myJLayeredPane = new MyDiffContainer(myMainPanel, myFilters.getUpdateMessage()); Disposer.register(this, myJLayeredPane); add(myJLayeredPane, BorderLayout.CENTER); } @@ -846,7 +844,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo @Override public void addMessageFilter(final Filter filter) { - myCustomFilter.addFilter(filter); + myFilters.addFilter(filter); } @Override @@ -965,7 +963,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo } private void highlightHyperlinksAndFoldings(RangeMarker lastProcessedOutput) { - boolean canHighlightHyperlinks = !myCustomFilter.isEmpty() || !myPredefinedMessageFilter.isEmpty(); + boolean canHighlightHyperlinks = !myFilters.isEmpty() || !myFilters.isEmpty(); if (!canHighlightHyperlinks && myUpdateFoldingsEnabled) { return; @@ -976,10 +974,10 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo ApplicationManager.getApplication().assertIsDispatchThread(); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); if (canHighlightHyperlinks) { - myHyperlinks.highlightHyperlinks(myCustomFilter, myPredefinedMessageFilter, line1, endLine); + myHyperlinks.highlightHyperlinks(myFilters, line1, endLine); } - if (myAllowHeavyFilters && myPredefinedMessageFilter.isAnyHeavy() && myPredefinedMessageFilter.shouldRunHeavy()) { + if (myAllowHeavyFilters && myFilters.isAnyHeavy() && myFilters.shouldRunHeavy()) { runHeavyFilters(line1, endLine); } if (myUpdateFoldingsEnabled) { @@ -1002,9 +1000,9 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myHeavyAlarm.addRequest(new Runnable() { @Override public void run() { - if (! myPredefinedMessageFilter.shouldRunHeavy()) return; + if (!myFilters.shouldRunHeavy()) return; try { - myPredefinedMessageFilter.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer() { + myFilters.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer() { @Override public void consume(final FilterMixin.AdditionalHighlight additionalHighlight) { if (myFlushAlarm.isDisposed()) return; diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index 8a2e67119c63..d99a38c199b4 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -239,7 +239,19 @@ public class EditorHyperlinkSupport { return getHyperlinkInfoByLineAndCol(pos.line, pos.column); } + @Deprecated public void highlightHyperlinks(final Filter customFilter, final Filter predefinedMessageFilter, final int line1, final int endLine) { + highlightHyperlinks(new Filter() { + @Nullable + @Override + public Result applyFilter(String line, int entireLength) { + Result result = customFilter.applyFilter(line, entireLength); + return result != null ? result : predefinedMessageFilter.applyFilter(line, entireLength); + } + }, line1, endLine); + } + + public void highlightHyperlinks(final Filter customFilter, final int line1, final int endLine) { final Document document = myEditor.getDocument(); final int startLine = Math.max(0, line1); @@ -251,9 +263,6 @@ public class EditorHyperlinkSupport { } final String text = getLineText(document, line, true); Filter.Result result = customFilter.applyFilter(text, endOffset); - if (result == null) { - result = predefinedMessageFilter.applyFilter(text, endOffset); - } if (result != null) { for (Filter.ResultItem resultItem : result.getResultItems()) { if (resultItem.hyperlinkInfo != null) { diff --git a/platform/platform-tests/testSrc/com/intellij/execution/filters/CompositeFilterTest.java b/platform/platform-tests/testSrc/com/intellij/execution/filters/CompositeFilterTest.java index d9ae0bbadb9e..037f2288c541 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/filters/CompositeFilterTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/filters/CompositeFilterTest.java @@ -16,7 +16,7 @@ package com.intellij.execution.filters; import com.intellij.mock.MockDumbService; -import junit.framework.Assert; +import org.junit.Assert; import org.jetbrains.annotations.Nullable; import org.junit.Before; import org.junit.Test; @@ -30,6 +30,7 @@ public class CompositeFilterTest { @Before public void setUp() throws Exception { myCompositeFilter = new CompositeFilter(new MockDumbService(null)); + myCompositeFilter.setForceUseAllFilters(false); } @Test @@ -55,6 +56,9 @@ public class CompositeFilterTest { myCompositeFilter.addFilter(returnResultFilter()); notNullResultOfSize(applyFilter(), 3); + myCompositeFilter.setForceUseAllFilters(true); + notNullResultOfSize(applyFilter(), 4); + } @Test @@ -73,7 +77,7 @@ public class CompositeFilterTest { return myCompositeFilter.applyFilter("foo\n", 10); } - private void notNullResultOfSize(Filter.Result object, int expected) { + private static void notNullResultOfSize(Filter.Result object, int expected) { Assert.assertNotNull(object); List resultItems = object.getResultItems(); Assert.assertEquals(expected, resultItems.size()); @@ -83,7 +87,8 @@ public class CompositeFilterTest { } } - private Filter throwSOEFilter() { + private static Filter throwSOEFilter() { + //noinspection InfiniteRecursion return new Filter() { @Nullable @Override @@ -93,7 +98,7 @@ public class CompositeFilterTest { }; } - private Filter returnNullFilter() { + private static Filter returnNullFilter() { return new Filter() { @Nullable @Override @@ -103,7 +108,7 @@ public class CompositeFilterTest { }; } - private Filter returnResultFilter() { + private static Filter returnResultFilter() { return new Filter() { @Nullable @Override @@ -113,7 +118,7 @@ public class CompositeFilterTest { }; } - private Filter returnContinuingResultFilter() { + private static Filter returnContinuingResultFilter() { return new Filter() { @Nullable @Override @@ -125,7 +130,7 @@ public class CompositeFilterTest { }; } - private Filter.Result createResult() { + private static Filter.Result createResult() { return new Filter.Result(1, 1, null, null); } -} +} \ No newline at end of file