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

com.siyeh.ig.bugs.FormatDecode 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-2014 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.bugs;

import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiType;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SuppressWarnings({"CollectionDeclaredAsConcreteClass", "ObjectEquality", "HardCodedStringLiteral"})
class FormatDecode {

  private static final String FORMAT_SPECIFIER =
    "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";

  private static final Pattern fsPattern = Pattern.compile(FORMAT_SPECIFIER);

  private FormatDecode() {}

  private static final Validator ALL_VALIDATOR = new AllValidator();

  private static final Validator DATE_VALIDATOR = new DateValidator();

  private static final Validator CHAR_VALIDATOR = new CharValidator();

  private static final Validator INT_VALIDATOR = new IntValidator();

  private static final Validator FLOAT_VALIDATOR = new FloatValidator();

  public static Validator[] decode(String formatString, int argumentCount) {
    final ArrayList parameters = new ArrayList();

    final Matcher matcher = fsPattern.matcher(formatString);
    int implicit = 0;
    int pos = 0;
    for (int i = 0; matcher.find(i); i = matcher.end()) {
      final String posSpec = matcher.group(1);
      final String flags = matcher.group(2);
      final String dateSpec = matcher.group(5);
      final String spec = matcher.group(6);

      // check this first because it should not affect "implicit"
      if ("n".equals(spec) || "%".equals(spec)) {
        continue;
      }

      if (posSpec != null) {
        final String num = posSpec.substring(0, posSpec.length() - 1);
        pos = Integer.parseInt(num) - 1;
      }
      else if (flags == null || flags.indexOf('<') < 0) {
        pos = implicit++;
      }
      // else if the flag has "<" reuse the last pos

      final Validator allowed;
      if (dateSpec != null) {  // a t or T
        allowed = DATE_VALIDATOR;
      }
      else {
        switch (Character.toLowerCase(spec.charAt(0))) {
          case 'b':
          case 'h':
          case 's':
            allowed = ALL_VALIDATOR;
            break;
          case 'c':
            allowed = CHAR_VALIDATOR;
            break;
          case 'd':
          case 'o':
          case 'x':
            allowed = INT_VALIDATOR;
            break;
          case 'e':
          case 'f':
          case 'g':
          case 'a':
            allowed = FLOAT_VALIDATOR;
            break;
          default:
            throw new UnknownFormatException(matcher.group());
        }
      }
      storeValidator(allowed, pos, parameters, argumentCount);
    }

    return parameters.toArray(new Validator[parameters.size()]);
  }

  private static void storeValidator(Validator validator, int pos,
                                     ArrayList parameters,
                                     int argumentCount) {
    if (pos < parameters.size()) {
      final Validator existing = parameters.get(pos);
      if (existing == null) {
        parameters.set(pos, validator);
      }
      else if (existing instanceof MultiValidator) {
        ((MultiValidator)existing).addValidator(validator);
      }
      else if (existing != validator) {
        final MultiValidator multiValidator = new MultiValidator();
        multiValidator.addValidator(existing);
        multiValidator.addValidator(validator);
        parameters.set(pos, multiValidator);
      }
    }
    else {
      while (pos > parameters.size() && argumentCount > parameters.size()) {
        parameters.add(null);
      }
      parameters.add(validator);
    }
  }

  public static class UnknownFormatException extends RuntimeException {

    public UnknownFormatException(String message) {
      super(message);
    }
  }

  private static class AllValidator implements Validator {

    @Override
    public boolean valid(PsiType type) {
      return true;
    }
  }

  private static class DateValidator implements Validator {

    @Override
    public boolean valid(PsiType type) {
      final String text = type.getCanonicalText();

      return PsiType.LONG.equals(type) ||
             CommonClassNames.JAVA_LANG_LONG.equals(text) ||
             CommonClassNames.JAVA_UTIL_DATE.equals(text) ||
             CommonClassNames.JAVA_UTIL_CALENDAR.equals(text);
    }
  }

  private static class CharValidator implements Validator {

    @Override
    public boolean valid(PsiType type) {
      if (PsiType.CHAR.equals(type) || PsiType.BYTE.equals(type) || PsiType.SHORT.equals(type) || PsiType.INT.equals(type)) {
        return true;
      }
      final String text = type.getCanonicalText();
      return CommonClassNames.JAVA_LANG_CHARACTER.equals(text) ||
             CommonClassNames.JAVA_LANG_BYTE.equals(text) ||
             CommonClassNames.JAVA_LANG_SHORT.equals(text) ||
             CommonClassNames.JAVA_LANG_INTEGER.equals(text);
    }
  }

  private static class IntValidator implements Validator {

    @Override
    public boolean valid(PsiType type) {
      final String text = type.getCanonicalText();
      return PsiType.INT.equals(type) ||
             CommonClassNames.JAVA_LANG_INTEGER.equals(text) ||
             PsiType.LONG.equals(type) ||
             CommonClassNames.JAVA_LANG_LONG.equals(text) ||
             PsiType.SHORT.equals(type) ||
             CommonClassNames.JAVA_LANG_SHORT.equals(text) ||
             PsiType.BYTE.equals(type) ||
             CommonClassNames.JAVA_LANG_BYTE.equals(text) ||
             "java.math.BigInteger".equals(text);
    }
  }

  private static class FloatValidator implements Validator {

    @Override
    public boolean valid(PsiType type) {
      final String text = type.getCanonicalText();
      return PsiType.DOUBLE.equals(type) ||
             CommonClassNames.JAVA_LANG_DOUBLE.equals(text) ||
             PsiType.FLOAT.equals(type) ||
             CommonClassNames.JAVA_LANG_FLOAT.equals(text) ||
             "java.math.BigDecimal".equals(text);
    }
  }

  private static class MultiValidator implements Validator {
    private final Set validators = new HashSet(3);

    @Override
    public boolean valid(PsiType type) {
      for (Validator validator : validators) {
        if (!validator.valid(type)) {
          return false;
        }
      }
      return true;
    }

    public void addValidator(Validator validator) {
      validators.add(validator);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy