mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 09:59:25 +00:00
remove Value class, add NewExpression and separate out Any classes
This commit is contained in:
57
langserver/java/anys.js
Normal file
57
langserver/java/anys.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const { JavaType, Method } = require('java-mti');
|
||||
const { Expression } = require('./expressiontypes/Expression');
|
||||
|
||||
/**
|
||||
* AnyType is a special type that's used to fill in types that are missing.
|
||||
* To prevent cascading errors, AnyType should be fully assign/cast/type-compatible
|
||||
* with any other type
|
||||
*/
|
||||
class AnyType extends JavaType {
|
||||
/**
|
||||
*
|
||||
* @param {String} label
|
||||
*/
|
||||
constructor(label) {
|
||||
super("class", [], '');
|
||||
super.simpleTypeName = label || '<unknown type>';
|
||||
}
|
||||
|
||||
static Instance = new AnyType('');
|
||||
|
||||
get rawTypeSignature() {
|
||||
return 'U';
|
||||
}
|
||||
|
||||
get typeSignature() {
|
||||
return 'U';
|
||||
}
|
||||
}
|
||||
|
||||
class AnyMethod extends Method {
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
constructor(name) {
|
||||
super(null, name, [], '');
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return AnyType.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
class AnyValue extends Expression {
|
||||
/**
|
||||
*
|
||||
* @param {String} label
|
||||
*/
|
||||
constructor(label) {
|
||||
super();
|
||||
this.label = label;
|
||||
this.type = AnyType.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
exports.AnyMethod = AnyMethod;
|
||||
exports.AnyType = AnyType;
|
||||
exports.AnyValue = AnyValue;
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Each token also contains detailed state information used for completion suggestions.
|
||||
*/
|
||||
const { JavaType, CEIType, PrimitiveType, ArrayType, UnresolvedType, NullType, TypeVariable, Field, Method } = require('java-mti');
|
||||
const { JavaType, CEIType, PrimitiveType, ArrayType, UnresolvedType, TypeVariable, Field, Method } = require('java-mti');
|
||||
const { SourceType, SourceTypeIdent, SourceField, SourceMethod, SourceConstructor, SourceInitialiser, SourceParameter, SourceAnnotation,
|
||||
SourceUnit, SourcePackage, SourceImport } = require('./source-types2');
|
||||
const ResolvedImport = require('./parsetypes/resolved-import');
|
||||
@@ -13,7 +13,8 @@ const { tokenize, Token } = require('./tokenizer');
|
||||
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
||||
const { genericTypeArgs, typeIdent, typeIdentList } = require('./typeident');
|
||||
const { TokenList } = require("./TokenList");
|
||||
const { AnyMethod, AnyType, AnyValue, Label, Local, MethodDeclarations, ResolvedIdent, Value, } = require("./body-types");
|
||||
const { AnyMethod, AnyType, AnyValue } = require("./anys");
|
||||
const { Label, Local, MethodDeclarations, ResolvedIdent } = require("./body-types");
|
||||
const { resolveImports, resolveSingleImport } = require('../java/import-resolver');
|
||||
|
||||
const { ArrayIndexExpression } = require("./expressiontypes/ArrayIndexExpression");
|
||||
@@ -26,11 +27,13 @@ const { IncDecExpression } = require("./expressiontypes/IncDecExpression");
|
||||
const { LambdaExpression } = require("./expressiontypes/LambdaExpression");
|
||||
const { MemberExpression } = require("./expressiontypes/MemberExpression");
|
||||
const { MethodCallExpression } = require("./expressiontypes/MethodCallExpression");
|
||||
const { NewArray, NewObject } = require("./expressiontypes/NewExpression");
|
||||
const { TernaryOpExpression } = require("./expressiontypes/TernaryOpExpression");
|
||||
const { ThisMemberExpression } = require("./expressiontypes/ThisMemberExpression");
|
||||
|
||||
const { BooleanLiteral } = require('./expressiontypes/literals/Boolean');
|
||||
const { CharacterLiteral } = require('./expressiontypes/literals/Character');
|
||||
const { InstanceLiteral } = require('./expressiontypes/literals/Instance');
|
||||
const { NumberLiteral } = require('./expressiontypes/literals/Number');
|
||||
const { NullLiteral } = require('./expressiontypes/literals/Null');
|
||||
const { StringLiteral } = require('./expressiontypes/literals/String');
|
||||
@@ -1533,11 +1536,8 @@ function rootTerm(tokens, mdecls, scope, imports, typemap) {
|
||||
case 'object-literal':
|
||||
// this, super or null
|
||||
const scoped_type = scope instanceof SourceType ? scope : scope.owner;
|
||||
if (tokens.current.value === 'this') {
|
||||
matches = new ResolvedIdent(tokens.current.value, [new Value(tokens.current.value, scoped_type)]);
|
||||
} else if (tokens.current.value === 'super') {
|
||||
const supertype = scoped_type.supers.find(s => s.typeKind === 'class') || typemap.get('java/lang/Object');
|
||||
matches = new ResolvedIdent(tokens.current.value, [new Value(tokens.current.value, supertype)]);
|
||||
if (tokens.current.value === 'this' || tokens.current.value === 'super') {
|
||||
matches = new ResolvedIdent(tokens.current.value, [new InstanceLiteral(tokens.current, scoped_type)]);
|
||||
} else {
|
||||
matches = new ResolvedIdent(tokens.current.value, [new NullLiteral(tokens.current)]);
|
||||
}
|
||||
@@ -1606,13 +1606,9 @@ function rootTerm(tokens, mdecls, scope, imports, typemap) {
|
||||
*/
|
||||
function newTerm(tokens, mdecls, scope, imports, typemap) {
|
||||
tokens.expectValue('new');
|
||||
const type_start_token = tokens.idx;
|
||||
const { resolved: ctr_type } = typeIdent(tokens, scope, imports, typemap, {no_array_qualifiers:true, type_vars:[]});
|
||||
if (ctr_type instanceof AnyType) {
|
||||
const toks = tokens.tokens.slice(type_start_token, tokens.idx);
|
||||
addproblem(tokens, ParseProblem.Error(toks, `Unresolved type: '${toks.map(t => t.source).join('')}'`));
|
||||
}
|
||||
let match = new ResolvedIdent(`new ${ctr_type.simpleTypeName}`, [], [], [ctr_type]);
|
||||
let ctr_args = [], type_body = null;
|
||||
switch(tokens.current.value) {
|
||||
case '[':
|
||||
match = arrayQualifiers(match, tokens, mdecls, scope, imports, typemap);
|
||||
@@ -1621,36 +1617,24 @@ function newTerm(tokens, mdecls, scope, imports, typemap) {
|
||||
// array init
|
||||
rootTerm(tokens, mdecls, scope, imports, typemap);
|
||||
}
|
||||
return new ResolvedIdent(match.source, [new Value(match.source, match.types[0])]);
|
||||
return new ResolvedIdent(match.source, [new NewArray(ctr_type, match)]);
|
||||
case '(':
|
||||
match = methodCallQualifier(match, tokens, mdecls, scope, imports, typemap);
|
||||
tokens.inc();
|
||||
if (!tokens.isValue(')')) {
|
||||
ctr_args = expressionList(tokens, mdecls, scope, imports, typemap);
|
||||
tokens.expectValue(')');
|
||||
}
|
||||
// @ts-ignore
|
||||
if (tokens.current.value === '{') {
|
||||
// final types cannot be inherited
|
||||
if (ctr_type.modifiers.includes('final') ) {
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, `Type '${ctr_type.fullyDottedTypeName}' is declared final and cannot be inherited from.`));
|
||||
}
|
||||
// anonymous type - just skip for now
|
||||
for (let balance = 0;;) {
|
||||
if (tokens.isValue('{')) {
|
||||
balance++;
|
||||
} else if (tokens.isValue('}')) {
|
||||
if (--balance === 0) {
|
||||
type_body = skipBody(tokens);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, 'Constructor expression expected'));
|
||||
break;
|
||||
}
|
||||
} else tokens.inc();
|
||||
}
|
||||
} else {
|
||||
// abstract and interface types must have a type body
|
||||
if (ctr_type.typeKind === 'interface' || ctr_type.modifiers.includes('abstract') ) {
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, `Type '${ctr_type.fullyDottedTypeName}' is abstract and cannot be instantiated without a body`));
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
addproblem(tokens, ParseProblem.Error(tokens.current, 'Constructor expression expected'));
|
||||
return new ResolvedIdent(match.source, [new Value(match.source, ctr_type)]);
|
||||
return new ResolvedIdent(match.source, [new NewObject(ctr_type, ctr_args, type_body)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/**
|
||||
* @typedef {import('./expressiontypes/Expression').Expression} Expression
|
||||
*/
|
||||
const { JavaType, ArrayType, Method, Parameter, Field } = require('java-mti');
|
||||
const { Token } = require('./tokenizer');
|
||||
|
||||
class ResolvedIdent {
|
||||
/**
|
||||
* @param {string} ident
|
||||
* @param {(Local|Parameter|Field|ArrayElement|ValueBase)[]} variables
|
||||
* @param {(Local|Parameter|Field|Expression)[]} variables
|
||||
* @param {Method[]} methods
|
||||
* @param {JavaType[]} types
|
||||
* @param {string} package_name
|
||||
@@ -20,45 +23,6 @@ class ResolvedIdent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AnyType is a special type that's used to fill in types that are missing.
|
||||
* To prevent cascading errors, AnyType should be fully assign/cast/type-compatible
|
||||
* with any other type
|
||||
*/
|
||||
class AnyType extends JavaType {
|
||||
/**
|
||||
*
|
||||
* @param {String} label
|
||||
*/
|
||||
constructor(label) {
|
||||
super("class", [], '');
|
||||
super.simpleTypeName = label || '<unknown type>';
|
||||
}
|
||||
|
||||
static Instance = new AnyType('');
|
||||
|
||||
get rawTypeSignature() {
|
||||
return 'U';
|
||||
}
|
||||
|
||||
get typeSignature() {
|
||||
return 'U';
|
||||
}
|
||||
}
|
||||
|
||||
class AnyMethod extends Method {
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
constructor(name) {
|
||||
super(null, name, [], '');
|
||||
}
|
||||
|
||||
get returnType() {
|
||||
return AnyType.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
class Local {
|
||||
/**
|
||||
* @param {Token[]} modifiers
|
||||
@@ -115,91 +79,7 @@ class MethodDeclarations {
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayElement {
|
||||
/**
|
||||
*
|
||||
* @param {Local|Parameter|Field|ArrayElement|Value} array_variable
|
||||
* @param {ResolvedIdent} index
|
||||
*/
|
||||
constructor(array_variable, index) {
|
||||
this.array_variable = array_variable;
|
||||
this.index = index;
|
||||
if (!(this.array_variable.type instanceof ArrayType)) {
|
||||
throw new Error('Array element cannot be created from non-array type');
|
||||
}
|
||||
this.name = `${array_variable.name}[${index.source}]`;
|
||||
/** @type {JavaType} */
|
||||
this.type = this.array_variable.type.elementType;
|
||||
}
|
||||
}
|
||||
|
||||
class ValueBase {}
|
||||
|
||||
class Value extends ValueBase {
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {JavaType} type
|
||||
*/
|
||||
constructor(name, type) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
class AnyValue extends Value {
|
||||
constructor(name) {
|
||||
super(name, AnyType.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
class MethodCall extends Value {
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {ResolvedIdent} instance
|
||||
* @param {Method} method
|
||||
*/
|
||||
constructor(name, instance, method) {
|
||||
super(name, method.returnType);
|
||||
this.instance = instance;
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructorCall extends Value {
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {JavaType} type
|
||||
*/
|
||||
constructor(name, type) {
|
||||
super(name, type);
|
||||
}
|
||||
}
|
||||
|
||||
class TernaryValue extends Value {
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {JavaType} true_type
|
||||
* @param {Token} colon
|
||||
* @param {Value} false_value
|
||||
*/
|
||||
constructor(name, true_type, colon, false_value) {
|
||||
super(name, true_type);
|
||||
this.colon = colon;
|
||||
this.falseValue = false_value;
|
||||
}
|
||||
}
|
||||
|
||||
exports.AnyMethod = AnyMethod;
|
||||
exports.AnyType = AnyType;
|
||||
exports.AnyValue = AnyValue;
|
||||
exports.ArrayElement = ArrayElement;
|
||||
exports.ConstructorCall = ConstructorCall;
|
||||
exports.Label = Label;
|
||||
exports.Local = Local;
|
||||
exports.MethodCall = MethodCall;
|
||||
exports.MethodDeclarations = MethodDeclarations;
|
||||
exports.ResolvedIdent = ResolvedIdent;
|
||||
exports.TernaryValue = TernaryValue;
|
||||
exports.Value = Value;
|
||||
exports.ValueBase = ValueBase;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { ValueBase } = require("../body-types");
|
||||
|
||||
class Expression extends ValueBase {
|
||||
class Expression {
|
||||
}
|
||||
|
||||
exports.Expression = Expression;
|
||||
|
||||
35
langserver/java/expressiontypes/NewExpression.js
Normal file
35
langserver/java/expressiontypes/NewExpression.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('java-mti').JavaType} JavaType
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
|
||||
class NewArray extends Expression {
|
||||
/**
|
||||
* @param {JavaType} element_type
|
||||
* @param {ResolvedIdent} dimensions
|
||||
*/
|
||||
constructor(element_type, dimensions) {
|
||||
super();
|
||||
this.element_type = element_type;
|
||||
this.dimensions = dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
class NewObject extends Expression {
|
||||
/**
|
||||
* @param {JavaType} object_type
|
||||
* @param {ResolvedIdent[]} ctr_args
|
||||
* @param {Token[]} type_body
|
||||
*/
|
||||
constructor(object_type, ctr_args, type_body) {
|
||||
super();
|
||||
this.element_type = object_type;
|
||||
this.ctr_args = ctr_args;
|
||||
this.type_body = type_body;
|
||||
}
|
||||
}
|
||||
|
||||
exports.NewArray = NewArray;
|
||||
exports.NewObject = NewObject;
|
||||
19
langserver/java/expressiontypes/literals/Instance.js
Normal file
19
langserver/java/expressiontypes/literals/Instance.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @typedef {import('../../tokenizer').Token} Token
|
||||
* @typedef {import('java-mti').CEIType} CEIType
|
||||
*/
|
||||
const { LiteralValue } = require('./LiteralValue');
|
||||
|
||||
class InstanceLiteral extends LiteralValue {
|
||||
/**
|
||||
*
|
||||
* @param {Token} token 'this' or 'super' token
|
||||
* @param {CEIType} scoped_type
|
||||
*/
|
||||
constructor(token, scoped_type) {
|
||||
super(token);
|
||||
this.scoped_type = scoped_type;
|
||||
}
|
||||
}
|
||||
|
||||
exports.InstanceLiteral = InstanceLiteral;
|
||||
@@ -3,7 +3,7 @@ const { SourceTypeIdent, SourceMethod, SourceConstructor, SourceInitialiser } =
|
||||
const ResolvedImport = require('./parsetypes/resolved-import');
|
||||
const { resolveTypeOrPackage, resolveNextTypeOrPackage } = require('./type-resolver');
|
||||
const { Token } = require('./tokenizer');
|
||||
const { AnyType } = require("./body-types");
|
||||
const { AnyType } = require("./anys");
|
||||
|
||||
/**
|
||||
* @typedef {SourceMethod|SourceConstructor|SourceInitialiser} SourceMC
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { SourceType } = require('../source-type');
|
||||
const ParseProblem = require('../parsetypes/parse-problem');
|
||||
const { AnyType } = require('../body-types');
|
||||
const { AnyType } = require('../anys');
|
||||
|
||||
/**
|
||||
* @param {SourceType} source_type
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const ParseProblem = require('../parsetypes/parse-problem');
|
||||
const {SourceType} = require('../source-type');
|
||||
const { AnyType } = require('../body-types');
|
||||
const { AnyType } = require('../anys');
|
||||
const { UnresolvedType } = require('java-mti');
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user