mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 18:08:29 +00:00
update to use new set of SourceX classes
This commit is contained in:
@@ -6,15 +6,15 @@
|
||||
*/
|
||||
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 { SourceType, SourceTypeIdent, SourceField, SourceMethod, SourceConstructor, SourceInitialiser, SourceParameter, SourceAnnotation } = require('./source-types2');
|
||||
const ResolvedImport = require('./parsetypes/resolved-import');
|
||||
const ParseProblem = require('./parsetypes/parse-problem');
|
||||
const { getOperatorType, Token } = require('./tokenizer');
|
||||
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
||||
const { genericTypeArgs, typeIdent, typeIdentList } = require('./typeident');
|
||||
const { TokenList } = require("./TokenList");
|
||||
const { AnyMethod, AnyType, AnyValue, ArrayElement, ArrayLiteral, ConstructorCall, Label, LiteralNumber, LiteralValue, Local, MethodCall, MethodDeclarations, ResolvedIdent, TernaryValue, Value } = require("./body-types");
|
||||
const { SourceType, SourceField2, SourceMethod2, SourceConstructor2, SourceParameter2 } = require('./source-types2');
|
||||
const { AnyMethod, AnyType, AnyValue, ArrayElement, ArrayLiteral, ConstructorCall, Label, LiteralNumber, LiteralValue, Local,
|
||||
MethodCall, MethodDeclarations, ResolvedIdent, TernaryValue, Value } = require("./body-types");
|
||||
|
||||
/**
|
||||
* @typedef {SourceMethod|SourceConstructor|SourceInitialiser} SourceMC
|
||||
@@ -47,11 +47,11 @@ function flattenBlocks(blocks, isMethod) {
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function parseBody(method, imports, typemap) {
|
||||
const body = method._decl.body().blockArray();
|
||||
if (!body || body.blocks[0].value !== '{') {
|
||||
const body = method.body;
|
||||
if (!body || body[0].value !== '{') {
|
||||
return null;
|
||||
}
|
||||
const tokenlist = new TokenList(flattenBlocks(body.blocks, true));
|
||||
const tokenlist = new TokenList(flattenBlocks(body, true));
|
||||
let block = null;
|
||||
let mdecls = new MethodDeclarations();
|
||||
try {
|
||||
@@ -245,7 +245,7 @@ class AssertStatement extends Statement {
|
||||
*/
|
||||
function localType(modifiers, tokens, mdecls, method, imports, typemap) {
|
||||
// local types are inner types with number-prefixed names, eg. Type$1Inner
|
||||
const type = typeDeclaration(method, modifiers, tokens.current, tokens, imports, typemap);
|
||||
const type = typeDeclaration(method.owner.packageName, method, modifiers, tokens.current, tokens, imports, typemap);
|
||||
mdecls.types.push(type);
|
||||
if (tokens.isValue('extends')) {
|
||||
const extends_types = typeIdentList(tokens, type, imports, typemap);
|
||||
@@ -268,7 +268,7 @@ function localType(modifiers, tokens, mdecls, method, imports, typemap) {
|
||||
*/
|
||||
function typeBody(type, tokens, method, imports, typemap) {
|
||||
while (!tokens.isValue('}')) {
|
||||
let modifiers = [];
|
||||
let modifiers = [], annotations = [];
|
||||
while (tokens.current.kind === 'modifier') {
|
||||
modifiers.push(tokens.current);
|
||||
tokens.inc();
|
||||
@@ -276,7 +276,7 @@ function typeBody(type, tokens, method, imports, typemap) {
|
||||
switch(tokens.current.kind) {
|
||||
case 'ident':
|
||||
case 'primitive-type':
|
||||
fmc(modifiers, [], type, tokens, imports, typemap);
|
||||
fmc(modifiers, annotations, [], type, tokens, imports, typemap);
|
||||
continue;
|
||||
case 'type-kw':
|
||||
localType(modifiers, tokens, new MethodDeclarations(), method, imports, typemap);
|
||||
@@ -285,11 +285,11 @@ function typeBody(type, tokens, method, imports, typemap) {
|
||||
switch(tokens.current.value) {
|
||||
case '<':
|
||||
const type_variables = typeVariableList(type, tokens, type, imports, typemap);
|
||||
fmc(modifiers, type_variables, type, tokens, imports, typemap);
|
||||
fmc(modifiers, annotations, type_variables, type, tokens, imports, typemap);
|
||||
continue;
|
||||
case '@':
|
||||
tokens.inc().value === 'interface'
|
||||
? annotationTypeDeclaration(type, modifiers.splice(0,1e9), tokens, imports, typemap)
|
||||
? annotationTypeDeclaration(type.packageName, type, modifiers.splice(0,1e9), tokens, imports, typemap)
|
||||
: annotation(tokens, type, imports, typemap);
|
||||
continue;
|
||||
case ';':
|
||||
@@ -304,19 +304,20 @@ function typeBody(type, tokens, method, imports, typemap) {
|
||||
|
||||
/**
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceAnnotation[]} annotations
|
||||
* @param {TypeVariable[]} type_variables
|
||||
* @param {SourceType} type
|
||||
* @param {TokenList} tokens
|
||||
* @param {ResolvedImport[]} imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function fmc(modifiers, type_variables, type, tokens, imports, typemap) {
|
||||
function fmc(modifiers, annotations, type_variables, type, tokens, imports, typemap) {
|
||||
const decl_type = typeIdent(tokens, type, imports, typemap);
|
||||
if (decl_type.rawTypeSignature === type.rawTypeSignature) {
|
||||
if (tokens.current.value === '(') {
|
||||
// constructor
|
||||
const { parameters, throws, body } = methodDeclaration(type, tokens, imports, typemap);
|
||||
const ctr = new SourceConstructor2(type, modifiers, parameters, throws, body);
|
||||
const ctr = new SourceConstructor(type, modifiers, parameters, throws, body);
|
||||
type.constructors.push(ctr);
|
||||
return;
|
||||
}
|
||||
@@ -328,7 +329,7 @@ function fmc(modifiers, type_variables, type, tokens, imports, typemap) {
|
||||
}
|
||||
if (tokens.current.value === '(') {
|
||||
const { parameters, throws, body } = methodDeclaration(type, tokens, imports, typemap);
|
||||
const method = new SourceMethod2(type, modifiers, decl_type, name, parameters, throws, body);
|
||||
const method = new SourceMethod(type, modifiers, annotations, new SourceTypeIdent([], decl_type), name, parameters, throws, body);
|
||||
type.methods.push(method);
|
||||
} else {
|
||||
if (name) {
|
||||
@@ -336,7 +337,7 @@ function fmc(modifiers, type_variables, type, tokens, imports, typemap) {
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, `Fields cannot declare type variables`));
|
||||
}
|
||||
const locals = var_ident_list(modifiers, decl_type, name, tokens, new MethodDeclarations(), type, imports, typemap);
|
||||
const fields = locals.map(l => new SourceField2(type, modifiers, l.type, l.decltoken));
|
||||
const fields = locals.map(l => new SourceField(type, modifiers, new SourceTypeIdent([], l.type), l.decltoken));
|
||||
type.fields.push(...fields);
|
||||
}
|
||||
semicolon(tokens);
|
||||
@@ -362,6 +363,7 @@ function annotation(tokens, scope, imports, typemap) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} package_name
|
||||
* @param {SourceType | SourceMC} scope
|
||||
* @param {Token[]} modifiers
|
||||
* @param {TokenList} tokens
|
||||
@@ -369,11 +371,12 @@ function annotation(tokens, scope, imports, typemap) {
|
||||
* @param {ResolvedImport[]} imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function annotationTypeDeclaration(scope, modifiers, tokens, imports, typemap) {
|
||||
const type = typeDeclaration(scope, modifiers, tokens.current, tokens, imports, typemap);
|
||||
function annotationTypeDeclaration(package_name, scope, modifiers, tokens, imports, typemap) {
|
||||
const type = typeDeclaration(package_name, scope, modifiers, tokens.current, tokens, imports, typemap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} package_name
|
||||
* @param {SourceType | SourceMC} scope
|
||||
* @param {Token[]} modifiers
|
||||
* @param {Token} kind_token
|
||||
@@ -381,14 +384,14 @@ function annotationTypeDeclaration(scope, modifiers, tokens, imports, typemap) {
|
||||
* @param {ResolvedImport[]} imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function typeDeclaration(scope, modifiers, kind_token, tokens, imports, typemap) {
|
||||
function typeDeclaration(package_name, scope, modifiers, kind_token, tokens, imports, typemap) {
|
||||
let name = tokens.inc();
|
||||
if (!tokens.isKind('ident')) {
|
||||
name = null;
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, `Type identifier expected`));
|
||||
return;
|
||||
}
|
||||
const type = new SourceType('', scope, '', modifiers.map(m => m.source), kind_token, name);
|
||||
const type = new SourceType(package_name, scope, '', modifiers.map(m => m.source), kind_token, name, typemap);
|
||||
type.typeVariables = tokens.current.value === '<'
|
||||
? typeVariableList(type, tokens, scope, imports, typemap)
|
||||
: [];
|
||||
@@ -516,7 +519,7 @@ function parameterDeclaration(owner, tokens, imports, typemap) {
|
||||
if (varargs) {
|
||||
type = new ArrayType(type, 1);
|
||||
}
|
||||
return new SourceParameter2(modifiers, type, varargs, name_token);
|
||||
return new SourceParameter(modifiers, new SourceTypeIdent([], type), varargs, name_token);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -331,6 +331,10 @@ class DeclaredVariableBlock extends DeclarationBlock {
|
||||
return this.varBlock ? this.varBlock.name : '';
|
||||
}
|
||||
|
||||
get name_token() {
|
||||
return this.varBlock ? this.varBlock.name_token : null;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.varBlock ? this.varBlock.type : '';
|
||||
}
|
||||
@@ -475,6 +479,10 @@ class MethodBlock extends MCBlock {
|
||||
return this.varBlock.name;
|
||||
}
|
||||
|
||||
get name_token() {
|
||||
return this.varBlock.name_token;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.varBlock.type + (this.postNameArrToken ? this.postNameArrToken.source : '');
|
||||
}
|
||||
|
||||
@@ -298,11 +298,14 @@ class ResolvableType extends UnresolvedType {
|
||||
}
|
||||
}
|
||||
|
||||
exports.SourceType = SourceType;
|
||||
exports.SourceField = SourceField;
|
||||
exports.SourceMethod = SourceMethod;
|
||||
exports.SourceParameter = SourceParameter;
|
||||
exports.SourceConstructor = SourceConstructor;
|
||||
const source_types = require('./source-types2');
|
||||
exports.SourceType = source_types.SourceType;
|
||||
exports.SourceTypeIdent = source_types.SourceTypeIdent;
|
||||
exports.SourceField = source_types.SourceField;
|
||||
exports.SourceMethod = source_types.SourceMethod;
|
||||
exports.SourceParameter = source_types.SourceParameter;
|
||||
exports.SourceConstructor = source_types.SourceConstructor;
|
||||
exports.DefaultConstructor = DefaultConstructor;
|
||||
exports.SourceInitialiser = SourceInitialiser;
|
||||
exports.SourceInitialiser = source_types.SourceInitialiser;
|
||||
exports.SourceAnnotation = source_types.SourceAnnotation;
|
||||
exports.ResolvableType = ResolvableType;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const { CEIType, JavaType, Field, Method, Constructor, Parameter } = require('java-mti');
|
||||
const { SourceMethod, SourceConstructor, SourceInitialiser } = require('./source-type');
|
||||
const { CEIType, JavaType, PrimitiveType, Field, Method, MethodBase, Constructor, Parameter } = require('java-mti');
|
||||
const { Token } = require('./tokenizer');
|
||||
|
||||
/**
|
||||
@@ -24,39 +23,69 @@ function generateShortSignature(scope_or_package_name, name) {
|
||||
class SourceType extends CEIType {
|
||||
/**
|
||||
* @param {string} packageName
|
||||
* @param {SourceType|SourceMethod2|SourceConstructor|SourceInitialiser} outer_scope
|
||||
* @param {SourceType|SourceMethod|SourceConstructor|SourceInitialiser} outer_scope
|
||||
* @param {string} docs
|
||||
* @param {string[]} modifiers
|
||||
* @param {Token} kind_token
|
||||
* @param {Token} name_token
|
||||
*/
|
||||
constructor(packageName, outer_scope, docs, modifiers, kind_token, name_token) {
|
||||
constructor(packageName, outer_scope, docs, modifiers, kind_token, name_token, typemap) {
|
||||
// @ts-ignore
|
||||
super(generateShortSignature(outer_scope || packageName, name_token), kind_token.source, modifiers, docs);
|
||||
super.packageName = packageName;
|
||||
this.kind_token = kind_token;
|
||||
this.name_token = name_token;
|
||||
this.scope = outer_scope;
|
||||
this.typemap = typemap;
|
||||
/**
|
||||
* Number of local/anonymous types declared in the scope of this type
|
||||
* The number is used when naming them.
|
||||
*/
|
||||
this.localTypeCount = 0;
|
||||
/** @type {SourceConstructor2[]} */
|
||||
/** @type {SourceTypeIdent[]} */
|
||||
this.extends_types = [];
|
||||
/** @type {SourceTypeIdent[]} */
|
||||
this.implements_types = [];
|
||||
/** @type {SourceConstructor[]} */
|
||||
this.constructors = [];
|
||||
/** @type {SourceMethod2[]} */
|
||||
/** @type {SourceMethod[]} */
|
||||
this.methods = [];
|
||||
/** @type {SourceField2[]} */
|
||||
/** @type {SourceField[]} */
|
||||
this.fields = [];
|
||||
/** @type {SourceInitialiser[]} */
|
||||
this.initers = [];
|
||||
}
|
||||
|
||||
get supers() {
|
||||
const supertypes = [...this.extends_types, ...this.implements_types].map(x => x.type);
|
||||
if (this.typeKind === 'enum') {
|
||||
/** @type {CEIType} */
|
||||
const enumtype = this.typemap.get('java/lang/Enum');
|
||||
supertypes.unshift(enumtype.specialise([this]));
|
||||
}
|
||||
else if (!supertypes.find(type => type.typeKind === 'class')) {
|
||||
supertypes.unshift(this.typemap.get('java/lang/Object'));
|
||||
}
|
||||
return supertypes;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceField2 extends Field {
|
||||
class SourceTypeIdent {
|
||||
/**
|
||||
* @param {Token[]} tokens
|
||||
* @param {JavaType} type
|
||||
*/
|
||||
constructor(tokens, type) {
|
||||
this.typeTokens = tokens;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceField extends Field {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token[]} modifiers
|
||||
* @param {JavaType} field_type
|
||||
* @param {SourceTypeIdent} field_type
|
||||
* @param {Token} name_token
|
||||
*/
|
||||
constructor(owner, modifiers, field_type, name_token) {
|
||||
@@ -71,15 +100,15 @@ class SourceField2 extends Field {
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.fieldType;
|
||||
return this.fieldType.type;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceConstructor2 extends Constructor {
|
||||
class SourceConstructor extends Constructor {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceParameter2[]} parameters
|
||||
* @param {SourceParameter[]} parameters
|
||||
* @param {JavaType[]} throws
|
||||
* @param {Token[]} body
|
||||
*/
|
||||
@@ -88,11 +117,11 @@ class SourceConstructor2 extends Constructor {
|
||||
this.owner = owner;
|
||||
this.sourceParameters = parameters;
|
||||
this.throws = throws;
|
||||
this.body_tokens = body;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
get hasImplementation() {
|
||||
return !!this.body_tokens;
|
||||
return !!this.body;
|
||||
}
|
||||
|
||||
get parameterCount() {
|
||||
@@ -100,7 +129,7 @@ class SourceConstructor2 extends Constructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter2[]}
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return this.sourceParameters;
|
||||
@@ -114,27 +143,29 @@ class SourceConstructor2 extends Constructor {
|
||||
}
|
||||
}
|
||||
|
||||
class SourceMethod2 extends Method {
|
||||
class SourceMethod extends Method {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token[]} modifiers
|
||||
* @param {JavaType} method_type
|
||||
* @param {SourceAnnotation[]} annotations
|
||||
* @param {SourceTypeIdent} method_type_ident
|
||||
* @param {Token} name_token
|
||||
* @param {SourceParameter2[]} parameters
|
||||
* @param {SourceParameter[]} parameters
|
||||
* @param {JavaType[]} throws
|
||||
* @param {Token[]} body
|
||||
*/
|
||||
constructor(owner, modifiers, method_type, name_token, parameters, throws, body) {
|
||||
constructor(owner, modifiers, annotations, method_type_ident, name_token, parameters, throws, body) {
|
||||
super(owner, name_token ? name_token.value : '', modifiers.map(m => m.value), '');
|
||||
this.annotations = annotations;
|
||||
this.owner = owner;
|
||||
this.methodType = method_type;
|
||||
this.methodTypeIdent = method_type_ident;
|
||||
this.sourceParameters = parameters;
|
||||
this.throws = throws;
|
||||
this.body_tokens = body;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
get hasImplementation() {
|
||||
return !!this.body_tokens;
|
||||
return !!this.body;
|
||||
}
|
||||
|
||||
get parameterCount() {
|
||||
@@ -142,7 +173,7 @@ class SourceMethod2 extends Method {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter2[]}
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return this.sourceParameters;
|
||||
@@ -152,26 +183,64 @@ class SourceMethod2 extends Method {
|
||||
* @returns {JavaType}
|
||||
*/
|
||||
get returnType() {
|
||||
return this.methodType;
|
||||
return this.methodTypeIdent.type;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceParameter2 extends Parameter {
|
||||
class SourceInitialiser extends MethodBase {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token[]} modifiers
|
||||
* @param {Token[]} body
|
||||
*/
|
||||
constructor(owner, modifiers, body) {
|
||||
super(owner, modifiers.map(m => m.value), '');
|
||||
/** @type {SourceType} */
|
||||
this.owner = owner;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return [];
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return PrimitiveType.map.V;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceParameter extends Parameter {
|
||||
/**
|
||||
* @param {Token[]} modifiers
|
||||
* @param {JavaType} type
|
||||
* @param {SourceTypeIdent} typeident
|
||||
* @param {boolean} varargs
|
||||
* @param {Token} name_token
|
||||
*/
|
||||
constructor(modifiers, type, varargs, name_token) {
|
||||
super(name_token ? name_token.value : '', type, varargs);
|
||||
constructor(modifiers, typeident, varargs, name_token) {
|
||||
super(name_token ? name_token.value : '', typeident.type, varargs);
|
||||
this.name_token = name_token;
|
||||
this.modifiers = modifiers;
|
||||
this.paramTypeIdent = typeident;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceAnnotation {
|
||||
/**
|
||||
* @param {SourceTypeIdent} typeident
|
||||
*/
|
||||
constructor(typeident) {
|
||||
this.annotationTypeIdent = typeident;
|
||||
}
|
||||
}
|
||||
|
||||
exports.SourceType = SourceType;
|
||||
exports.SourceField2 = SourceField2;
|
||||
exports.SourceMethod2 = SourceMethod2;
|
||||
exports.SourceParameter2 = SourceParameter2;
|
||||
exports.SourceConstructor2 = SourceConstructor2;
|
||||
exports.SourceTypeIdent = SourceTypeIdent;
|
||||
exports.SourceField = SourceField;
|
||||
exports.SourceMethod = SourceMethod;
|
||||
exports.SourceParameter = SourceParameter;
|
||||
exports.SourceConstructor = SourceConstructor;
|
||||
exports.SourceInitialiser = SourceInitialiser;
|
||||
exports.SourceAnnotation = SourceAnnotation;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const { JavaType } = require('java-mti');
|
||||
const { ArrayType, JavaType, TypeVariable } = require('java-mti');
|
||||
const { ModuleBlock, TypeDeclBlock } = require('./parser9');
|
||||
const { resolveImports } = require('../java/import-resolver');
|
||||
const ResolvedImport = require('../java/parsetypes/resolved-import');
|
||||
const { SourceType, SourceMethod, SourceConstructor, ResolvableType } = require('./source-type');
|
||||
const { SourceType, SourceTypeIdent, SourceField, SourceMethod, SourceConstructor, SourceInitialiser, SourceParameter, SourceAnnotation } = require('./source-type');
|
||||
const { parseBody, flattenBlocks } = require('./body-parser3');
|
||||
const { TokenList } = require('./TokenList');
|
||||
const { typeIdent } = require('./typeident');
|
||||
@@ -10,57 +10,102 @@ const { typeIdent } = require('./typeident');
|
||||
|
||||
/**
|
||||
* @param {ModuleBlock} mod
|
||||
* @param {string} owner_typename
|
||||
* @param {SourceType} outer_type
|
||||
* @param {ModuleBlock|TypeDeclBlock} parent
|
||||
* @param {SourceType[]} source_types
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function getSourceTypes(mod, owner_typename, parent, source_types, typemap) {
|
||||
function getSourceTypes(mod, outer_type, parent, source_types, typemap) {
|
||||
parent.types.forEach(type => {
|
||||
const qualifiedTypeName = `${owner_typename}${type.simpleName}`;
|
||||
// we add the names of type variables here, but we resolve any bounds later
|
||||
//const typevar_names = type.typevars.map(tv => tv.name);
|
||||
//const mti = new MTI().addType(package_name, '', mods, type.kind(), qualifiedTypeName, typevar_names);
|
||||
const t = new SourceType(mod, type, qualifiedTypeName, typemap);
|
||||
const t = new SourceType(mod.packageName, outer_type, '', type.modifiers.map(m => m.value), type.kindToken, type.name_token, typemap);
|
||||
t.typeVariables = type.typevars.map(tv => new TypeVariable(t, tv.name, [new TypeVariable.Bound(t, 'Ljava/lang/Object;', false)]));
|
||||
source_types.push(t);
|
||||
getSourceTypes(mod, `${qualifiedTypeName}$`, type, source_types, typemap);
|
||||
getSourceTypes(mod, t, type, source_types, typemap);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvableType} rt
|
||||
* @param {SourceType|SourceMethod|SourceConstructor} scope
|
||||
* @param {ResolvedImport[]} resolved_imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
* @param {TokenList} tokens
|
||||
* @param {ModuleBlock|TypeDeclBlock} parent
|
||||
* @param {ResolvedImport[]} imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function resolveResolvableType(rt, scope, resolved_imports, typemap) {
|
||||
const tokens = new TokenList(flattenBlocks(rt.typeTokens, false));
|
||||
rt._resolved = typeIdent(tokens, scope, resolved_imports, typemap);
|
||||
}
|
||||
function populateTypes(tokens, parent, imports, typemap) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SourceType} source_type
|
||||
* @param {ResolvedImport[]} resolved_imports
|
||||
* @param {Map<string,JavaType>} typemap
|
||||
*/
|
||||
function resolveResolvableTypes(source_type, resolved_imports, typemap) {
|
||||
source_type.extends_types.forEach(rt => resolveResolvableType(rt, source_type, resolved_imports, typemap));
|
||||
source_type.implements_types.forEach(rt => resolveResolvableType(rt, source_type, resolved_imports, typemap));
|
||||
|
||||
source_type.fields.forEach(f => resolveResolvableType(f._type, source_type, resolved_imports, typemap));
|
||||
|
||||
// methods and constructors can have parameterized types
|
||||
source_type.methods.forEach(m => {
|
||||
resolveResolvableType(m._returnType, m, resolved_imports, typemap);
|
||||
m.parameters.forEach(p => resolveResolvableType(p._paramType, m, resolved_imports, typemap));
|
||||
parent.types.forEach(type => {
|
||||
const source_type = typemap.get(type.shortSignature);
|
||||
if (source_type instanceof SourceType) {
|
||||
if (type.extends_decl)
|
||||
source_type.extends_types = resolveTypeList(source_type, type.extends_decl);
|
||||
if (type.implements_decl)
|
||||
source_type.implements_types = resolveTypeList(source_type, type.implements_decl);
|
||||
|
||||
// fields
|
||||
source_type.fields = type.fields.map(f => {
|
||||
const field_type = resolveTypeFromTokens(source_type, f);
|
||||
return new SourceField(source_type, f.modifiers, field_type, f.name_token);
|
||||
});
|
||||
// methods
|
||||
source_type.methods = type.methods.map(m => {
|
||||
const method_type = resolveTypeFromTokens(source_type, m);
|
||||
const params = m.parameters.map(p => {
|
||||
let param_type = resolveTypeFromTokens(source_type, p);
|
||||
return new SourceParameter(p.modifiers, param_type, p.isVarArgs, p.name_token);
|
||||
})
|
||||
const annotations = m.annotations.map(a => new SourceAnnotation(resolveTypeFromTokens(source_type, {typeTokens: [a.blockArray().blocks.slice().pop()]})))
|
||||
return new SourceMethod(source_type, m.modifiers, annotations, method_type, m.name_token, params, [], flattenBlocks([m.body()], true));
|
||||
})
|
||||
// constructors
|
||||
source_type.constructors = type.constructors.map(c => {
|
||||
const params = c.parameters.map(p => {
|
||||
const param_type = resolveTypeFromTokens(source_type, p);
|
||||
return new SourceParameter(p.modifiers, param_type, p.isVarArgs, p.name_token);
|
||||
})
|
||||
return new SourceConstructor(source_type, c.modifiers, params, [], flattenBlocks([c.body()], true));
|
||||
})
|
||||
// initialisers
|
||||
source_type.initers = type.initialisers.map(i => {
|
||||
return new SourceInitialiser(source_type, i.modifiers, flattenBlocks([i.body()], true));
|
||||
})
|
||||
}
|
||||
populateTypes(tokens, type, imports, typemap);
|
||||
});
|
||||
|
||||
source_type.declaredConstructors.forEach(c => {
|
||||
c.parameters.forEach(p => resolveResolvableType(p._paramType, c, resolved_imports, typemap));
|
||||
});
|
||||
function resolveTypeFromTokens(scope, decl) {
|
||||
const typetokens = flattenBlocks([decl.typeTokens[0]], false);
|
||||
tokens.current = tokens.tokens[tokens.idx = tokens.tokens.indexOf(typetokens[0])];
|
||||
let type = typeIdent(tokens, scope, imports, typemap);
|
||||
if (decl.varBlock && decl.varBlock.post_name_arr_token) {
|
||||
type = new ArrayType(type, decl.varBlock.post_name_arr_token.source.replace(/[^\[]/g,'').length);
|
||||
}
|
||||
if (decl.isVarArgs) {
|
||||
type = new ArrayType(type, 1);
|
||||
}
|
||||
return new SourceTypeIdent(typetokens, type);
|
||||
}
|
||||
|
||||
function resolveTypeList(scope, eit_decl) {
|
||||
const types = [];
|
||||
const eit_tokens = flattenBlocks([eit_decl], false);
|
||||
tokens.current = tokens.tokens[tokens.idx = tokens.tokens.indexOf(eit_tokens[0])];
|
||||
tokens.inc(); // bypass extends/implements/throws keyword
|
||||
for (;;) {
|
||||
const start = tokens.idx;
|
||||
const type = typeIdent(tokens, scope, imports, typemap);
|
||||
let end = tokens.idx - 1;
|
||||
while (tokens.tokens[end].kind === 'wsc') {
|
||||
end -= 1;
|
||||
}
|
||||
types.push(new SourceTypeIdent(tokens.tokens.slice(start, end + 1), type));
|
||||
if (!tokens.isValue(',')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {ModuleBlock} mod
|
||||
* @param {Map<string, JavaType>} androidLibrary
|
||||
@@ -70,30 +115,25 @@ function validate(mod, androidLibrary) {
|
||||
|
||||
/** @type {SourceType[]} */
|
||||
const source_types = [];
|
||||
getSourceTypes(mod, '', mod, source_types, androidLibrary);
|
||||
getSourceTypes(mod, null, mod, source_types, androidLibrary);
|
||||
|
||||
const imports = resolveImports(androidLibrary, source_types, mod.imports, mod.packageName);
|
||||
|
||||
source_types.forEach(t => {
|
||||
resolveResolvableTypes(t, imports.resolved, imports.typemap);
|
||||
});
|
||||
populateTypes(new TokenList(flattenBlocks(mod.blocks, false)), mod, imports.resolved, imports.typemap);
|
||||
|
||||
let probs = [];
|
||||
source_types.forEach(t => {
|
||||
t.initers.forEach(i => {
|
||||
console.log('<clinit>()');
|
||||
const parsed = parseBody(i, imports.resolved, imports.typemap);
|
||||
if (parsed)
|
||||
probs = probs.concat(parsed.problems)
|
||||
})
|
||||
t.declaredConstructors.forEach(c => {
|
||||
console.log(c.label);
|
||||
t.constructors.forEach(c => {
|
||||
const parsed = parseBody(c, imports.resolved, imports.typemap);
|
||||
if (parsed)
|
||||
probs = probs.concat(parsed.problems)
|
||||
})
|
||||
t.methods.forEach(m => {
|
||||
console.log(m.label);
|
||||
const parsed = parseBody(m, imports.resolved, imports.typemap);
|
||||
if (parsed)
|
||||
probs = probs.concat(parsed.problems)
|
||||
@@ -107,7 +147,6 @@ function validate(mod, androidLibrary) {
|
||||
require('./validation/parse-errors'),
|
||||
require('./validation/modifier-errors'),
|
||||
require('./validation/unresolved-imports'),
|
||||
require('./validation/unresolved-types'),
|
||||
require('./validation/invalid-types'),
|
||||
require('./validation/bad-extends'),
|
||||
require('./validation/bad-implements'),
|
||||
|
||||
@@ -10,7 +10,7 @@ function checkExtends(source_type, probs) {
|
||||
if (source_type.extends_types.length === 0) {
|
||||
return;
|
||||
}
|
||||
const supertypes = source_type.extends_types.map(st => st.resolved);
|
||||
const supertypes = source_type.extends_types.map(st => st.type);
|
||||
const supertype = supertypes[0];
|
||||
if (source_type.typeKind === 'enum') {
|
||||
probs.push(ParseProblem.Error(source_type.extends_types[0].typeTokens, `Enum types cannot declare a superclass`));
|
||||
|
||||
@@ -11,7 +11,7 @@ function checkImplements(source_type, probs) {
|
||||
if (source_type.implements_types.length === 0) {
|
||||
return;
|
||||
}
|
||||
const interfaces = source_type.implements_types.map(it => it.resolved);
|
||||
const interfaces = source_type.implements_types.map(it => it.type);
|
||||
if (source_type.typeKind === 'interface') {
|
||||
probs.push(ParseProblem.Error(source_type.implements_types[0].typeTokens, `Interface types cannot declare an implements section`));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { ModuleBlock, TextBlock } = require('../parser9');
|
||||
const { ModuleBlock } = require('../parser9');
|
||||
const ParseProblem = require('../parsetypes/parse-problem');
|
||||
const {SourceType} = require('../source-type');
|
||||
const {SourceType, SourceAnnotation} = require('../source-type');
|
||||
const {CEIType, Method} = require('java-mti');
|
||||
|
||||
function nonAbstractLabel(label) {
|
||||
@@ -19,10 +19,10 @@ function checkOverrides(source_type, probs) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @type {{ann:TextBlock, method:Method, method_id:string}[]} */
|
||||
/** @type {{ann:SourceAnnotation, method:Method, method_id:string}[]} */
|
||||
const overriden_methods = [];
|
||||
source_type.methods.reduce((arr, method) => {
|
||||
const ann = method._decl.annotations.find(a => /^@\s*Override$/.test(a.source));
|
||||
const ann = method.annotations.find(a => /^Override$/.test(a.annotationTypeIdent.type.simpleTypeName));
|
||||
if (ann) {
|
||||
arr.push({
|
||||
ann,
|
||||
@@ -52,7 +52,7 @@ function checkOverrides(source_type, probs) {
|
||||
|
||||
overriden_methods.forEach(x => {
|
||||
if (!methods.has(x.method_id)) {
|
||||
probs.push(ParseProblem.Error(x.ann, `${x.method.label} does not override a matching method in any inherited type or interface`));
|
||||
probs.push(ParseProblem.Error(x.ann.annotationTypeIdent.typeTokens, `${x.method.label} does not override a matching method in any inherited type or interface`));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
const { ModuleBlock, TypeDeclBlock } = require('../parser9');
|
||||
const { ModuleBlock } = require('../parser9');
|
||||
const ParseProblem = require('../parsetypes/parse-problem');
|
||||
const {SourceType} = require('../source-type');
|
||||
const {JavaType, ArrayType, CEIType, TypeArgument, UnresolvedType} = require('java-mti');
|
||||
const { AnyType } = require('../body-types');
|
||||
const {Token} = require('../tokenizer');
|
||||
const {JavaType} = require('java-mti');
|
||||
|
||||
/**
|
||||
* @param {JavaType} type
|
||||
* @param {boolean} is_return_type
|
||||
* @param {Token[]} typeTokens
|
||||
* @param {ParseProblem[]} probs
|
||||
*/
|
||||
function checkType(type, is_return_type, typeTokens, probs) {
|
||||
const typesig = type.typeSignature;
|
||||
@@ -26,11 +29,11 @@ function checkType(type, is_return_type, typeTokens, probs) {
|
||||
* @param {*} probs
|
||||
*/
|
||||
function checkInvalidTypes(type, probs) {
|
||||
type.fields.forEach(f => checkType(f.type, false, f._decl.typeTokens, probs));
|
||||
type.fields.forEach(f => checkType(f.type, false, f.fieldType.typeTokens, probs));
|
||||
type.methods.forEach(m => {
|
||||
checkType(m.returnType, true, m._decl.typeTokens, probs);
|
||||
checkType(m.returnType, true, m.methodTypeIdent.typeTokens, probs);
|
||||
m.parameters.forEach(p => {
|
||||
checkType(p.type, false, p._decl.typeTokens, probs);
|
||||
checkType(p.type, false, p.paramTypeIdent.typeTokens, probs);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ function checkConstructor(source_type, probs) {
|
||||
if (!superclass.constructors.find(c => c.parameterCount === 0)) {
|
||||
// the source type has no declared constructors, but the superclass
|
||||
// does not include a default (parameterless) constructor
|
||||
probs.push(ParseProblem.Error(source_type._decl.name_token, `Type ${superclass.fullyDottedRawName} requires a constructor to be declared because the inherited class '${superclass.fullyDottedRawName}' does not define a default constructor.`));
|
||||
probs.push(ParseProblem.Error(source_type.name_token, `Class '${source_type.fullyDottedRawName}' requires a constructor to be declared because the inherited class '${superclass.fullyDottedRawName}' does not define a default constructor.`));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ function checkImplementedInterfaces(source_type, probs) {
|
||||
}
|
||||
})
|
||||
if (missing_methods.length) {
|
||||
probs.push(ParseProblem.Error(source_type._decl.kindToken, `Non-abstract ${source_type.typeKind} '${source_type.fullyDottedRawName}' does not implement the following methods from interface '${intf.fullyDottedRawName}':\n${missing_methods.join('\n')}`));
|
||||
probs.push(ParseProblem.Error(source_type.kind_token, `Non-abstract ${source_type.typeKind} '${source_type.fullyDottedRawName}' does not implement the following methods from interface '${intf.fullyDottedRawName}':\n${missing_methods.join('\n')}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
const { ModuleBlock, TypeDeclBlock } = require('../parser9');
|
||||
const ParseProblem = require('../parsetypes/parse-problem');
|
||||
const {SourceType} = require('../source-type');
|
||||
const {JavaType, CEIType, TypeArgument, UnresolvedType} = require('java-mti')
|
||||
|
||||
/**
|
||||
* @param {JavaType} type
|
||||
*/
|
||||
function checkType(type, typeTokens, probs) {
|
||||
if (type instanceof UnresolvedType) {
|
||||
probs.push(ParseProblem.Error(typeTokens, `Unknown type: ${type.label}`));
|
||||
return;
|
||||
}
|
||||
if (type instanceof CEIType) {
|
||||
type.typeVariables.forEach(tv => {
|
||||
if (tv instanceof TypeArgument) {
|
||||
checkType(tv.type, typeTokens, probs);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SourceType} type
|
||||
* @param {*} probs
|
||||
*/
|
||||
function checkUnresolvedTypes(type, probs) {
|
||||
type.extends_types.forEach(superclass => checkType(superclass.resolved, superclass.typeTokens, probs));
|
||||
type.implements_types.forEach(superintf => checkType(superintf.resolved, superintf.typeTokens, probs));
|
||||
type.fields.forEach(f => checkType(f.type, f._decl.typeTokens, probs));
|
||||
type.methods.forEach(m => {
|
||||
checkType(m.returnType, m._decl.typeTokens, probs);
|
||||
m.parameters.forEach(p => {
|
||||
checkType(p.type, p._decl.typeTokens, probs);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {ModuleBlock} mod
|
||||
* @param {*} imports
|
||||
* @param {SourceType[]} source_types
|
||||
*/
|
||||
module.exports = function(mod, imports, source_types) {
|
||||
/** @type {ParseProblem[]} */
|
||||
const probs = [];
|
||||
|
||||
source_types.forEach(type => checkUnresolvedTypes(type, probs));
|
||||
|
||||
return probs;
|
||||
}
|
||||
Reference in New Issue
Block a user