add support for generic inferred-type arguments

This commit is contained in:
Dave Holoway
2020-06-11 13:44:59 +01:00
parent 90c537b82d
commit 5b29b9998d
2 changed files with 28 additions and 15 deletions

View File

@@ -4,7 +4,8 @@
* *
* 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, NullType, WildcardType, TypeVariable, Field, Method, ReifiedMethod, Parameter, Constructor, signatureToType } = require('java-mti'); const { JavaType, CEIType, PrimitiveType, ArrayType, UnresolvedType, NullType, WildcardType, TypeVariableType,
TypeVariable, InferredTypeArgument, 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');
@@ -1269,6 +1270,10 @@ function isTypeArgumentCompatible(dest_typevar, value_typevar_type) {
} }
return false; return false;
} }
if (value_typevar_type instanceof TypeVariableType) {
// inferred type arguments of the form `x = List<>` are compatible with every destination type variable
return value_typevar_type.typeVariable instanceof InferredTypeArgument;
}
return dest_typevar.type === value_typevar_type; return dest_typevar.type === value_typevar_type;
} }

View File

@@ -89,26 +89,34 @@ function typeIdent(tokens, scope, imports, typemap, allow_array_qualifiers = tru
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
*/ */
function genericTypeArgs(tokens, types, scope, imports, typemap) { function genericTypeArgs(tokens, types, scope, imports, typemap) {
if (!tokens.isValue('>')) { if (tokens.isValue('>')) {
const type_arguments = typeIdentList(tokens, scope, imports, typemap); // <> operator - build new types with inferred type arguments
types.forEach((t,i,arr) => { types.forEach((t,i,arr) => {
if (t instanceof CEIType) { if (t instanceof CEIType) {
let specialised = t.specialise(type_arguments); let specialised = t.makeInferredTypeArgs();
if (typemap.has(specialised.shortSignature)) {
arr[i] = typemap.get(specialised.shortSignature);
return;
}
typemap.set(specialised.shortSignature, specialised);
arr[i] = specialised; arr[i] = specialised;
} }
}); });
if (/>>>?/.test(tokens.current.value)) { return;
// we need to split >> and >>> into separate > tokens to handle things like List<Class<?>>
const new_tokens = tokens.current.value.split('').map((gt,i) => new Token(tokens.current.range.source, tokens.current.range.start + i, 1, 'comparison-operator'));
tokens.splice(tokens.idx, 1, ...new_tokens);
}
tokens.expectValue('>');
} }
const type_arguments = typeIdentList(tokens, scope, imports, typemap);
types.forEach((t,i,arr) => {
if (t instanceof CEIType) {
let specialised = t.specialise(type_arguments);
if (typemap.has(specialised.shortSignature)) {
arr[i] = typemap.get(specialised.shortSignature);
return;
}
typemap.set(specialised.shortSignature, specialised);
arr[i] = specialised;
}
});
if (/>>>?/.test(tokens.current.value)) {
// we need to split >> and >>> into separate > tokens to handle things like List<Class<?>>
const new_tokens = tokens.current.value.split('').map((gt,i) => new Token(tokens.current.range.source, tokens.current.range.start + i, 1, 'comparison-operator'));
tokens.splice(tokens.idx, 1, ...new_tokens);
}
tokens.expectValue('>');
} }
/** /**