mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
support package name as a resolved value
This commit is contained in:
@@ -37,7 +37,11 @@ class TokenList {
|
|||||||
markEnd() {
|
markEnd() {
|
||||||
let i = this.idx;
|
let i = this.idx;
|
||||||
while (this.tokens[--i].kind === 'wsc') { }
|
while (this.tokens[--i].kind === 'wsc') { }
|
||||||
return this.tokens.slice(this.marks.shift(), i + 1);
|
const range = [this.marks.shift(), i + 1];
|
||||||
|
if (range[1] <= range[0]) {
|
||||||
|
range[1] = range[0] + 1;
|
||||||
|
}
|
||||||
|
return this.tokens.slice(range[0], range[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ class AnyValue extends Expression {
|
|||||||
this.label = label;
|
this.label = label;
|
||||||
this.type = AnyType.Instance;
|
this.type = AnyType.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolveExpression() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,6 +104,21 @@ class TypeIdentType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom type used to represent package name expressions
|
||||||
|
*
|
||||||
|
* eg. `java`
|
||||||
|
*/
|
||||||
|
class PackageNameType {
|
||||||
|
/**
|
||||||
|
* @param {string} package_name
|
||||||
|
*/
|
||||||
|
constructor(package_name) {
|
||||||
|
this.package_name = package_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom type used to represent an array literal
|
* Custom type used to represent an array literal
|
||||||
*
|
*
|
||||||
@@ -131,7 +150,7 @@ class MultiValueType {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./expressiontypes/literals/Number').NumberLiteral} NumberLiteral
|
* @typedef {import('./expressiontypes/literals/Number').NumberLiteral} NumberLiteral
|
||||||
* @typedef {JavaType|MethodType|LambdaType|ArrayValueType|TypeIdentType|MultiValueType|NumberLiteral} ResolvedValue
|
* @typedef {JavaType|MethodType|LambdaType|ArrayValueType|TypeIdentType|PackageNameType|MultiValueType|NumberLiteral} ResolvedValue
|
||||||
**/
|
**/
|
||||||
|
|
||||||
exports.AnyMethod = AnyMethod;
|
exports.AnyMethod = AnyMethod;
|
||||||
@@ -141,4 +160,5 @@ exports.ArrayValueType = ArrayValueType;
|
|||||||
exports.LambdaType = LambdaType;
|
exports.LambdaType = LambdaType;
|
||||||
exports.MethodType = MethodType;
|
exports.MethodType = MethodType;
|
||||||
exports.MultiValueType = MultiValueType;
|
exports.MultiValueType = MultiValueType;
|
||||||
|
exports.PackageNameType = PackageNameType;
|
||||||
exports.TypeIdentType = TypeIdentType;
|
exports.TypeIdentType = TypeIdentType;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
const { JavaType, CEIType, ArrayType, Method } = require('java-mti');
|
const { JavaType, CEIType, ArrayType, Method } = require('java-mti');
|
||||||
const { Token } = require('./tokenizer');
|
const { Token } = require('./tokenizer');
|
||||||
const { AnyType, MethodType, TypeIdentType } = require('./anys');
|
const { AnyType, MethodType, PackageNameType, TypeIdentType } = require('./anys');
|
||||||
const ParseProblem = require('./parsetypes/parse-problem');
|
const ParseProblem = require('./parsetypes/parse-problem');
|
||||||
|
|
||||||
|
|
||||||
@@ -40,10 +40,12 @@ class ResolvedIdent {
|
|||||||
if (this.types[0]) {
|
if (this.types[0]) {
|
||||||
return new TypeIdentType(this.types[0]);
|
return new TypeIdentType(this.types[0]);
|
||||||
}
|
}
|
||||||
|
if (this.package_name) {
|
||||||
|
return new PackageNameType(this.package_name);
|
||||||
|
}
|
||||||
ri.problems.push(ParseProblem.Error(this.tokens, `Unresolved identifier: ${this.source}`));
|
ri.problems.push(ParseProblem.Error(this.tokens, `Unresolved identifier: ${this.source}`));
|
||||||
return AnyType.Instance;
|
return AnyType.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Local {
|
class Local {
|
||||||
@@ -98,7 +100,13 @@ class MethodDeclarations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
popScope() {
|
popScope() {
|
||||||
[this.locals, this.labels, this.types] = this._scopeStack.pop();
|
const prev = {
|
||||||
|
locals: this.locals,
|
||||||
|
labels: this.labels,
|
||||||
|
types: this.types,
|
||||||
|
};
|
||||||
|
([this.locals, this.labels, this.types] = this._scopeStack.pop());
|
||||||
|
return prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Expression {
|
|||||||
* @returns {ResolvedValue}
|
* @returns {ResolvedValue}
|
||||||
*/
|
*/
|
||||||
resolveExpression(ri) {
|
resolveExpression(ri) {
|
||||||
throw new Error('Expression.resolveType');
|
throw new Error('Expression.resolveExpression');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Token|Token[]} */
|
/** @returns {Token|Token[]} */
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class LambdaExpression extends Expression {
|
|||||||
/**
|
/**
|
||||||
* @param {ResolveInfo} ri
|
* @param {ResolveInfo} ri
|
||||||
*/
|
*/
|
||||||
resolveType(ri) {
|
resolveExpression(ri) {
|
||||||
return new LambdaType();
|
return new LambdaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
const { Expression } = require("./Expression");
|
const { Expression } = require("./Expression");
|
||||||
const { CEIType } = require('java-mti');
|
const { CEIType } = require('java-mti');
|
||||||
const { AnyType, MethodType, TypeIdentType } = require('../anys');
|
const { AnyType, MethodType, PackageNameType, TypeIdentType } = require('../anys');
|
||||||
const { getTypeInheritanceList } = require('../expression-resolver');
|
const { getTypeInheritanceList } = require('../expression-resolver');
|
||||||
|
const { resolveNextPackage } = require('../type-resolver');
|
||||||
const ParseProblem = require('../parsetypes/parse-problem');
|
const ParseProblem = require('../parsetypes/parse-problem');
|
||||||
|
|
||||||
class MemberExpression extends Expression {
|
class MemberExpression extends Expression {
|
||||||
@@ -25,25 +26,36 @@ class MemberExpression extends Expression {
|
|||||||
* @param {ResolveInfo} ri
|
* @param {ResolveInfo} ri
|
||||||
*/
|
*/
|
||||||
resolveExpression(ri) {
|
resolveExpression(ri) {
|
||||||
let type = this.instance.resolveExpression(ri);
|
let instance = this.instance.resolveExpression(ri);
|
||||||
if (type instanceof TypeIdentType) {
|
if (instance instanceof TypeIdentType) {
|
||||||
// static member
|
// static member
|
||||||
type = type.type;
|
instance = instance.type;
|
||||||
}
|
}
|
||||||
if (type instanceof AnyType) {
|
if (instance instanceof AnyType) {
|
||||||
return type;
|
return instance;
|
||||||
}
|
}
|
||||||
const ident = this.member.value;
|
const ident = this.member.value;
|
||||||
if (!(type instanceof CEIType)) {
|
|
||||||
|
if (instance instanceof PackageNameType) {
|
||||||
|
const { sub_package_name, type } = resolveNextPackage(instance.package_name, ident, ri.typemap);
|
||||||
|
if (!type && !sub_package_name) {
|
||||||
|
ri.problems.push(ParseProblem.Error(this.member, `Unresolved identifier: '${ident}'`));
|
||||||
|
}
|
||||||
|
return type ? new TypeIdentType(type)
|
||||||
|
: sub_package_name ? new PackageNameType(sub_package_name)
|
||||||
|
: AnyType.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(instance instanceof CEIType)) {
|
||||||
ri.problems.push(ParseProblem.Error(this.member, `Unresolved member: '${ident}'`));
|
ri.problems.push(ParseProblem.Error(this.member, `Unresolved member: '${ident}'`));
|
||||||
return AnyType.Instance;
|
return AnyType.Instance;
|
||||||
}
|
}
|
||||||
const field = type.fields.find(f => f.name === ident);
|
const field = instance.fields.find(f => f.name === ident);
|
||||||
if (field) {
|
if (field) {
|
||||||
return field.type;
|
return field.type;
|
||||||
}
|
}
|
||||||
let methods = new Map();
|
let methods = new Map();
|
||||||
getTypeInheritanceList(type).forEach(type => {
|
getTypeInheritanceList(instance).forEach(type => {
|
||||||
type.methods.forEach(m => {
|
type.methods.forEach(m => {
|
||||||
let msig;
|
let msig;
|
||||||
if (m.name === ident && !methods.has(msig = m.methodSignature)) {
|
if (m.name === ident && !methods.has(msig = m.methodSignature)) {
|
||||||
@@ -54,7 +66,7 @@ class MemberExpression extends Expression {
|
|||||||
if (methods.size > 0) {
|
if (methods.size > 0) {
|
||||||
return new MethodType([...methods.values()]);
|
return new MethodType([...methods.values()]);
|
||||||
}
|
}
|
||||||
ri.problems.push(ParseProblem.Error(this.member, `Unresolved member: '${ident}' in type '${type.fullyDottedRawName}'`));
|
ri.problems.push(ParseProblem.Error(this.member, `Unresolved member: '${ident}' in type '${instance.fullyDottedRawName}'`));
|
||||||
return AnyType.Instance;
|
return AnyType.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Variable extends Expression {
|
|||||||
/**
|
/**
|
||||||
* @param {ResolveInfo} ri
|
* @param {ResolveInfo} ri
|
||||||
*/
|
*/
|
||||||
resolveType(ri) {
|
resolveExpression(ri) {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class InstanceLiteral extends LiteralValue {
|
|||||||
*/
|
*/
|
||||||
constructor(token, scoped_type) {
|
constructor(token, scoped_type) {
|
||||||
super(token, null);
|
super(token, null);
|
||||||
|
this.token = token;
|
||||||
this.scoped_type = scoped_type;
|
this.scoped_type = scoped_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,16 +364,11 @@ function resolveNextTypeOrPackage(ident, outer_types, outer_package_name, typema
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (outer_package_name) {
|
if (outer_package_name) {
|
||||||
const type_match = `${outer_package_name}/${ident}`;
|
const { type, sub_package_name } = resolveNextPackage(outer_package_name, ident, typemap);
|
||||||
if (typemap.has(type_match)) {
|
if (type) {
|
||||||
// it matches a type
|
types.push(type);
|
||||||
types.push(typemap.get(type_match));
|
|
||||||
}
|
|
||||||
const package_match = type_match + '/';
|
|
||||||
if ([...typemap.keys()].find(fqn => fqn.startsWith(package_match))) {
|
|
||||||
// it matches a sub-package
|
|
||||||
package_name = type_match;
|
|
||||||
}
|
}
|
||||||
|
package_name = sub_package_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -382,6 +377,27 @@ function resolveNextTypeOrPackage(ident, outer_types, outer_package_name, typema
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} package_name
|
||||||
|
* @param {string} ident
|
||||||
|
* @param {TypeMap} typemap
|
||||||
|
*/
|
||||||
|
function resolveNextPackage(package_name, ident, typemap) {
|
||||||
|
let type = null, sub_package_name = '';
|
||||||
|
const qualified_name = `${package_name}/${ident}`;
|
||||||
|
type = typemap.get(qualified_name) || null;
|
||||||
|
const package_match = qualified_name + '/';
|
||||||
|
if ([...typemap.keys()].find(fqn => fqn.startsWith(package_match))) {
|
||||||
|
// it matches a sub-package
|
||||||
|
sub_package_name = qualified_name;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
sub_package_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
parse_type,
|
parse_type,
|
||||||
resolveType,
|
resolveType,
|
||||||
@@ -390,4 +406,5 @@ module.exports = {
|
|||||||
ResolvedType,
|
ResolvedType,
|
||||||
resolveTypeOrPackage,
|
resolveTypeOrPackage,
|
||||||
resolveNextTypeOrPackage,
|
resolveNextTypeOrPackage,
|
||||||
|
resolveNextPackage,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user