specialise methods with type variables

This commit is contained in:
Dave Holoway
2020-06-10 11:57:16 +01:00
parent 41adfbe53e
commit 309cc47107
2 changed files with 14 additions and 14 deletions

View File

@@ -4,7 +4,7 @@
* *
* Each token also contains detailed state information used for completion suggestions. * Each token also contains detailed state information used for completion suggestions.
*/ */
const { JavaType, CEIType, PrimitiveType, ArrayType, UnresolvedType, WildcardType, TypeVariable, Field, Method, Parameter, Constructor, signatureToType } = require('java-mti'); const { JavaType, CEIType, PrimitiveType, ArrayType, UnresolvedType, NullType, WildcardType, TypeVariable, Field, Method, ReifiedMethod, Parameter, Constructor, signatureToType } = require('java-mti');
const { SourceMethod, SourceConstructor, SourceInitialiser } = require('./source-type'); const { SourceMethod, SourceConstructor, SourceInitialiser } = require('./source-type');
const ResolvedImport = require('./parsetypes/resolved-import'); const ResolvedImport = require('./parsetypes/resolved-import');
const ParseProblem = require('./parsetypes/parse-problem'); const ParseProblem = require('./parsetypes/parse-problem');
@@ -1768,11 +1768,20 @@ function arrayElementOrConstructor(tokens, open_array, matches, index) {
*/ */
function methodCallExpression(tokens, instance, call_arguments, typemap) { function methodCallExpression(tokens, instance, call_arguments, typemap) {
const ident = `${instance.source}(${call_arguments.map(arg => arg.source).join(',')})`; const ident = `${instance.source}(${call_arguments.map(arg => arg.source).join(',')})`;
// method call resolving is painful in Java - we need to match arguments against // method call resolving is painful in Java - we need to match arguments against
// possible types in the call, but this must include matching against inherited types and choosing the // possible types in the call, but this must include matching against inherited types and choosing the
// most-specific match // most-specific match
const methods = instance.methods.filter(m => isCallCompatible(m, call_arguments)); const methods = [];
instance.methods.forEach(m => {
if (m.typeVariables.length) {
// if the method is declared with type variables, specialise it based upon the argument types
m = ReifiedMethod.build(m, call_arguments.map(arg => arg.variables[0].type));
}
if (isCallCompatible(m, call_arguments)) {
methods.push(m);
}
});
const types = instance.types.filter(t => { const types = instance.types.filter(t => {
// interfaces use Object constructors // interfaces use Object constructors
const type = t.typeKind === 'interface' const type = t.typeKind === 'interface'
@@ -1859,16 +1868,6 @@ function getTypeInheritanceList(type) {
return Array.from(types.done); return Array.from(types.done);
} }
class NullType extends JavaType {
constructor() {
super('class', [], '');
super.simpleTypeName = 'null';
}
get typeSignature() {
return 'null';
}
}
/** /**
* @param {ResolvedIdent} matches * @param {ResolvedIdent} matches

View File

@@ -1,4 +1,4 @@
const { JavaType, CEIType, PrimitiveType, Constructor, Method, MethodBase, Field, Parameter, TypeVariable, UnresolvedType, signatureToType } = require('java-mti'); const { JavaType, ArrayType, CEIType, NullType, PrimitiveType, TypeVariableType, Constructor, Method, MethodBase, Field, Parameter, TypeVariable, UnresolvedType, signatureToType } = require('java-mti');
const { ModuleBlock, TypeDeclBlock, FieldBlock, ConstructorBlock, MethodBlock, InitialiserBlock, ParameterBlock, TextBlock } = require('./parser9'); const { ModuleBlock, TypeDeclBlock, FieldBlock, ConstructorBlock, MethodBlock, InitialiserBlock, ParameterBlock, TextBlock } = require('./parser9');
/** /**
@@ -214,6 +214,7 @@ class SourceMethod extends Method {
this._decl = decl; this._decl = decl;
this._parameters = decl.parameters.map((p,i) => new SourceParameter(p)); this._parameters = decl.parameters.map((p,i) => new SourceParameter(p));
this._returnType = new ResolvableType(decl); this._returnType = new ResolvableType(decl);
/** @type {TypeVariable[]} */
this._typevars = decl.typeVariables.map(tv => { this._typevars = decl.typeVariables.map(tv => {
const typevar = new TypeVariable(owner, tv.name); const typevar = new TypeVariable(owner, tv.name);
// automatically add the Object bound // automatically add the Object bound