All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.siyeh.ig.numeric.ConfusingFloatingPointLiteralInspection Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition java-analysis-impl library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2003-2013 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.ig.numeric;

import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.PsiType;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class ConfusingFloatingPointLiteralInspection extends BaseInspection {

  @Override
  @NotNull
  public String getDisplayName() {
    return InspectionGadgetsBundle.message("confusing.floating.point.literal.display.name");
  }

  @Override
  @NotNull
  protected String buildErrorString(Object... infos) {
    return InspectionGadgetsBundle.message("confusing.floating.point.literal.problem.descriptor");
  }

  @Override
  public InspectionGadgetsFix buildFix(Object... infos) {
    return new ConfusingFloatingPointLiteralFix();
  }

  private static class ConfusingFloatingPointLiteralFix extends InspectionGadgetsFix {

    @Override
    @NotNull
    public String getFamilyName() {
      return getName();
    }

    @Override
    @NotNull
    public String getName() {
      return InspectionGadgetsBundle.message("confusing.floating.point.literal.change.quickfix");
    }

    @Override
    public void doFix(Project project, ProblemDescriptor descriptor) {
      final PsiExpression literalExpression = (PsiExpression)descriptor.getPsiElement();
      final String text = literalExpression.getText();
      final String newText = getCanonicalForm(text);
      PsiReplacementUtil.replaceExpression(literalExpression, newText);
    }

    private static String getCanonicalForm(@NonNls String text) {
      final boolean isHexadecimal = text.startsWith("0x") || text.startsWith("0X");
      int breakPoint = text.indexOf((int)'e');
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'E');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'f');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'F');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'p');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'P');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'d');
      }
      if (breakPoint < 0) {
        breakPoint = text.indexOf((int)'D');
      }
      final String suffix;
      final String prefix;
      if (breakPoint < 0) {
        suffix = "";
        prefix = text;
      }
      else {
        suffix = text.substring(breakPoint);
        prefix = text.substring(0, breakPoint);
      }
      final int indexPoint = prefix.indexOf((int)'.');
      if (indexPoint < 0) {
        return prefix + ".0" + suffix;
      }
      else if (isHexadecimal && indexPoint == 2) {
        return prefix.substring(0, 2) + '0' + prefix.substring(2) + suffix;
      }
      else if (indexPoint == 0) {
        return '0' + prefix + suffix;
      }
      else {
        return prefix + '0' + suffix;
      }
    }
  }

  @Override
  public BaseInspectionVisitor buildVisitor() {
    return new ConfusingFloatingPointLiteralVisitor();
  }

  private static class ConfusingFloatingPointLiteralVisitor extends BaseInspectionVisitor {

    @Override
    public void visitLiteralExpression(@NotNull PsiLiteralExpression literal) {
      super.visitLiteralExpression(literal);
      final PsiType type = literal.getType();
      if ((PsiType.FLOAT.equals(type) || PsiType.DOUBLE.equals(type)) && isConfusing(literal.getText())) {
        registerError(literal);
      }
    }

    private static boolean isConfusing(@Nullable CharSequence text) {
      if (text == null) {
        return false;
      }
      final int length = text.length();
      if (length < 3) {
        return true;
      }
      boolean hex = true;
      final char firstChar = text.charAt(0);
      if (firstChar != '0') {
        if (!StringUtil.isDecimalDigit(firstChar)) {
          return true;
        }
        hex = false;
      }
      final char secondChar = text.charAt(1);
      if (hex && secondChar != 'x' && secondChar != 'X') {
        hex = false;
      }
      int index = hex ? 2 : 1;
      char nextChar = text.charAt(index);
      if (hex) {
        if (!StringUtil.isHexDigit(nextChar)) {
          return true;
        }
      }
      while (hex && StringUtil.isHexDigit(nextChar) || StringUtil.isDecimalDigit(nextChar) || nextChar == '_') {
        index++;
        if (index >= length) {
          return true;
        }
        nextChar = text.charAt(index);
      }
      if (nextChar != '.') {
        return true;
      }
      index++;
      if (index >= length) {
        return true;
      }
      nextChar = text.charAt(index);
      if (hex) {
        if (!StringUtil.isHexDigit(nextChar)) {
          return true;
        }
      } else if (!StringUtil.isDecimalDigit(nextChar)) {
        return true;
      }
      //  seen, skip the rest.
      return false;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy