Fix resolving of enclosed type identifiers

This commit is contained in:
Dave Holoway
2020-06-05 16:45:07 +01:00
parent b1d4261f28
commit 9c579662e6
3 changed files with 51 additions and 22 deletions

View File

@@ -1445,15 +1445,16 @@ function expressionList(tokens, locals, method, imports, typemap) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {SourceMC} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
*/ */
function typeIdentList(tokens, imports, typemap) { function typeIdentList(tokens, method, imports, typemap) {
let type = typeIdent(tokens, imports, typemap); let type = typeIdent(tokens, method, imports, typemap);
const types = [type]; const types = [type];
while (tokens.current.value === ',') { while (tokens.current.value === ',') {
tokens.inc(); tokens.inc();
type = typeIdent(tokens, imports, typemap); type = typeIdent(tokens, method, imports, typemap);
types.push(type); types.push(type);
} }
return types; return types;
@@ -1461,14 +1462,15 @@ function typeIdentList(tokens, imports, typemap) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {SourceMC} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
*/ */
function typeIdent(tokens, imports, typemap) { function typeIdent(tokens, method, imports, typemap) {
if (tokens.current.kind !== 'ident') { if (tokens.current.kind !== 'ident') {
return new UnresolvedType(); return new UnresolvedType();
} }
const { types, package_name } = resolveTypeOrPackage(tokens.current.value, imports, typemap); const { types, package_name } = resolveTypeOrPackage(tokens.current.value, method._owner, imports, typemap);
let matches = new ResolvedIdent(tokens.current.value, [], [], types, package_name); let matches = new ResolvedIdent(tokens.current.value, [], [], types, package_name);
for (;;) { for (;;) {
tokens.inc(); tokens.inc();
@@ -1476,7 +1478,7 @@ function typeIdent(tokens, imports, typemap) {
matches = parseDottedIdent(matches, tokens, typemap); matches = parseDottedIdent(matches, tokens, typemap);
} else if (tokens.isValue('<')) { } else if (tokens.isValue('<')) {
if (!tokens.isValue('>')) { if (!tokens.isValue('>')) {
typeIdentList(tokens, imports, typemap); typeIdentList(tokens, method, imports, typemap);
tokens.expectValue('>'); tokens.expectValue('>');
} }
} else { } else {
@@ -1701,7 +1703,7 @@ function qualifiers(matches, tokens, locals, method, imports, typemap) {
tokens.inc(); tokens.inc();
let type_arguments = []; let type_arguments = [];
if (!tokens.isValue('>')) { if (!tokens.isValue('>')) {
type_arguments = typeIdentList(tokens, imports, typemap); type_arguments = typeIdentList(tokens, method, imports, typemap);
tokens.expectValue('>'); tokens.expectValue('>');
} }
matches.types = matches.types.map(t => { matches.types = matches.types.map(t => {
@@ -1842,6 +1844,13 @@ function resolveIdentifier(tokens, locals, method, imports, typemap) {
return matches; return matches;
} }
/**
* @param {string} ident
* @param {Local[]} locals
* @param {SourceMC} method
* @param {ResolvedImport[]} imports
* @param {Map<String,JavaType>} typemap
*/
function findIdentifier(ident, locals, method, imports, typemap) { function findIdentifier(ident, locals, method, imports, typemap) {
const matches = new ResolvedIdent(ident); const matches = new ResolvedIdent(ident);
@@ -1873,7 +1882,7 @@ function findIdentifier(ident, locals, method, imports, typemap) {
}); });
} }
const { types, package_name } = resolveTypeOrPackage(ident, imports, typemap); const { types, package_name } = resolveTypeOrPackage(ident, method._owner, imports, typemap);
matches.types = types; matches.types = types;
matches.package_name = package_name; matches.package_name = package_name;
@@ -1883,25 +1892,44 @@ function findIdentifier(ident, locals, method, imports, typemap) {
/** /**
* *
* @param {string} ident * @param {string} ident
* @param {CEIType} scoped_type
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
*/ */
function resolveTypeOrPackage(ident, imports, typemap) { function resolveTypeOrPackage(ident, scoped_type, imports, typemap) {
const types = []; const types = [];
let package_name = ''; let package_name = '';
// is it a top-level type from the imports // is it an enclosed type of the currently scoped type or any outer type
const top_level_type = '/' + ident; if (scoped_type) {
for (let i of imports) { const scopes = scoped_type.shortSignature.split('$');
const fqn = i.fullyQualifiedNames.find(fqn => fqn.endsWith(top_level_type)); while (scopes.length) {
if (fqn) { const enc_type = typemap.get(`${scopes.join('$')}$${ident}`);
types.push(i.types.get(fqn)); if (enc_type) {
types.push(enc_type);
break;
}
scopes.pop();
} }
} }
// is it a default-package type
const default_type = typemap.get(ident); if (!types[0]) {
if (default_type) { // is it a top-level type from the imports
types.push(default_type); const top_level_type = '/' + ident;
for (let i of imports) {
const fqn = i.fullyQualifiedNames.find(fqn => fqn.endsWith(top_level_type));
if (fqn) {
types.push(i.types.get(fqn));
}
}
}
if (!types[0]) {
// is it a default-package type
const default_type = typemap.get(ident);
if (default_type) {
types.push(default_type);
}
} }
// the final option is the start of a package name // the final option is the start of a package name

View File

@@ -38,7 +38,7 @@ function resolveImportTypes(typenames, import_decl) {
* - followed by implicit packages * - followed by implicit packages
* *
* @param {Map<string, import('java-mti').JavaType>} androidLibrary * @param {Map<string, import('java-mti').JavaType>} androidLibrary
* @param {import('java-mti').JavaType[]} sourceTypes * @param {import('./source-type').SourceType[]} sourceTypes
* @param {ImportBlock[]} imports list of declared imports in the module * @param {ImportBlock[]} imports list of declared imports in the module
* @param {string} package_name package name of the module * @param {string} package_name package name of the module
* @param {string[]} [implicitPackages] list of implicit demand-load packages * @param {string[]} [implicitPackages] list of implicit demand-load packages

View File

@@ -60,13 +60,13 @@ function validate(mod, androidLibrary) {
source_types.forEach(t => { source_types.forEach(t => {
t.constructors.forEach(c => { t.constructors.forEach(c => {
console.log(c.label); console.log(c.label);
const parsed = parseBody(c._owner._decl.mod.source, c, imports.resolved, androidLibrary); const parsed = parseBody(c._owner._decl.mod.source, c, imports.resolved, imports.typemap);
if (parsed) if (parsed)
probs = probs.concat(parsed.problems) probs = probs.concat(parsed.problems)
}) })
t.methods.forEach(m => { t.methods.forEach(m => {
console.log(m.label); console.log(m.label);
const parsed = parseBody(m._owner._decl.mod.source, m, imports.resolved, androidLibrary); const parsed = parseBody(m._owner._decl.mod.source, m, imports.resolved, imports.typemap);
if (parsed) if (parsed)
probs = probs.concat(parsed.problems) probs = probs.concat(parsed.problems)
}) })
@@ -104,6 +104,7 @@ function validate(mod, androidLibrary) {
} }
let flattened = flatten(problems).filter(x => x); let flattened = flatten(problems).filter(x => x);
console.log(`Problems: ${flattened.length}`)
return flattened; return flattened;
} }