diff --git a/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/after.java.template b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/after.java.template
new file mode 100644
index 000000000000..9835666b9f27
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/after.java.template
@@ -0,0 +1,5 @@
+public class X {
+ void f() {
+ int i = 0x5;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/before.java.template b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/before.java.template
new file mode 100644
index 000000000000..48bfb8cf83ff
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/before.java.template
@@ -0,0 +1,5 @@
+public class X {
+ void f() {
+ int i = 5;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/description.html b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/description.html
new file mode 100644
index 000000000000..74844ff47554
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/JavaNumberConversionIntention/description.html
@@ -0,0 +1,5 @@
+
+
+Converts number to different base or notation (e.g. decimal to hex or scientific notation to plain).
+
+
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/AbstractNumberConversionIntention.java b/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/AbstractNumberConversionIntention.java
new file mode 100644
index 000000000000..b9768fa6f8f8
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/AbstractNumberConversionIntention.java
@@ -0,0 +1,199 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.codeInsight.intention.numeric;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.SmartPsiElementPointer;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public abstract class AbstractNumberConversionIntention implements IntentionAction {
+ private static final String TITLE = "Convert number to...";
+ private String myText;
+ private NumberConverter myConverter;
+ private NumberConversionContext myContext;
+
+ @Nls(capitalization = Nls.Capitalization.Sentence)
+ @NotNull
+ @Override
+ public String getText() {
+ return myText == null ? TITLE : myText;
+ }
+
+ @Nls(capitalization = Nls.Capitalization.Sentence)
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Convert number";
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ myText = null;
+ myConverter = null;
+ myContext = null;
+ List converters = getConverters(file);
+ if (converters.isEmpty()) return false;
+ int offset = editor.getCaretModel().getOffset();
+ myContext = getContext(file, offset);
+ if (myContext == null && offset > 0) {
+ myContext = getContext(file, offset - 1);
+ }
+ if (myContext == null) return false;
+ Number number = myContext.myNumber;
+ String text = myContext.myText;
+ NumberConverter singleConverter = null;
+ for (NumberConverter converter : converters) {
+ String convertedText = converter.getConvertedText(text, number);
+ if (convertedText != null) {
+ if (singleConverter != null) return true;
+ singleConverter = converter;
+ }
+ }
+ if (singleConverter == null) return false;
+ String convertedText = singleConverter.getConvertedText(text, number);
+ myText = getActionName(singleConverter, convertedText);
+ myConverter = singleConverter;
+ return true;
+ }
+
+ @Nullable
+ public NumberConversionContext getContext(PsiFile file, int offset) {
+ PsiElement element = file.findElementAt(offset);
+ return element == null ? null : extract(element);
+ }
+
+ public String getActionName(NumberConverter converter, String convertedText) {
+ return String.format("Convert number to %s (%s)", converter, convertedText);
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ if (myContext == null) return;
+ Number number = myContext.myNumber;
+ String text = myContext.myText;
+ class Conversion {
+ final NumberConverter myConverter;
+ final String myResult;
+
+ Conversion(NumberConverter converter, String result) {
+ myConverter = converter;
+ myResult = result;
+ }
+
+ void convert() {
+ WriteCommandAction.runWriteCommandAction(project, getActionName(myConverter, myResult), null, () -> {
+ PsiElement element = myContext.getElement();
+ if (element != null) {
+ replace(element, myResult);
+ }
+ }, file);
+ }
+
+ @Override
+ public String toString() {
+ return StringUtil.capitalize(myConverter.toString()) + " (" + myResult + ")";
+ }
+ }
+ List list = getConverters(file).stream()
+ .map(converter -> new Conversion(converter, converter.getConvertedText(text, number)))
+ .filter(conversion -> conversion.myResult != null)
+ .collect(Collectors.toList());
+ if (myConverter != null) {
+ list.stream().filter(c -> c.myConverter.equals(myConverter)).findFirst().ifPresent(Conversion::convert);
+ // For some reason preselected conversion is not available anymore: do nothing
+ return;
+ }
+ JBPopup popup = JBPopupFactory.getInstance().createPopupChooserBuilder(list)
+ .setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
+ .setAccessibleName(TITLE)
+ .setTitle(StringUtil.wordsToBeginFromUpperCase(TITLE))
+ .setMovable(false)
+ .setResizable(false)
+ .setRequestFocus(true)
+ .setItemChosenCallback(Conversion::convert)
+ .createPopup();
+ popup.showInBestPositionFor(editor);
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return false;
+ }
+
+ /**
+ * Extract conversion context from given PsiElement
+ * @param element an element to extract the context from
+ * @return extracted context or null if given element is not a number which could be converted.
+ */
+ @Nullable
+ @Contract(pure = true)
+ protected abstract NumberConversionContext extract(@NotNull PsiElement element);
+
+ /**
+ * Returns list of converters which are applicable to given file
+ *
+ * @param file file to find relevant converters
+ * @return list of converters for given PsiFile
+ */
+ @NotNull
+ @Contract(pure = true)
+ protected abstract List getConverters(@NotNull PsiFile file);
+
+ /**
+ * Performs a replacement of given source number with the conversion result.
+ *
+ * @param sourceElement element to replace (previously returned by extract in {@link NumberConversionContext}).
+ * @param replacement replacement text
+ */
+ protected abstract void replace(PsiElement sourceElement, String replacement);
+
+ /**
+ * A context for number conversion
+ */
+ protected static class NumberConversionContext {
+ /**
+ * An element which represents a number to be converted
+ */
+ @NotNull final SmartPsiElementPointer myElement;
+ /**
+ * A value of that number
+ */
+ @NotNull final Number myNumber;
+ /**
+ * A textual representation of the number
+ */
+ @NotNull final String myText;
+ /**
+ * Whether there's a separate negation (unary minus) applied to the number. If true, {@link #myText} doesn't include that negation,
+ * but {@link #myNumber} is properly negated and {@link #myElement} points to the unary minus expression.
+ */
+ final boolean myNegated;
+
+ public NumberConversionContext(@NotNull PsiElement element, @NotNull Number number, @NotNull String text, boolean negated) {
+ myElement = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element);
+ myNumber = number;
+ myText = text;
+ myNegated = negated;
+ }
+
+ PsiElement getElement() {
+ return myElement.getElement();
+ }
+ }
+}
diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/NumberConverter.java b/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/NumberConverter.java
new file mode 100644
index 000000000000..546a385891b8
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/codeInsight/intention/numeric/NumberConverter.java
@@ -0,0 +1,29 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.codeInsight.intention.numeric;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * An algorithm to convert a number to different representation while preserving its value
+ * (e.g. decimal to hex).
+ * @see AbstractNumberConversionIntention
+ */
+public interface NumberConverter {
+ /**
+ * Converts the supplied number to another representation
+ * @param text original textual representation of the number (unary minus could be omitted for negative numbers)
+ * @param number numeric value of the number
+ * @return the converted number or null if given number cannot be converted
+ */
+ @Nullable
+ @Contract(pure = true)
+ String getConvertedText(@NotNull String text, @NotNull Number number);
+
+ /**
+ * @return textual representation of this converter in lowercase (e.g. "hex" for converter which converts a number to hex).
+ */
+ @Override
+ String toString();
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
index b617c34863f0..20b4788ef3b4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
@@ -1035,11 +1035,14 @@ public class ExpressionUtils {
// red code
return false;
}
- @NonNls final String text = literal.getText();
- if (text.charAt(0) != '0' || text.length() < 2) {
+ return isOctalLiteralText(literal.getText());
+ }
+
+ public static boolean isOctalLiteralText(String literalText) {
+ if (literalText.charAt(0) != '0' || literalText.length() < 2) {
return false;
}
- final char c1 = text.charAt(1);
+ final char c1 = literalText.charAt(1);
return c1 == '_' || (c1 >= '0' && c1 <= '7');
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/JavaPsiMathUtil.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/JavaPsiMathUtil.java
index 6524bf39ab65..d035c1342ab2 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/JavaPsiMathUtil.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/JavaPsiMathUtil.java
@@ -177,8 +177,13 @@ public class JavaPsiMathUtil {
return null;
}
+ /**
+ * Negate given number of type Integer, Long, Double or Float, preserving the original type
+ * @param value number to negate
+ * @return negated number; null if supplied value is not supported.
+ */
@Nullable
- private static Number negate(Object value) {
+ public static Number negate(Object value) {
if (value instanceof Integer) {
return -((Integer)value).intValue();
}
diff --git a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
index 64f3bac38247..cbeb53a22de5 100644
--- a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
+++ b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
@@ -11,37 +11,7 @@
- com.siyeh.ipp.integer.ConvertIntegerToDecimalIntention
- com.siyeh.IntentionPowerPackBundle
- intention.category.numbers
-
-
-
- com.siyeh.ipp.integer.ConvertIntegerToHexIntention
- com.siyeh.IntentionPowerPackBundle
- intention.category.numbers
-
-
-
- com.siyeh.ipp.integer.ConvertToScientificNotationIntention
- com.siyeh.IntentionPowerPackBundle
- intention.category.numbers
-
-
-
- com.siyeh.ipp.integer.ConvertToPlainIntention
- com.siyeh.IntentionPowerPackBundle
- intention.category.numbers
-
-
-
- com.siyeh.ipp.integer.ConvertIntegerToOctalIntention
- com.siyeh.IntentionPowerPackBundle
- intention.category.numbers
-
-
-
- com.siyeh.ipp.integer.ConvertIntegerToBinaryIntention
+ com.siyeh.ipp.integer.JavaNumberConversionIntention
com.siyeh.IntentionPowerPackBundle
intention.category.numbers
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryIntention.java
deleted file mode 100644
index e7368c50fbcc..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryIntention.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2000-2011 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-public class ConvertIntegerToBinaryIntention extends ConvertNumberIntentionBase {
- @Override
- @NotNull
- public PsiElementPredicate getElementPredicate() {
- return new ConvertIntegerToBinaryPredicate();
- }
-
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- if (PsiType.INT.equals(type)) {
- final int intValue = negated ? -value.intValue() : value.intValue();
- return "0b" + Integer.toBinaryString(intValue);
- }
- else if (PsiType.LONG.equals(type)) {
- final long longValue = negated ? -value.longValue() : value.longValue();
- return "0b" + Long.toBinaryString(longValue) + "L";
- }
-
- return null;
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryPredicate.java
deleted file mode 100644
index b78ccad0690f..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToBinaryPredicate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.intellij.psi.util.PsiUtil;
-import com.siyeh.ipp.base.PsiElementPredicate;
-
-class ConvertIntegerToBinaryPredicate implements PsiElementPredicate {
- @Override
- public boolean satisfiedBy(final PsiElement element) {
- if (!(element instanceof PsiLiteralExpression) || !PsiUtil.isLanguageLevel7OrHigher(element)) {
- return false;
- }
-
- final PsiLiteralExpression literalExpression = (PsiLiteralExpression)element;
- if (literalExpression.getValue() == null) {
- return false;
- }
- final PsiType type = literalExpression.getType();
- if (!PsiType.INT.equals(type) && !PsiType.LONG.equals(type)) {
- return false;
- }
- final String text = element.getText();
- return !(text.startsWith("0b") || text.startsWith("0B"));
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalIntention.java
deleted file mode 100644
index 78e06245ec31..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalIntention.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-public class ConvertIntegerToDecimalIntention extends ConvertNumberIntentionBase {
- @Override
- @NotNull
- public PsiElementPredicate getElementPredicate() {
- return new ConvertIntegerToDecimalPredicate();
- }
-
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- if (PsiType.INT.equals(type)) {
- final int intValue = negated ? -value.intValue() : value.intValue();
- return Integer.toString(intValue);
- }
- else if (PsiType.LONG.equals(type)) {
- final long longValue = negated ? -value.longValue() : value.longValue();
- return longValue + "L";
- }
- else if (PsiType.FLOAT.equals(type)) {
- final float floatValue = negated ? -value.floatValue() : value.floatValue();
- return Float.toString(floatValue) + 'f';
- }
- else if (PsiType.DOUBLE.equals(type)) {
- final double doubleValue = negated ? -value.doubleValue() : value.doubleValue();
- return Double.toString(doubleValue);
- }
-
- return null;
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalPredicate.java
deleted file mode 100644
index b3a6709583b1..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToDecimalPredicate.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NonNls;
-
-class ConvertIntegerToDecimalPredicate implements PsiElementPredicate {
-
- @Override
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiLiteralExpression)) {
- return false;
- }
- final PsiLiteralExpression expression = (PsiLiteralExpression)element;
- if (expression.getValue() == null) {
- return false;
- }
- final PsiType type = expression.getType();
- @NonNls final String text = expression.getText();
- if (text.length() < 2) {
- return false;
- }
- if (PsiType.INT.equals(type) || PsiType.LONG.equals(type)) {
- if ("0L".equals(text) || "0l".equals(text)) {
- return false;
- }
- return text.charAt(0) == '0';
- }
- if (PsiType.DOUBLE.equals(type) || PsiType.FLOAT.equals(type)) {
- return text.startsWith("0x") || text.startsWith("0X");
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexIntention.java
deleted file mode 100644
index abe0f363bbfd..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexIntention.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-public class ConvertIntegerToHexIntention extends ConvertNumberIntentionBase {
- @Override
- @NotNull
- public PsiElementPredicate getElementPredicate() {
- return new ConvertIntegerToHexPredicate();
- }
-
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- if (PsiType.INT.equals(type)) {
- final int intValue = negated ? -value.intValue() : value.intValue();
- return "0x" + Integer.toHexString(intValue);
- }
- else if (PsiType.LONG.equals(type)) {
- final long longValue = negated ? -value.longValue() : value.longValue();
- return "0x" + Long.toHexString(longValue) + "L";
- }
- else if (PsiType.FLOAT.equals(type)) {
- final float floatValue = negated ? -value.floatValue() : value.floatValue();
- return Float.toHexString(floatValue) + 'f';
- }
- else if (PsiType.DOUBLE.equals(type)) {
- final double doubleValue = negated ? -value.doubleValue() : value.doubleValue();
- return Double.toHexString(doubleValue);
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexPredicate.java
deleted file mode 100644
index 0d0a5111bb0d..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToHexPredicate.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.intellij.psi.util.PsiUtil;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NonNls;
-
-class ConvertIntegerToHexPredicate implements PsiElementPredicate {
-
- @Override
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiLiteralExpression)) {
- return false;
- }
- final PsiLiteralExpression expression = (PsiLiteralExpression)element;
- if (expression.getValue() == null) {
- return false;
- }
- final PsiType type = expression.getType();
- @NonNls final String text = expression.getText();
- if (PsiType.INT.equals(type) || PsiType.LONG.equals(type)) {
- return !text.startsWith("0x") && !text.startsWith("0X");
- }
- if (PsiType.DOUBLE.equals(type) || PsiType.FLOAT.equals(type)) {
- if (!PsiUtil.isLanguageLevel5OrHigher(expression)) {
- return false;
- }
- return !text.startsWith("0x") && !text.startsWith("0X");
- }
- return false;
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalIntention.java
deleted file mode 100644
index 3fe49da952bc..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalIntention.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2003-2008 Dave Griffith, Bsa Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-public class ConvertIntegerToOctalIntention extends ConvertNumberIntentionBase {
- @Override
- @NotNull
- public PsiElementPredicate getElementPredicate() {
- return new ConvertIntegerToOctalPredicate();
- }
-
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- if (PsiType.INT.equals(type)) {
- final int intValue = negated ? -value.intValue() : value.intValue();
- return "0" + Integer.toOctalString(intValue);
- }
- else if (PsiType.LONG.equals(type)) {
- final long longValue = negated ? -value.longValue() : value.longValue();
- return "0" + Long.toOctalString(longValue) + "L";
- }
-
- return null;
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalPredicate.java
deleted file mode 100644
index 491d0707524d..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertIntegerToOctalPredicate.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.siyeh.ig.psiutils.ExpressionUtils;
-import com.siyeh.ipp.base.PsiElementPredicate;
-
-class ConvertIntegerToOctalPredicate implements PsiElementPredicate {
-
- @Override
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiLiteralExpression)) {
- return false;
- }
- final PsiLiteralExpression expression = (PsiLiteralExpression)element;
- if (expression.getValue() == null) {
- return false;
- }
- final PsiType type = expression.getType();
- if (!(PsiType.INT.equals(type) || PsiType.LONG.equals(type))) {
- return false;
- }
- return !ExpressionUtils.isOctalLiteral(expression);
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java
deleted file mode 100644
index dde7732cb11b..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
- */
-package com.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiExpression;
-import com.intellij.psi.PsiType;
-import com.siyeh.ig.PsiReplacementUtil;
-import com.siyeh.ig.psiutils.CommentTracker;
-import com.siyeh.ig.psiutils.ExpressionUtils;
-import com.siyeh.ipp.base.Intention;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public abstract class ConvertNumberIntentionBase extends Intention {
- @Override
- protected void processIntention(@NotNull final PsiElement element) {
- final PsiExpression expression = (PsiExpression)element;
- final Number value = (Number)ExpressionUtils.computeConstantExpression(expression);
- if (value == null) return;
- final PsiType type = expression.getType();
- final boolean negated = ExpressionUtils.isNegative(expression);
-
- final String resultString = convertValue(value, type, negated);
- if (resultString == null) return;
-
- PsiReplacementUtil.replaceExpression(negated ? (PsiExpression)expression.getParent() : expression, resultString, new CommentTracker());
- }
-
- @Nullable
- protected abstract String convertValue(final Number value, final PsiType type, final boolean negated);
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java
deleted file mode 100644
index b43729ff74d5..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2000-2016 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-import java.math.BigDecimal;
-
-/**
- * @author Konstantin Bulenkov
- */
-public class ConvertToPlainIntention extends ConvertNumberIntentionBase {
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- String text = new BigDecimal(value.toString()).stripTrailingZeros().toPlainString();
- if (negated) text = "-" + text;
- if (PsiType.FLOAT.equals(type)) text += "f";
- return text;
- }
-
- @NotNull
- @Override
- protected PsiElementPredicate getElementPredicate() {
- return new ConvertToPlainPredicate();
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainPredicate.java
deleted file mode 100644
index 22d83306af02..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainPredicate.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-
-/**
- * @author Konstantin Bulenkov
- */
-class ConvertToPlainPredicate implements PsiElementPredicate {
-
- @Override
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiLiteralExpression)) {
- return false;
- }
- final PsiLiteralExpression expression = (PsiLiteralExpression)element;
- if (expression.getValue() == null) {
- return false;
- }
- final PsiType type = expression.getType();
- if (!PsiType.DOUBLE.equals(type) && !PsiType.FLOAT.equals(type)) {
- return false;
- }
- final String text = expression.getText();
- return text.contains("e") || text.contains("E");
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationIntention.java
deleted file mode 100644
index 4970530026d0..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationIntention.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2000-2010 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.siyeh.ipp.integer;
-
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NotNull;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.Locale;
-
-/**
- * @author Konstantin Bulenkov
- */
-public class ConvertToScientificNotationIntention extends ConvertNumberIntentionBase {
- private static final DecimalFormat FORMAT = new DecimalFormat("0.0#############E00", new DecimalFormatSymbols(Locale.US));
-
- @Override
- protected String convertValue(final Number value, final PsiType type, final boolean negated) {
- final double doubleValue = Double.parseDouble(value.toString()); // convert to double w/o adding parasitic digits
- final String text = FORMAT.format(negated ? -doubleValue : doubleValue);
- return PsiType.FLOAT.equals(type) ? text + "f" : text;
- }
-
- @NotNull
- @Override
- protected PsiElementPredicate getElementPredicate() {
- return new ConvertToScientificNotationPredicate();
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java
deleted file mode 100644
index 1f2d8971df58..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.siyeh.ipp.integer;
-
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLiteralExpression;
-import com.intellij.psi.PsiType;
-import com.siyeh.ipp.base.PsiElementPredicate;
-
-/**
- * @author Konstantin Bulenkov
- */
-class ConvertToScientificNotationPredicate implements PsiElementPredicate {
-
- @Override
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiLiteralExpression)) {
- return false;
- }
- final PsiLiteralExpression expression = (PsiLiteralExpression)element;
- if (expression.getValue() == null) {
- return false;
- }
- final PsiType type = expression.getType();
- if (!PsiType.DOUBLE.equals(type) && !PsiType.FLOAT.equals(type)) {
- return false;
- }
- final String text = StringUtil.trimStart(expression.getText(), "-");
- return !text.contains("e");
- }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConversionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConversionIntention.java
new file mode 100644
index 000000000000..77b0d45aa656
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConversionIntention.java
@@ -0,0 +1,71 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.siyeh.ipp.integer;
+
+import com.intellij.codeInsight.intention.numeric.AbstractNumberConversionIntention;
+import com.intellij.codeInsight.intention.numeric.NumberConverter;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ImmutableList;
+import com.siyeh.ig.psiutils.CommentTracker;
+import com.siyeh.ig.psiutils.ExpressionUtils;
+import com.siyeh.ig.psiutils.JavaPsiMathUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static com.intellij.util.containers.ContainerUtil.immutableList;
+import static com.siyeh.ipp.integer.JavaNumberConverters.*;
+
+public class JavaNumberConversionIntention extends AbstractNumberConversionIntention {
+ private static final ImmutableList JAVA_1_CONVERTERS = immutableList(
+ INTEGER_TO_DECIMAL, INTEGER_TO_HEX, INTEGER_TO_OCTAL, FLOAT_TO_DECIMAL, FLOAT_TO_PLAIN, FLOAT_TO_SCIENTIFIC);
+ private static final ImmutableList JAVA_5_CONVERTERS = immutableList(
+ INTEGER_TO_DECIMAL, INTEGER_TO_HEX, INTEGER_TO_OCTAL, FLOAT_TO_DECIMAL, FLOAT_TO_PLAIN, FLOAT_TO_SCIENTIFIC, FLOAT_TO_HEX);
+ private static final ImmutableList JAVA_7_CONVERTERS = immutableList(
+ INTEGER_TO_DECIMAL, INTEGER_TO_HEX, INTEGER_TO_BINARY, INTEGER_TO_OCTAL,
+ FLOAT_TO_DECIMAL, FLOAT_TO_PLAIN, FLOAT_TO_SCIENTIFIC, FLOAT_TO_HEX);
+
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ protected NumberConversionContext extract(@NotNull PsiElement element) {
+ if (element instanceof PsiJavaToken) {
+ element = element.getParent();
+ }
+ PsiLiteralExpression literal = ObjectUtils.tryCast(element, PsiLiteralExpression.class);
+ if (literal == null) return null;
+ Number value = ObjectUtils.tryCast(literal.getValue(), Number.class);
+ if (value == null) return null;
+ if (ExpressionUtils.isNegative(literal)) {
+ value = Objects.requireNonNull(JavaPsiMathUtil.negate(value));
+ return new NumberConversionContext(element.getParent(), value, literal.getText(), true);
+ }
+ return new NumberConversionContext(element, value, literal.getText(), false);
+ }
+
+ @Override
+ @NotNull
+ @Contract(pure = true)
+ protected List getConverters(@NotNull PsiFile file) {
+ if (!(file instanceof PsiJavaFile)) return Collections.emptyList();
+ LanguageLevel level = PsiUtil.getLanguageLevel(file);
+ if (level.isLessThan(LanguageLevel.JDK_1_5)) {
+ return JAVA_1_CONVERTERS;
+ }
+ if (level.isLessThan(LanguageLevel.JDK_1_7)) {
+ return JAVA_5_CONVERTERS;
+ }
+ return JAVA_7_CONVERTERS;
+ }
+
+ @Override
+ protected void replace(PsiElement sourceElement, String replacement) {
+ new CommentTracker().replaceAndRestoreComments(sourceElement, replacement);
+ }
+}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConverters.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConverters.java
new file mode 100644
index 000000000000..3480ddb24ed9
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/JavaNumberConverters.java
@@ -0,0 +1,158 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.siyeh.ipp.integer;
+
+import com.intellij.codeInsight.intention.numeric.NumberConverter;
+import com.siyeh.ig.psiutils.ExpressionUtils;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+public class JavaNumberConverters {
+ static final NumberConverter INTEGER_TO_HEX = new NumberConverter() {
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if (text.startsWith("0x") || text.startsWith("0X")) return null;
+ if (number instanceof Integer) {
+ return "0x" + Integer.toHexString(number.intValue());
+ }
+ if (number instanceof Long) {
+ return "0x" + Long.toHexString(number.longValue()) + "L";
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() { return "hex";}
+ };
+ static final NumberConverter INTEGER_TO_BINARY = new NumberConverter() {
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if (text.startsWith("0b") || text.startsWith("0B")) return null;
+ if (number instanceof Integer) {
+ return "0b" + Integer.toBinaryString(number.intValue());
+ }
+ if (number instanceof Long) {
+ return "0b" + Long.toBinaryString(number.longValue()) + "L";
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() { return "binary";}
+ };
+ static final NumberConverter INTEGER_TO_OCTAL = new NumberConverter() {
+ @Nullable
+ @Override
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if (ExpressionUtils.isOctalLiteralText(text)) return null;
+ if (number instanceof Integer) {
+ return "0" + Integer.toOctalString(number.intValue());
+ }
+ if (number instanceof Long) {
+ return "0" + Long.toOctalString(number.longValue()) + "L";
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "octal";
+ }
+ };
+ static final NumberConverter INTEGER_TO_DECIMAL = new NumberConverter() {
+ @Nullable
+ @Override
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if ("0L".equals(text) || "0l".equals(text) || text.charAt(0) != '0') return null;
+ if (number instanceof Integer) {
+ return Integer.toString(number.intValue());
+ }
+ if (number instanceof Long) {
+ return Long.toString(number.longValue()) + 'L';
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "decimal";
+ }
+ };
+ static final NumberConverter FLOAT_TO_HEX = new NumberConverter() {
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String originalText, @NotNull Number original) {
+ if (originalText.startsWith("0x") || originalText.startsWith("0X")) return null;
+ if (original instanceof Float) {
+ return Float.toHexString(original.floatValue()) + "f";
+ }
+ if (original instanceof Double) {
+ return Double.toHexString(original.doubleValue());
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() { return "hex";}
+ };
+ static final NumberConverter FLOAT_TO_DECIMAL = new NumberConverter() {
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String originalText, @NotNull Number original) {
+ if (!originalText.startsWith("0x") && !originalText.startsWith("0X")) return null;
+ if (original instanceof Float) {
+ return Float.toString(original.floatValue()) + 'f';
+ }
+ if (original instanceof Double) {
+ return Double.toString(original.doubleValue());
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() { return "decimal";}
+ };
+ static final NumberConverter FLOAT_TO_PLAIN = new NumberConverter() {
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if (!(number instanceof Float) && !(number instanceof Double)) return null;
+ if (!text.contains("e") && !text.contains("E")) return null;
+ String result = new BigDecimal(number.toString()).stripTrailingZeros().toPlainString();
+ if (number instanceof Float) result += "f";
+ return result;
+ }
+
+ @Override
+ public String toString() { return "plain format";}
+ };
+ static final NumberConverter FLOAT_TO_SCIENTIFIC = new NumberConverter() {
+ private final DecimalFormat FORMAT = new DecimalFormat("0.0#############E00", new DecimalFormatSymbols(Locale.US));
+
+ @Override
+ @Nullable
+ @Contract(pure = true)
+ public String getConvertedText(@NotNull String text, @NotNull Number number) {
+ if (!(number instanceof Float) && !(number instanceof Double)) return null;
+ if (text.contains("e") || text.contains("E")) return null;
+ String result = FORMAT.format(Double.parseDouble(number.toString())); // convert to double w/o adding parasitic digits
+ if (number instanceof Float) result += "f";
+ return result;
+ }
+
+ @Override
+ public String toString() { return "scientific format";}
+ };
+}
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex.java
new file mode 100644
index 000000000000..c7145df9242c
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex.java
@@ -0,0 +1,3 @@
+class C {
+ double x = 1.23456789E03;
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex_after.java
new file mode 100644
index 000000000000..724d9998fcca
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToHex_after.java
@@ -0,0 +1,3 @@
+class C {
+ double x = 0x1.34a4584f4c6e7p10;
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToBinaryTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToBinaryTest.java
deleted file mode 100644
index 1f3b7b4cc15e..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToBinaryTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2000-2011 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.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-public class ConvertIntegerToBinaryTest extends IPPTestCase {
- public void testDecToBin1() { doTest(); }
- public void testDecToBin2() { doTest(); }
- public void testHexToBin1() { doTest(); }
- public void testHexToBin2() { doTest(); }
- public void testOctToBin1() { doTest(); }
- public void testOctToBin2() { doTest(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.integer.to.binary.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "integer";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToDecimalTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToDecimalTest.java
deleted file mode 100644
index 10405e41ac70..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToDecimalTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2000-2011 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.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-public class ConvertIntegerToDecimalTest extends IPPTestCase {
- public void testHexToDec1() { doTest(); }
- public void testHexToDec2() { doTest(); }
- public void testHexToDec3() { doTest(); }
- public void testHexToDec4() { doTest(); }
- public void testOctToDec1() { doTest(); }
- public void testOctToDec2() { doTest(); }
- public void testBinToDec1() { doTest(); }
- public void testBinToDec2() { doTest(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.integer.to.decimal.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "integer";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToHexTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToHexTest.java
deleted file mode 100644
index efa37c1d7f6d..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToHexTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2000-2011 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.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-public class ConvertIntegerToHexTest extends IPPTestCase {
- public void testDecToHex1() { doTest(); }
- public void testDecToHex2() { doTest(); }
- public void testDecToHex3() { doTest(); }
- public void testDecToHex4() { doTest(); }
- public void testOctToHex1() { doTest(); }
- public void testOctToHex2() { doTest(); }
- public void testBinToHex1() { doTest(); }
- public void testBinToHex2() { doTest(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.integer.to.hex.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "integer";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToOctalTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToOctalTest.java
deleted file mode 100644
index 838983e326cc..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertIntegerToOctalTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-public class ConvertIntegerToOctalTest extends IPPTestCase {
- public void testDecToOct1() { doTest(); }
- public void testDecToOct2() { doTest(); }
- public void testHexToOct1() { doTest(); }
- public void testHexToOct2() { doTest(); }
- public void testBinToOct1() { doTest(); }
- public void testBinToOct2() { doTest(); }
- public void testRedOctal() { assertIntentionNotAvailable(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.integer.to.octal.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "integer";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java
deleted file mode 100644
index de6a34fb1c1c..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2000-2016 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-/**
- * @see ConvertToPlainIntention
- */
-public class ConvertToPlainTest extends IPPTestCase {
- public void testToPlain() { doTest(); }
- public void testNegatedFloatToPlain() { doTest(); }
- public void testWithUnderscoresToPlain() { doTest(); }
- public void testNoTrailingZeros() { doTest(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.to.plain.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "float";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToScientificNotationTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToScientificNotationTest.java
deleted file mode 100644
index 4643e1743c89..000000000000
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToScientificNotationTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2000-2011 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.siyeh.ipp.integer;
-
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.IPPTestCase;
-
-public class ConvertToScientificNotationTest extends IPPTestCase {
- public void testToSci() { doTest(); }
- public void testNegatedFloatToSci() { doTest(); }
- public void testWithUnderscoresToSci() { doTest(); }
-
- @Override
- protected String getIntentionName() {
- return IntentionPowerPackBundle.message("convert.to.scientific.notation.intention.name");
- }
-
- @Override
- protected String getRelativePath() {
- return "float";
- }
-}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertFloatingNumberTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertFloatingNumberTest.java
new file mode 100644
index 000000000000..ea6d06171f03
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertFloatingNumberTest.java
@@ -0,0 +1,34 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.siyeh.ipp.integer;
+
+import com.intellij.ui.ChooserInterceptor;
+import com.intellij.ui.UiInterceptors;
+import com.siyeh.ipp.IPPTestCase;
+
+import java.util.regex.Pattern;
+
+public class JavaConvertFloatingNumberTest extends IPPTestCase {
+ public void testToPlain() { doTestWithChooser("Plain format"); }
+ public void testToHex() { doTestWithChooser("Hex"); }
+ public void testNegatedFloatToPlain() { doTestWithChooser("Plain format"); }
+ public void testWithUnderscoresToPlain() { doTestWithChooser("Plain format"); }
+ public void testNoTrailingZeros() { doTestWithChooser("Plain format"); }
+ public void testToSci() { doTestWithChooser("Scientific format"); }
+ public void testNegatedFloatToSci() { doTestWithChooser("Scientific format"); }
+ public void testWithUnderscoresToSci() { doTestWithChooser("Scientific format"); }
+
+ private void doTestWithChooser(String selectedOption) {
+ UiInterceptors.register(new ChooserInterceptor(null, Pattern.quote(selectedOption) + " \\(.*\\)"));
+ doTest();
+ }
+
+ @Override
+ protected String getIntentionName() {
+ return "Convert number to...";
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "float";
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertNumericBaseTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertNumericBaseTest.java
new file mode 100644
index 000000000000..dac770c9de5b
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/JavaConvertNumericBaseTest.java
@@ -0,0 +1,55 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.siyeh.ipp.integer;
+
+import com.intellij.ui.ChooserInterceptor;
+import com.intellij.ui.UiInterceptors;
+import com.siyeh.ipp.IPPTestCase;
+
+import java.util.regex.Pattern;
+
+public class JavaConvertNumericBaseTest extends IPPTestCase {
+ public void testDecToHex1() { doTestWithChooser("Hex"); }
+ public void testDecToHex2() { doTestWithChooser("Hex"); }
+ public void testDecToHex3() { doTestWithChooser("Hex"); }
+ public void testDecToHex4() { doTestWithChooser("Hex"); }
+ public void testOctToHex1() { doTestWithChooser("Hex"); }
+ public void testOctToHex2() { doTestWithChooser("Hex"); }
+ public void testBinToHex1() { doTestWithChooser("Hex"); }
+ public void testBinToHex2() { doTestWithChooser("Hex"); }
+ public void testDecToOct1() { doTestWithChooser("Octal"); }
+ public void testDecToOct2() { doTestWithChooser("Octal"); }
+ public void testHexToOct1() { doTestWithChooser("Octal"); }
+ public void testHexToOct2() { doTestWithChooser("Octal"); }
+ public void testBinToOct1() { doTestWithChooser("Octal"); }
+ public void testBinToOct2() { doTestWithChooser("Octal"); }
+ public void testRedOctal() { assertIntentionNotAvailable(); }
+ public void testHexToDec1() { doTestWithChooser("Decimal"); }
+ public void testHexToDec2() { doTestWithChooser("Decimal"); }
+ public void testHexToDec3() { doTestWithChooser("Decimal"); }
+ public void testHexToDec4() { doTestWithChooser("Decimal"); }
+ public void testOctToDec1() { doTestWithChooser("Decimal"); }
+ public void testOctToDec2() { doTestWithChooser("Decimal"); }
+ public void testBinToDec1() { doTestWithChooser("Decimal"); }
+ public void testBinToDec2() { doTestWithChooser("Decimal"); }
+ public void testDecToBin1() { doTestWithChooser("Binary"); }
+ public void testDecToBin2() { doTestWithChooser("Binary"); }
+ public void testHexToBin1() { doTestWithChooser("Binary"); }
+ public void testHexToBin2() { doTestWithChooser("Binary"); }
+ public void testOctToBin1() { doTestWithChooser("Binary"); }
+ public void testOctToBin2() { doTestWithChooser("Binary"); }
+
+ private void doTestWithChooser(String selectedOption) {
+ UiInterceptors.register(new ChooserInterceptor(null, Pattern.quote(selectedOption) + " \\(.*\\)"));
+ doTest();
+ }
+
+ @Override
+ protected String getIntentionName() {
+ return "Convert number to...";
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "integer";
+ }
+}