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

au.com.integradev.delphi.utils.CastUtils Maven / Gradle / Ivy

There is a newer version: 1.12.1
Show newest version
/*
 * Sonar Delphi Plugin
 * Copyright (C) 2023 Integrated Application Development
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package au.com.integradev.delphi.utils;

import java.util.List;
import java.util.Optional;
import org.sonar.plugins.communitydelphi.api.ast.ArgumentListNode;
import org.sonar.plugins.communitydelphi.api.ast.ArgumentNode;
import org.sonar.plugins.communitydelphi.api.ast.BinaryExpressionNode;
import org.sonar.plugins.communitydelphi.api.ast.DelphiNode;
import org.sonar.plugins.communitydelphi.api.ast.ExpressionNode;
import org.sonar.plugins.communitydelphi.api.ast.NameReferenceNode;
import org.sonar.plugins.communitydelphi.api.ast.PrimaryExpressionNode;
import org.sonar.plugins.communitydelphi.api.operator.BinaryOperator;
import org.sonar.plugins.communitydelphi.api.symbol.declaration.NameDeclaration;
import org.sonar.plugins.communitydelphi.api.symbol.declaration.TypeNameDeclaration;
import org.sonar.plugins.communitydelphi.api.token.DelphiTokenType;
import org.sonar.plugins.communitydelphi.api.type.IntrinsicType;
import org.sonar.plugins.communitydelphi.api.type.Type;
import org.sonar.plugins.communitydelphi.api.type.Type.ClassReferenceType;
import org.sonar.plugins.communitydelphi.api.type.Type.ProceduralType;
import org.sonar.plugins.communitydelphi.api.type.TypeFactory;

public class CastUtils {
  private CastUtils() {
    // Utility class
  }

  public static Optional readSoftCast(BinaryExpressionNode binaryExpression) {
    if (binaryExpression.getOperator() != BinaryOperator.AS) {
      return Optional.empty();
    }

    Type originalType = getOriginalType(binaryExpression.getLeft());
    Type castedType = getSoftCastedType(binaryExpression.getRight());
    return Optional.of(new DelphiCast(originalType, castedType));
  }

  public static Optional readHardCast(
      PrimaryExpressionNode primaryExpression, TypeFactory typeFactory) {
    List children = primaryExpression.getChildren();
    if (children.size() < 2
        || !(children.get(1) instanceof ArgumentListNode)
        || !isValidHardCastHeader(children.get(0))) {
      return Optional.empty();
    }

    ArgumentListNode argumentList = (ArgumentListNode) primaryExpression.getChild(1);
    List arguments = argumentList.getArgumentNodes();
    if (arguments.size() != 1) {
      return Optional.empty();
    }
    Type originalType = getOriginalType(arguments.get(0).getExpression());

    DelphiNode nameReference = primaryExpression.getChild(0);
    Type castedType = getHardCastedType(nameReference, typeFactory);

    return castedType == null
        ? Optional.empty()
        : Optional.of(new DelphiCast(originalType, castedType));
  }

  private static boolean isValidHardCastHeader(DelphiNode node) {
    return node instanceof NameReferenceNode
        || node.getTokenType() == DelphiTokenType.STRING
        || node.getTokenType() == DelphiTokenType.FILE;
  }

  private static Type getOriginalType(ExpressionNode expression) {
    Type result = expression.getType();
    if (result.isRoutine()) {
      result = ((ProceduralType) result).returnType();
    }
    return result;
  }

  private static Type getSoftCastedType(ExpressionNode expression) {
    Type result = expression.getType();
    if (result.isClassReference()) {
      result = ((ClassReferenceType) result).classType();
    }
    return result;
  }

  private static Type getHardCastedType(DelphiNode node, TypeFactory typeFactory) {
    if (node instanceof NameReferenceNode) {
      NameDeclaration declaration = ((NameReferenceNode) node).getLastName().getNameDeclaration();
      if (declaration instanceof TypeNameDeclaration) {
        return ((TypeNameDeclaration) declaration).getType();
      }
    }

    switch (node.getTokenType()) {
      case STRING:
        return typeFactory.getIntrinsic(IntrinsicType.STRING);
      case FILE:
        return typeFactory.untypedFile();
      default:
        return null;
    }
  }

  public static class DelphiCast {
    private final Type originalType;
    private final Type castedType;

    private DelphiCast(Type originalType, Type castedType) {
      this.originalType = originalType;
      this.castedType = castedType;
    }

    public Type originalType() {
      return originalType;
    }

    public Type castedType() {
      return castedType;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy