FuzzyMethodCvt.java
/*
** Module : FuzzyMethodCvt.java
** Abstract : Implements conversion method resolution when there are multiple overloads which may match.
**
** Copyright (c) 2023-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
** 001 CA 20230928 Initial version.
** 002 CA 20250319 A method from a super-class can have the same name as current class, so calls to this kind
** of methods must not be resolved as a constructor for the current class.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.uast;
import java.util.*;
import java.util.logging.*;
import com.goldencode.p2j.convert.*;
/**
* Implements the rules to perform fuzzy method lookup, for conversion.
*/
public class FuzzyMethodCvt
extends FuzzyMethodLookup
{
/** Logger. */
private static final ConversionStatus LOG = ConversionStatus.get(FuzzyMethodCvt.class);
/** The class definition where the search will start. */
private final ClassDefinition clsDef;
/**
* Initialize this instance.
*
* @param clsDef
* The type where the method lookup starts from.
*/
public FuzzyMethodCvt(ClassDefinition clsDef)
{
this.clsDef = clsDef;
}
/**
* Get the list of all possible methods that could match in this class AND its parent classes. The
* actual types are not checked but the method name, access mode, static/instance and number of
* parameters must all match.
*
* @param name
* Method name.
* @param num
* Number of parameters.
* @param access
* Access mode (<code>KW_PUBLIC</code>, <code>KW_PROTECTD</code> or <code>KW_PRIVATE</code>).
* @param isStatic
* If <code>true</code>, only static methods will be looked up. Otherwise any method can be
* returned.
* @param internal
* {@code true} if the lookup is internal to the current class definition.
* @param first
* {@code true} if the first match should be immediately returned as the result.
* @param exist
* The set of existing methods already represented in the list.
* @param constructor
* Flag indicating this must resolve a constructor.
*
* @return List of possible methods that match. This may be an empty list if no match exists.
*/
@Override
protected List<MatchMetrics> candidates(String name,
int num,
int access,
boolean isStatic,
boolean internal,
boolean first,
Set<SignatureKey> exist,
boolean constructor)
{
return clsDef.candidates(name, num, access, isStatic, internal, first, exist, constructor);
}
/**
* Detect if the callee class is an instance of an implemented interface of the caller class.
*
* @param caller
* The caller type.
* @param callee
* The callee type.
*
* @return {@code true} if the given class is an implemented interface in this class.
*/
@Override
protected boolean isImplemented(String caller, String callee)
{
// parse out the classes
ClassDefinition src = parseObjectSpec(caller);
ClassDefinition tgt = parseObjectSpec(callee);
return src.isImplemented(tgt);
}
/**
* Detect if the callee class is an instance of a parent class or an implemented interface of a parent
* class, of the caller.
*
* @param caller
* The caller type.
* @param callee
* The callee type to check.
* @param incrementer
* Code to be executed to increment the inheritance level.
*
* @return {@code true} if the given class is a parent class or an implemented interface of a parent
* class.
*/
@Override
protected boolean isInheritedFrom(String caller, String callee, Runnable incrementer)
{
// parse out the classes
ClassDefinition src = parseObjectSpec(caller);
ClassDefinition tgt = parseObjectSpec(callee);
return src.isInheritedFrom(tgt, true, incrementer);
}
/**
* Reports if the class name is Progress.Lang.ParameterList and the method name is {@code setParameter()}.
*
* @param method
* The method name.
*
* @return {@code true} if this is a setParameter call.
*/
@Override
protected boolean isSetParam(String method)
{
return "Progress.Lang.ParameterList".equalsIgnoreCase(clsDef.getName()) &&
"setParameter".equalsIgnoreCase(method);
}
/**
* Get the class name where this method lookup starts from.
*
* @return See above.
*/
@Override
protected String getClassName()
{
return clsDef.getName();
}
/**
* Parse the given object spec (in the form "object<? extends _CLS_>" or "jobject<? extends _CLS_>") and
* return the class definition associated with _CLS_.
*
* @param spec
* The specification to parse.
*
* @return The class definition or {@code null} if the spec was malformed or if there is no such
* definition.
*/
private ClassDefinition parseObjectSpec(String spec)
{
String sig = "object<? extends ";
int idx = spec.indexOf(sig);
ClassDefinition cls = null;
if (idx != -1)
{
String cname = spec.substring(idx + sig.length(), spec.length() - 1);
cls = SymbolResolver.getClassDefinition(cname);
if (cls == null)
{
LOG.log(Level.SEVERE, String.format("No class found for %s (object spec %s)!", cname, spec));
}
}
else
{
LOG.log(Level.SEVERE, String.format("Malformed object spec %s!", spec));
}
return cls;
}
}