mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
updated validation to use new JavaTypes module instead of MTIs
This commit is contained in:
182
langserver/java/source-type.js
Normal file
182
langserver/java/source-type.js
Normal file
@@ -0,0 +1,182 @@
|
||||
const { JavaType, CEIType, Method, Field, Parameter, TypeVariable, UnresolvedType } = require('java-mti');
|
||||
const { ModuleBlock, TypeDeclBlock, FieldBlock, MethodBlock, ParameterBlock, TextBlock } = require('./parser9');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{modifiers:TextBlock[]}} x
|
||||
*/
|
||||
function mapmods(x) {
|
||||
return x.modifiers.map(m => m.source);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {TextBlock} decl
|
||||
*/
|
||||
function extractTypeList(decl) {
|
||||
if (!decl) {
|
||||
return [];
|
||||
}
|
||||
const types = [];
|
||||
const re = /[WD]( *[WDT.])*/g;
|
||||
const declba = decl.blockArray();
|
||||
const sm = declba.sourcemap();
|
||||
for (let m; m = re.exec(sm.simplified);) {
|
||||
const start = sm.map[m.index], end = sm.map[m.index + m[0].length-1];
|
||||
const block_range = declba.blocks.slice(start, end+1);
|
||||
types.push(block_range);
|
||||
}
|
||||
return types.map(tokens => {
|
||||
const decl = {
|
||||
type: tokens.map(t => t.source).join(''),
|
||||
typeTokens: tokens,
|
||||
}
|
||||
return new ResolvableType(decl);
|
||||
});
|
||||
}
|
||||
|
||||
class SourceType extends CEIType {
|
||||
/**
|
||||
* @param {ModuleBlock} mod
|
||||
* @param {TypeDeclBlock} type
|
||||
* @param {string} qualified_type_name qualified $-separated type name
|
||||
*/
|
||||
constructor(mod, type, qualified_type_name) {
|
||||
super(type.shortSignature, type.kind(), mapmods(type), type.docs);
|
||||
this._decl = type;
|
||||
super.packageName = mod.packageName;
|
||||
super.simpleTypeName = type.simpleName;
|
||||
super.dottedTypeName = qualified_type_name.replace(/\$/g, '.');
|
||||
super.fullyDottedRawName = type.fullyDottedName;
|
||||
|
||||
this.extends_types = type.extends_decl ? extractTypeList(type.extends_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.fields = type.fields.map(f => new SourceField(this, f));
|
||||
this.methods = type.methods.map(m => new SourceMethod(this, m));
|
||||
super.typevars = type.typevars.map(tv => {
|
||||
const typevar = new TypeVariable(tv.name);
|
||||
// automatically add the Object bound
|
||||
typevar.bounds.push(new TypeVariable.Bound(this, 'Ljava/lang/Object;', false));
|
||||
return typevar;
|
||||
});
|
||||
}
|
||||
|
||||
get supers() {
|
||||
return [
|
||||
...this.implicit_extend.map(t => t.resolved),
|
||||
...this.extends_types.map(t => t.resolved),
|
||||
...this.implements_types.map(t => t.resolved)
|
||||
];
|
||||
}
|
||||
|
||||
getAllResolvableTypes() {
|
||||
/** @type {ResolvableType[]} */
|
||||
const res = [
|
||||
...this.implicit_extend,
|
||||
...this.extends_types,
|
||||
...this.implements_types,
|
||||
];
|
||||
this.fields.forEach(f => res.push(f._type));
|
||||
this.methods.forEach(m => {
|
||||
res.push(m._returnType);
|
||||
m.parameters.forEach(p => res.push(p._paramType));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceField extends Field {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {FieldBlock} decl
|
||||
*/
|
||||
constructor(owner, decl) {
|
||||
super(mapmods(decl), decl.docs);
|
||||
this._owner = owner;
|
||||
this._decl = decl;
|
||||
this._type = new ResolvableType(decl);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._decl.name;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceMethod extends Method {
|
||||
/**
|
||||
* @param {SourceType} owner
|
||||
* @param {MethodBlock} decl
|
||||
*/
|
||||
constructor(owner, decl) {
|
||||
super(mapmods(decl), decl.docs);
|
||||
this._owner = owner;
|
||||
this._decl = decl;
|
||||
this._parameters = decl.parameters.map((p,i) => new SourceParameter(p));
|
||||
this._returnType = new ResolvableType(decl);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._decl.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {SourceParameter[]}
|
||||
*/
|
||||
get parameters() {
|
||||
return this._parameters;
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return this._returnType.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class SourceParameter extends Parameter {
|
||||
/**
|
||||
* @param {ParameterBlock} decl
|
||||
* @param {ResolvableType} [type]
|
||||
*/
|
||||
constructor(decl, type = new ResolvableType(decl)) {
|
||||
super(decl.name, type, decl.isVarArgs);
|
||||
this._decl = decl;
|
||||
this._paramType = type;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._paramType.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
class ResolvableType extends UnresolvedType {
|
||||
/**
|
||||
*
|
||||
* @param {{type:string, typeTokens:TextBlock[]}} decl
|
||||
*/
|
||||
constructor(decl) {
|
||||
super(decl.type);
|
||||
this._decl = decl;
|
||||
/** @type {import('../java/parsetypes/resolved-type')} */
|
||||
this._resolved = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {JavaType}
|
||||
*/
|
||||
get resolved() {
|
||||
if (!this._resolved) return this;
|
||||
if (!this._resolved.mtis.length) return this;
|
||||
return this._resolved.mtis[0];
|
||||
}
|
||||
|
||||
get typeTokens() {
|
||||
return this._decl.typeTokens;
|
||||
}
|
||||
}
|
||||
|
||||
exports.SourceType = SourceType;
|
||||
Reference in New Issue
Block a user