mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
update ResolvableType to use same type resolving as method body parsing
This commit is contained in:
@@ -30,7 +30,7 @@ class TokenList {
|
|||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
isValue(value) {
|
isValue(value) {
|
||||||
if (this.current.value === value) {
|
if (this.current && this.current.value === value) {
|
||||||
this.inc();
|
this.inc();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -45,14 +45,18 @@ class TokenList {
|
|||||||
if (this.isValue(value)) {
|
if (this.isValue(value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
const token = this.current || this.tokens[this.tokens.length - 1];
|
||||||
const addproblem = require("./body-parser3").addproblem;
|
const addproblem = require("./body-parser3").addproblem;
|
||||||
addproblem(this, ParseProblem.Error(this.current, `${value} expected`));
|
addproblem(this, ParseProblem.Error(token, `${value} expected`));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get previous() {
|
get previous() {
|
||||||
for (let idx = this.idx - 1; idx >= 0; idx--) {
|
for (let idx = this.idx - 1; idx >= 0; idx--) {
|
||||||
if (idx === 0 || this.tokens[idx].kind !== 'wsc') {
|
if (idx <= 0) {
|
||||||
|
return this.tokens[0];
|
||||||
|
}
|
||||||
|
if (this.tokens[idx].kind !== 'wsc') {
|
||||||
return this.tokens[idx];
|
return this.tokens[idx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const ResolvedImport = require('./parsetypes/resolved-import');
|
|||||||
const ParseProblem = require('./parsetypes/parse-problem');
|
const ParseProblem = require('./parsetypes/parse-problem');
|
||||||
const { getOperatorType, Token } = require('./tokenizer');
|
const { getOperatorType, Token } = require('./tokenizer');
|
||||||
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
||||||
const { typeIdentList } = require('./typeident');
|
const { genericTypeArgs } = require('./typeident');
|
||||||
const { TokenList } = require("./TokenList");
|
const { TokenList } = require("./TokenList");
|
||||||
const { AnyMethod, AnyType, AnyValue, ArrayElement, ArrayLiteral, ConstructorCall, LiteralNumber, LiteralValue, Local, MethodCall, ResolvedIdent, TernaryValue, Value } = require("./body-types");
|
const { AnyMethod, AnyType, AnyValue, ArrayElement, ArrayLiteral, ConstructorCall, LiteralNumber, LiteralValue, Local, MethodCall, ResolvedIdent, TernaryValue, Value } = require("./body-types");
|
||||||
|
|
||||||
@@ -19,17 +19,21 @@ const { AnyMethod, AnyType, AnyValue, ArrayElement, ArrayLiteral, ConstructorCal
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
function flattenBlocks(blocks) {
|
/**
|
||||||
|
* @param {*[]} blocks
|
||||||
|
* @param {boolean} isMethod
|
||||||
|
*/
|
||||||
|
function flattenBlocks(blocks, isMethod) {
|
||||||
return blocks.reduce((arr,block) => {
|
return blocks.reduce((arr,block) => {
|
||||||
if (block instanceof Token) {
|
if (block instanceof Token) {
|
||||||
// 'default' and 'synchronised' are not modifiers inside method bodies
|
// 'default' and 'synchronised' are not modifiers inside method bodies
|
||||||
if (block.kind === 'modifier' && /^(default|synchronized)$/.test(block.value)) {
|
if (isMethod && block.kind === 'modifier' && /^(default|synchronized)$/.test(block.value)) {
|
||||||
block.kind = 'statement-kw'
|
block.kind = 'statement-kw'
|
||||||
block.simplified = block.value;
|
block.simplified = block.value;
|
||||||
}
|
}
|
||||||
arr.push(block);
|
arr.push(block);
|
||||||
} else {
|
} else {
|
||||||
arr = [...arr, ...flattenBlocks(block.blockArray().blocks)];
|
arr = [...arr, ...flattenBlocks(block.blockArray().blocks, isMethod)];
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}, [])
|
}, [])
|
||||||
@@ -45,7 +49,7 @@ function parseBody(method, imports, typemap) {
|
|||||||
if (!body || body.blocks[0].value !== '{') {
|
if (!body || body.blocks[0].value !== '{') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const tokenlist = new TokenList(flattenBlocks(body.blocks));
|
const tokenlist = new TokenList(flattenBlocks(body.blocks, true));
|
||||||
let block = null;
|
let block = null;
|
||||||
try {
|
try {
|
||||||
block = statementBlock(tokenlist, [], method, imports, typemap);
|
block = statementBlock(tokenlist, [], method, imports, typemap);
|
||||||
@@ -1913,21 +1917,7 @@ function qualifiers(matches, tokens, locals, method, imports, typemap) {
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
tokens.inc();
|
tokens.inc();
|
||||||
let type_arguments = [];
|
genericTypeArgs(tokens, matches.types, method._owner, imports, typemap);
|
||||||
if (!tokens.isValue('>')) {
|
|
||||||
type_arguments = typeIdentList(tokens, method._owner, imports, typemap);
|
|
||||||
tokens.expectValue('>');
|
|
||||||
}
|
|
||||||
matches.types = matches.types.map(t => {
|
|
||||||
if (t instanceof CEIType) {
|
|
||||||
if (t.typevars.length) {
|
|
||||||
const specialised_type = t.specialise(type_arguments);
|
|
||||||
typemap.set(specialised_type.shortSignature, specialised_type);
|
|
||||||
return specialised_type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return matches;
|
return matches;
|
||||||
@@ -2122,3 +2112,4 @@ function findIdentifier(ident, locals, method, imports, typemap) {
|
|||||||
|
|
||||||
exports.addproblem = addproblem;
|
exports.addproblem = addproblem;
|
||||||
exports.parseBody = parseBody;
|
exports.parseBody = parseBody;
|
||||||
|
exports.flattenBlocks = flattenBlocks;
|
||||||
|
|||||||
@@ -40,15 +40,16 @@ class SourceType extends CEIType {
|
|||||||
* @param {ModuleBlock} mod
|
* @param {ModuleBlock} mod
|
||||||
* @param {TypeDeclBlock} type
|
* @param {TypeDeclBlock} type
|
||||||
* @param {string} qualified_type_name qualified $-separated type name
|
* @param {string} qualified_type_name qualified $-separated type name
|
||||||
|
* @param {Map<string,JavaType>} typemap
|
||||||
*/
|
*/
|
||||||
constructor(mod, type, qualified_type_name) {
|
constructor(mod, type, qualified_type_name, typemap) {
|
||||||
super(type.shortSignature, type.kind(), mapmods(type), type.docs);
|
super(type.shortSignature, type.kind(), mapmods(type), type.docs);
|
||||||
this._decl = type;
|
this._decl = type;
|
||||||
this._dottedTypeName = qualified_type_name.replace(/\$/g, '.');
|
this._dottedTypeName = qualified_type_name.replace(/\$/g, '.');
|
||||||
|
|
||||||
this.extends_types = type.extends_decl ? extractTypeList(type.extends_decl) : [];
|
this.extends_types = type.extends_decl ? extractTypeList(type.extends_decl) : [];
|
||||||
this.implements_types = type.implements_decl ? extractTypeList(type.implements_decl) : [];
|
this.implements_types = type.implements_decl ? extractTypeList(type.implements_decl) : [];
|
||||||
this.implicit_extend = !this.extends_types.length && !this.implements_types.length ? [new ResolvableType({type: 'java.lang.Object', typeTokens:[]})] : [];
|
this.implicit_extend = !this.extends_types.length && !this.implements_types.length ? [typemap.get('java/lang/Object')] : [];
|
||||||
|
|
||||||
this.fields = type.fields.map(f => new SourceField(this, f));
|
this.fields = type.fields.map(f => new SourceField(this, f));
|
||||||
this.methods = type.methods.map(m => new SourceMethod(this, m));
|
this.methods = type.methods.map(m => new SourceMethod(this, m));
|
||||||
@@ -81,7 +82,7 @@ class SourceType extends CEIType {
|
|||||||
|
|
||||||
get supers() {
|
get supers() {
|
||||||
return [
|
return [
|
||||||
...this.implicit_extend.map(t => t.resolved),
|
...this.implicit_extend,
|
||||||
...this.extends_types.map(t => t.resolved),
|
...this.extends_types.map(t => t.resolved),
|
||||||
...this.implements_types.map(t => t.resolved)
|
...this.implements_types.map(t => t.resolved)
|
||||||
];
|
];
|
||||||
@@ -90,7 +91,6 @@ class SourceType extends CEIType {
|
|||||||
getAllResolvableTypes() {
|
getAllResolvableTypes() {
|
||||||
/** @type {ResolvableType[]} */
|
/** @type {ResolvableType[]} */
|
||||||
const res = [
|
const res = [
|
||||||
...this.implicit_extend,
|
|
||||||
...this.extends_types,
|
...this.extends_types,
|
||||||
...this.implements_types,
|
...this.implements_types,
|
||||||
];
|
];
|
||||||
@@ -247,7 +247,7 @@ class ResolvableType extends UnresolvedType {
|
|||||||
constructor(decl) {
|
constructor(decl) {
|
||||||
super(decl.type);
|
super(decl.type);
|
||||||
this._decl = decl;
|
this._decl = decl;
|
||||||
/** @type {import('../java/parsetypes/resolved-type')} */
|
/** @type {JavaType} */
|
||||||
this._resolved = null;
|
this._resolved = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,9 +255,7 @@ class ResolvableType extends UnresolvedType {
|
|||||||
* @returns {JavaType}
|
* @returns {JavaType}
|
||||||
*/
|
*/
|
||||||
get resolved() {
|
get resolved() {
|
||||||
if (!this._resolved) return this;
|
return this._resolved || this;
|
||||||
if (!this._resolved.mtis.length) return this;
|
|
||||||
return this._resolved.mtis[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get typeTokens() {
|
get typeTokens() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const { ArrayType, CEIType, JavaType, WildcardType } = require('java-mti');
|
const { ArrayType, CEIType, JavaType, PrimitiveType, WildcardType } = 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 { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
||||||
@@ -34,30 +34,29 @@ function typeIdentList(tokens, scoped_type, imports, typemap) {
|
|||||||
* @param {Map<string,JavaType>} typemap
|
* @param {Map<string,JavaType>} typemap
|
||||||
*/
|
*/
|
||||||
function typeIdent(tokens, scoped_type, imports, typemap) {
|
function typeIdent(tokens, scoped_type, imports, typemap) {
|
||||||
if (tokens.current.kind !== 'ident') {
|
let types = [], package_name = '';
|
||||||
if (tokens.current.value === '?') {
|
switch(tokens.current.kind) {
|
||||||
return wildcardTypeArgument(tokens, scoped_type, imports, typemap);
|
case 'ident':
|
||||||
|
({ types, package_name } = resolveTypeOrPackage(tokens.current.value, scoped_type, imports, typemap));
|
||||||
|
break;
|
||||||
|
case 'primitive-type':
|
||||||
|
types.push(PrimitiveType.fromName(tokens.current.value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return tokens.current.value === '?'
|
||||||
|
? wildcardTypeArgument(tokens, scoped_type, imports, typemap)
|
||||||
|
: AnyType.Instance;
|
||||||
}
|
}
|
||||||
return AnyType.Instance;
|
|
||||||
}
|
|
||||||
let { types, package_name } = resolveTypeOrPackage(tokens.current.value, scoped_type, imports, typemap);
|
|
||||||
tokens.inc();
|
tokens.inc();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (tokens.isValue('.')) {
|
if (tokens.isValue('.')) {
|
||||||
if (tokens.current.kind !== 'ident') {
|
if (tokens.current.kind !== 'ident') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
resolveNextTypeOrPackage(tokens.current.value, types, package_name, typemap);
|
({ types, package_name } = resolveNextTypeOrPackage(tokens.current.value, types, package_name, typemap));
|
||||||
|
tokens.inc();
|
||||||
} else if (tokens.isValue('<')) {
|
} else if (tokens.isValue('<')) {
|
||||||
if (!tokens.isValue('>')) {
|
genericTypeArgs(tokens, types, scoped_type, imports, typemap);
|
||||||
typeIdentList(tokens, scoped_type, imports, typemap);
|
|
||||||
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('>');
|
|
||||||
}
|
|
||||||
} else if (tokens.isValue('[')) {
|
} else if (tokens.isValue('[')) {
|
||||||
let arrdims = 0;
|
let arrdims = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@@ -79,6 +78,37 @@ function typeIdent(tokens, scoped_type, imports, typemap) {
|
|||||||
return types[0] || AnyType.Instance;
|
return types[0] || AnyType.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {TokenList} tokens
|
||||||
|
* @param {JavaType[]} types
|
||||||
|
* @param {CEIType} scoped_type
|
||||||
|
* @param {ResolvedImport[]} imports
|
||||||
|
* @param {Map<string,JavaType>} typemap
|
||||||
|
*/
|
||||||
|
function genericTypeArgs(tokens, types, scoped_type, imports, typemap) {
|
||||||
|
if (!tokens.isValue('>')) {
|
||||||
|
const type_arguments = typeIdentList(tokens, scoped_type, 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('>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {TokenList} tokens
|
* @param {TokenList} tokens
|
||||||
* @param {CEIType} scoped_type
|
* @param {CEIType} scoped_type
|
||||||
@@ -105,3 +135,4 @@ function wildcardTypeArgument(tokens, scoped_type, imports, typemap) {
|
|||||||
|
|
||||||
exports.typeIdent = typeIdent;
|
exports.typeIdent = typeIdent;
|
||||||
exports.typeIdentList = typeIdentList;
|
exports.typeIdentList = typeIdentList;
|
||||||
|
exports.genericTypeArgs = genericTypeArgs;
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ const { resolveImports } = require('../java/import-resolver');
|
|||||||
const ResolvedImport = require('../java/parsetypes/resolved-import');
|
const ResolvedImport = require('../java/parsetypes/resolved-import');
|
||||||
const { resolveType } = require('../java/type-resolver');
|
const { resolveType } = require('../java/type-resolver');
|
||||||
const { SourceType, SourceConstructor } = require('./source-type');
|
const { SourceType, SourceConstructor } = require('./source-type');
|
||||||
const { parseBody } = require('./body-parser3');
|
const { parseBody, flattenBlocks } = require('./body-parser3');
|
||||||
|
const { TokenList } = require('./TokenList');
|
||||||
|
const { typeIdent } = require('./typeident');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,16 +14,17 @@ const { parseBody } = require('./body-parser3');
|
|||||||
* @param {string} owner_typename
|
* @param {string} owner_typename
|
||||||
* @param {ModuleBlock|TypeDeclBlock} parent
|
* @param {ModuleBlock|TypeDeclBlock} parent
|
||||||
* @param {SourceType[]} source_types
|
* @param {SourceType[]} source_types
|
||||||
|
* @param {Map<string,JavaType>} typemap
|
||||||
*/
|
*/
|
||||||
function getSourceTypes(mod, owner_typename, parent, source_types) {
|
function getSourceTypes(mod, owner_typename, parent, source_types, typemap) {
|
||||||
parent.types.forEach(type => {
|
parent.types.forEach(type => {
|
||||||
const qualifiedTypeName = `${owner_typename}${type.simpleName}`;
|
const qualifiedTypeName = `${owner_typename}${type.simpleName}`;
|
||||||
// we add the names of type variables here, but we resolve any bounds later
|
// we add the names of type variables here, but we resolve any bounds later
|
||||||
//const typevar_names = type.typevars.map(tv => tv.name);
|
//const typevar_names = type.typevars.map(tv => tv.name);
|
||||||
//const mti = new MTI().addType(package_name, '', mods, type.kind(), qualifiedTypeName, typevar_names);
|
//const mti = new MTI().addType(package_name, '', mods, type.kind(), qualifiedTypeName, typevar_names);
|
||||||
const t = new SourceType(mod, type, qualifiedTypeName);
|
const t = new SourceType(mod, type, qualifiedTypeName, typemap);
|
||||||
source_types.push(t);
|
source_types.push(t);
|
||||||
getSourceTypes(mod, `${qualifiedTypeName}$`, type, source_types);
|
getSourceTypes(mod, `${qualifiedTypeName}$`, type, source_types, typemap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,10 +35,10 @@ function getSourceTypes(mod, owner_typename, parent, source_types) {
|
|||||||
* @param {Map<string,JavaType>} typemap
|
* @param {Map<string,JavaType>} typemap
|
||||||
*/
|
*/
|
||||||
function resolveResolvableTypes(source_type, resolved_imports, typemap) {
|
function resolveResolvableTypes(source_type, resolved_imports, typemap) {
|
||||||
const fully_qualified_scope = source_type.shortSignature;
|
|
||||||
const resolvableTypes = source_type.getAllResolvableTypes();
|
const resolvableTypes = source_type.getAllResolvableTypes();
|
||||||
resolvableTypes.forEach(rt => {
|
resolvableTypes.forEach(rt => {
|
||||||
rt._resolved = resolveType(rt.label, fully_qualified_scope, resolved_imports, typemap);
|
const tokens = new TokenList(flattenBlocks(rt.typeTokens, false));
|
||||||
|
rt._resolved = typeIdent(tokens, source_type, resolved_imports, typemap);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +51,7 @@ function validate(mod, androidLibrary) {
|
|||||||
|
|
||||||
/** @type {SourceType[]} */
|
/** @type {SourceType[]} */
|
||||||
const source_types = [];
|
const source_types = [];
|
||||||
getSourceTypes(mod, '', mod, source_types);
|
getSourceTypes(mod, '', mod, source_types, androidLibrary);
|
||||||
|
|
||||||
const imports = resolveImports(androidLibrary, source_types, mod.imports, mod.packageName);
|
const imports = resolveImports(androidLibrary, source_types, mod.imports, mod.packageName);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user