mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
rename source types module
This commit is contained in:
500
langserver/java/source-types.js
Normal file
500
langserver/java/source-types.js
Normal file
@@ -0,0 +1,500 @@
|
||||
const { CEIType, JavaType, PrimitiveType, ArrayType, TypeVariableType, Field, Method, MethodBase, Constructor, Parameter, TypeVariable, TypeArgument } = require('java-mti');
|
||||
const { Token } = require('./tokenizer');
|
||||
|
||||
/**
|
||||
* @typedef {import('./body-types').ResolvedIdent} ResolvedIdent
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {SourceType|SourceMethod|SourceConstructor|SourceInitialiser|string} scope_or_package_name
|
||||
* @param {string} name
|
||||
*/
|
||||
function generateShortSignature(scope_or_package_name, name) {
|
||||
if (scope_or_package_name instanceof SourceType) {
|
||||
const type = scope_or_package_name;
|
||||
return `${type._rawShortSignature}$${name}`;
|
||||
}
|
||||
if (scope_or_package_name instanceof SourceMethod
|
||||
|| scope_or_package_name instanceof SourceConstructor
|
||||
|| scope_or_package_name instanceof SourceInitialiser) {
|
||||
const method = scope_or_package_name;
|
||||
return `${method.owner._rawShortSignature}$${method.owner.localTypeCount += 1}${name}`;
|
||||
}
|
||||
const pkgname = scope_or_package_name;
|
||||
return pkgname ?`${pkgname.replace(/\./g, '/')}/${name}` : name;
|
||||
}
|
||||
|
||||
class SourceType extends CEIType {
|
||||
/**
|
||||
* @param {string} packageName
|
||||
* @param {SourceType|SourceMethod|SourceConstructor|SourceInitialiser} outer_scope
|
||||
* @param {string} docs
|
||||
* @param {Token[]} modifiers
|
||||
* @param {string} typeKind
|
||||
* @param {Token} kind_token
|
||||
* @param {Token} name_token
|
||||
* @param {Map<string,CEIType>} typemap
|
||||
*/
|
||||
constructor(packageName, outer_scope, docs, modifiers, typeKind, kind_token, name_token, typemap) {
|
||||
// @ts-ignore
|
||||
super(generateShortSignature(outer_scope || packageName, name_token.value), typeKind, modifiers.map(m => m.source), docs);
|
||||
super.packageName = packageName;
|
||||
this.modifierTokens = modifiers;
|
||||
this.kind_token = kind_token;
|
||||
this.nameToken = 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 {SourceTypeIdent[]} */
|
||||
this.extends_types = [];
|
||||
/** @type {SourceTypeIdent[]} */
|
||||
this.implements_types = [];
|
||||
/** @type {SourceConstructor[]} */
|
||||
this.constructors = [];
|
||||
/** @type {SourceMethod[]} */
|
||||
this.methods = [];
|
||||
/** @type {SourceField[]} */
|
||||
this.fields = [];
|
||||
/** @type {SourceInitialiser[]} */
|
||||
this.initers = [];
|
||||
/** @type {SourceEnumValue[]} */
|
||||
this.enumValues = [];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Token} ident
|
||||
* @param {ResolvedIdent[]} ctr_args
|
||||
* @param {SourceType} anonymousType
|
||||
*/
|
||||
addEnumValue(ident, ctr_args, anonymousType) {
|
||||
this.enumValues.push(new SourceEnumValue(this, ident, ctr_args, anonymousType));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} package_name
|
||||
* @param {SourceType|SourceMethod|SourceConstructor|SourceInitialiser} outer_scope
|
||||
* @param {string} name
|
||||
*/
|
||||
static getShortSignature(package_name, outer_scope, name) {
|
||||
return generateShortSignature(outer_scope || package_name || '', name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Token[]} mods
|
||||
*/
|
||||
setModifierTokens(mods) {
|
||||
this.modifierTokens = mods;
|
||||
this.modifiers = mods.map(m => m.source);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {JavaType[]} types
|
||||
* @returns {CEIType}
|
||||
*/
|
||||
specialise(types) {
|
||||
const short_sig = `${this.shortSignature}<${types.map(t => t.typeSignature).join('')}>`;
|
||||
if (this.typemap.has(short_sig)) {
|
||||
// @ts-ignore
|
||||
return this.typemap.get(short_sig);
|
||||
}
|
||||
/** @type {'class'|'enum'|'interface'|'@interface'} */
|
||||
// @ts-ignore
|
||||
const typeKind = this.typeKind;
|
||||
const specialised_type = new SpecialisedSourceType(this, typeKind, this._rawShortSignature, types);
|
||||
this.typemap.set(short_sig, specialised_type);
|
||||
return specialised_type;
|
||||
}
|
||||
|
||||
get supers() {
|
||||
const supertypes = [...this.extends_types, ...this.implements_types].map(x => x.resolved);
|
||||
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 SpecialisedSourceType extends CEIType {
|
||||
/**
|
||||
*
|
||||
* @param {SourceType} source_type
|
||||
* @param {'class'|'enum'|'interface'|'@interface'} typeKind
|
||||
* @param {string} raw_short_signature
|
||||
* @param {JavaType[]} types
|
||||
*/
|
||||
constructor(source_type, typeKind, raw_short_signature, types) {
|
||||
super(raw_short_signature, typeKind, source_type.modifiers, source_type.docs);
|
||||
this.typemap = source_type.typemap;
|
||||
/** @type {TypeArgument[]} */
|
||||
// @ts-ignore
|
||||
const type_args = source_type.typeVariables.map((tv, idx) => new TypeArgument(this, tv, types[idx] || this.typemap.get('java/lang/Object')));
|
||||
this.typeVariables = type_args;
|
||||
|
||||
function resolveType(type, typevars = []) {
|
||||
if (type instanceof ArrayType) {
|
||||
return new ArrayType(resolveType(type.base, typevars), type.arrdims);
|
||||
}
|
||||
if (!(type instanceof TypeVariableType)) {
|
||||
return type;
|
||||
}
|
||||
if (typevars.includes(type.typeVariable)) {
|
||||
return type;
|
||||
}
|
||||
const specialised_type = type_args.find(ta => ta.name === type.typeVariable.name);
|
||||
return specialised_type.type;
|
||||
}
|
||||
|
||||
this.fields = source_type.fields.map(f => {
|
||||
const type = this;
|
||||
return new class extends Field {
|
||||
constructor() {
|
||||
super(f.modifiers, f.docs);
|
||||
this.owner = type;
|
||||
this.source = f;
|
||||
this.fieldType = resolveType(f.fieldTypeIdent.resolved);
|
||||
}
|
||||
get name() { return this.source.name }
|
||||
get type() { return this.fieldType }
|
||||
};
|
||||
});
|
||||
|
||||
this.constructors = source_type.constructors.map(c => {
|
||||
const type = this;
|
||||
return new class extends Constructor {
|
||||
constructor() {
|
||||
super(type, c.modifiers, c.docs);
|
||||
this.owner = type;
|
||||
this.source = c;
|
||||
this._parameters = c.sourceParameters.map(p => new Parameter(p.name, resolveType(p.paramTypeIdent.resolved, c.typeVariables), p.varargs));
|
||||
}
|
||||
get hasImplementation() {
|
||||
return !!this.source.body;
|
||||
}
|
||||
get parameters() {
|
||||
return this._parameters;
|
||||
}
|
||||
get returnType() {
|
||||
return this.owner;
|
||||
}
|
||||
get typeVariables() {
|
||||
return this.source.typeVars;
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
this.methods = source_type.methods.map(m => {
|
||||
const type = this;
|
||||
return new class extends Method {
|
||||
constructor() {
|
||||
super(type, m.name, m.modifiers, m.docs);
|
||||
this.owner = type;
|
||||
this.source = m;
|
||||
this._returnType = resolveType(m.returnType, m.typeVars)
|
||||
this._parameters = m.sourceParameters.map(p => new Parameter(p.name, resolveType(p.type, m.typeVars), p.varargs));
|
||||
}
|
||||
get hasImplementation() {
|
||||
return !!this.source.body;
|
||||
}
|
||||
get parameters() {
|
||||
return this._parameters;
|
||||
}
|
||||
get returnType() {
|
||||
return this._returnType;
|
||||
}
|
||||
get typeVariables() {
|
||||
return this.source.typeVars;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class SourceEnumValue extends Field {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token} ident
|
||||
* @param {ResolvedIdent[]} ctr_args
|
||||
* @param {SourceType} anonymousType
|
||||
*/
|
||||
constructor(owner, ident, ctr_args, anonymousType) {
|
||||
super(['public','static','final'], '');
|
||||
this.owner = owner;
|
||||
this.ident = ident;
|
||||
this.value = ctr_args;
|
||||
this.anonymousType = anonymousType;
|
||||
}
|
||||
|
||||
get label() {
|
||||
// don't include the implicit modifiers in the label
|
||||
return `${this.owner.simpleTypeName} ${this.name}`;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.ident.value;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.owner;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceTypeIdent {
|
||||
/**
|
||||
* @param {Token[]} tokens
|
||||
* @param {JavaType} type
|
||||
*/
|
||||
constructor(tokens, type) {
|
||||
this.tokens = tokens;
|
||||
this.resolved = type;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceField extends Field {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceTypeIdent} field_type_ident
|
||||
* @param {Token} name_token
|
||||
* @param {ResolvedIdent} init
|
||||
*/
|
||||
constructor(owner, modifiers, field_type_ident, name_token, init) {
|
||||
super(modifiers.map(m => m.value), '');
|
||||
this.owner = owner;
|
||||
this.modifierTokens = modifiers;
|
||||
this.fieldTypeIdent = field_type_ident;
|
||||
this.nameToken = name_token;
|
||||
this.init = init;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.nameToken ? this.nameToken.value : '';
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.fieldTypeIdent.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceConstructor extends Constructor {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {TypeVariable[]} type_vars
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceParameter[]} parameters
|
||||
* @param {JavaType[]} throws
|
||||
* @param {Token[]} body
|
||||
*/
|
||||
constructor(owner, type_vars, modifiers, parameters, throws, body) {
|
||||
super(owner, modifiers.map(m => m.value), '');
|
||||
this.owner = owner;
|
||||
this.typeVars = type_vars;
|
||||
this.modifierTokens = modifiers;
|
||||
this.sourceParameters = parameters;
|
||||
this.throws = throws;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
get hasImplementation() {
|
||||
return !!this.body;
|
||||
}
|
||||
|
||||
get parameterCount() {
|
||||
return this.sourceParameters.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return this.sourceParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceType}
|
||||
*/
|
||||
get returnType() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
get typeVariables() {
|
||||
return this.typeVars;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceMethod extends Method {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {TypeVariable[]} type_vars
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceAnnotation[]} annotations
|
||||
* @param {SourceTypeIdent} method_type_ident
|
||||
* @param {Token} name_token
|
||||
* @param {SourceParameter[]} parameters
|
||||
* @param {JavaType[]} throws
|
||||
* @param {Token[]} body
|
||||
*/
|
||||
constructor(owner, type_vars, 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.typeVars = type_vars;
|
||||
this.modifierTokens = modifiers;
|
||||
this.returnTypeIdent = method_type_ident;
|
||||
this.nameToken = name_token;
|
||||
this.sourceParameters = parameters;
|
||||
this.throws = throws;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
get hasImplementation() {
|
||||
return !!this.body;
|
||||
}
|
||||
|
||||
get parameterCount() {
|
||||
return this.sourceParameters.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return this.sourceParameters;
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return this.returnTypeIdent.resolved;
|
||||
}
|
||||
|
||||
get typeVariables() {
|
||||
return this.typeVars;
|
||||
}
|
||||
}
|
||||
|
||||
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.modifierTokens = modifiers;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return [];
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return PrimitiveType.map.V;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceParameter extends Parameter {
|
||||
/**
|
||||
* @param {Token[]} modifiers
|
||||
* @param {SourceTypeIdent} typeident
|
||||
* @param {boolean} varargs
|
||||
* @param {Token} name_token
|
||||
*/
|
||||
constructor(modifiers, typeident, varargs, name_token) {
|
||||
super(name_token ? name_token.value : '', typeident.resolved, varargs);
|
||||
this.nameToken = name_token;
|
||||
this.modifierTokens = modifiers;
|
||||
this.paramTypeIdent = typeident;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.paramTypeIdent.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceAnnotation {
|
||||
/**
|
||||
* @param {SourceTypeIdent} typeident
|
||||
*/
|
||||
constructor(typeident) {
|
||||
this.annotationTypeIdent = typeident;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.annotationTypeIdent.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class SourcePackage {
|
||||
/**
|
||||
* @param {Token[]} tokens
|
||||
* @param {string} name
|
||||
*/
|
||||
constructor(tokens, name) {
|
||||
this.tokens = tokens;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceImport {
|
||||
|
||||
/**
|
||||
* @param {Token[]} tokens
|
||||
* @param {Token[]} name_tokens
|
||||
* @param {string} pkg_name
|
||||
* @param {Token} static_token
|
||||
* @param {Token} asterisk_token
|
||||
* @param {import('./parsetypes/resolved-import')} resolved
|
||||
*/
|
||||
constructor(tokens, name_tokens, pkg_name, static_token, asterisk_token, resolved) {
|
||||
this.tokens = tokens;
|
||||
this.nameTokens = name_tokens;
|
||||
this.package_name = pkg_name;
|
||||
this.staticToken = static_token;
|
||||
this.asteriskToken = asterisk_token;
|
||||
this.resolved = resolved;
|
||||
}
|
||||
|
||||
get isDemandLoad() {
|
||||
return !!this.asteriskToken;
|
||||
}
|
||||
|
||||
get isStatic() {
|
||||
return !!this.staticToken;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceUnit {
|
||||
/** @type {SourcePackage} */
|
||||
package_ = null;
|
||||
/** @type {SourceImport[]} */
|
||||
imports = [];
|
||||
/** @type {SourceType[]} */
|
||||
types = [];
|
||||
}
|
||||
|
||||
exports.SourceType = SourceType;
|
||||
exports.SourceTypeIdent = SourceTypeIdent;
|
||||
exports.SourceField = SourceField;
|
||||
exports.SourceMethod = SourceMethod;
|
||||
exports.SourceParameter = SourceParameter;
|
||||
exports.SourceConstructor = SourceConstructor;
|
||||
exports.SourceInitialiser = SourceInitialiser;
|
||||
exports.SourceAnnotation = SourceAnnotation;
|
||||
exports.SourceUnit = SourceUnit;
|
||||
exports.SourcePackage = SourcePackage;
|
||||
exports.SourceImport = SourceImport;
|
||||
Reference in New Issue
Block a user