perform more detailed search of implemented methods

This commit is contained in:
Dave Holoway
2020-06-23 14:41:20 +01:00
parent ce345965e5
commit cd6bf29e9f
3 changed files with 44 additions and 4 deletions

View File

@@ -304,8 +304,10 @@ function isTypeAssignable(dest_type, value_type) {
}
}
}
} else if (dest_type instanceof TypeVariableType) {
is_assignable = !(value_type instanceof PrimitiveType || value_type instanceof NullType);
}
return is_assignable;
return is_assignable;
}
/**

View File

@@ -136,7 +136,6 @@ class SourceType extends CEIType {
}
/**
*
* @param {JavaType[]} types
* @returns {CEIType}
*/
@@ -178,6 +177,7 @@ class SpecialisedSourceType extends CEIType {
*/
constructor(source_type, typeKind, raw_short_signature, types) {
super(raw_short_signature, typeKind, source_type.modifiers, source_type.docs);
this.source_type = source_type;
this.typemap = source_type.typemap;
/** @type {TypeArgument[]} */
// @ts-ignore
@@ -262,6 +262,25 @@ class SpecialisedSourceType extends CEIType {
};
});
}
/**
* @param {JavaType[]} types
* @returns {CEIType}
*/
specialise(types) {
const short_sig = `${this._rawShortSignature}<${types.map(t => t.typeSignature).join('')}>`;
if (this.typemap.has(short_sig)) {
// @ts-ignore
return this.typemap.get(short_sig);
}
/** @type {'class'|'enum'|'interface'|'@interface'} */
// @ts-ignore
const typeKind = this.typeKind;
const specialised_type = new SpecialisedSourceType(this.source_type, typeKind, this._rawShortSignature, types);
this.typemap.set(short_sig, specialised_type);
return specialised_type;
}
}
class SourceEnumValue extends Field {

View File

@@ -1,11 +1,27 @@
const ParseProblem = require('../parsetypes/parse-problem');
const { SourceType } = require('../source-types');
const {CEIType} = require('java-mti');
const { CEIType, Method} = require('java-mti');
const {isTypeAssignable} = require('../expression-resolver');
function nonAbstractLabel(label) {
return label.replace(/\babstract /g, '');
}
/**
*
* @param {Method} impl method implementation
* @param {Method} method interface method
*/
function isMethodCompatible(impl, method) {
const impl_params = impl.parameters;
const method_params = method.parameters;
if (impl_params.length !== method_params.length) {
return false;
}
return impl_params.every((p,idx) => isTypeAssignable(method_params[idx].type, p.type))
&& isTypeAssignable(method.returnType, impl.returnType);
}
/**
* @param {SourceType} source_type
* @param {*} probs
@@ -44,7 +60,10 @@ function checkImplementedInterfaces(source_type, probs) {
}
const namedsig = `${m.name}${m.methodSignature}`
if (implemented.indexOf(namedsig) < 0) {
missing_methods.push(nonAbstractLabel(m.label));
// perform a more detailed search for a compatible match
if (!source_type.methods.find(source_method => source_method.name === m.name && isMethodCompatible(source_method, m))) {
missing_methods.push(nonAbstractLabel(m.label));
}
}
})
if (missing_methods.length) {