diff --git a/langserver/java/body-parser3.js b/langserver/java/body-parser3.js index bf2687d..299e894 100644 --- a/langserver/java/body-parser3.js +++ b/langserver/java/body-parser3.js @@ -25,14 +25,12 @@ const { ArrayValueExpression } = require("./expressiontypes/ArrayValueExpression const { BinaryOpExpression } = require("./expressiontypes/BinaryOpExpression"); const { BracketedExpression } = require("./expressiontypes/BracketedExpression"); const { CastExpression } = require("./expressiontypes/CastExpression"); -const { ClassMemberExpression } = require("./expressiontypes/ClassMemberExpression"); 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 { UnaryOpExpression } = require("./expressiontypes/UnaryOpExpression"); const { Variable } = require("./expressiontypes/Variable"); @@ -1718,11 +1716,8 @@ function memberQualifier(matches, tokens, mdecls, scope, imports, typemap) { let types = [], package_name = ''; switch (tokens.current.value) { case 'class': - expr = new ClassMemberExpression(matches, tokens.consume()); - break; case 'this': - case 'super': - expr = new ThisMemberExpression(matches, tokens.consume()); + expr = new MemberExpression(matches, dot, tokens.consume()); break; default: let member = tokens.getIfKind('ident'); diff --git a/langserver/java/expressiontypes/ClassMemberExpression.js b/langserver/java/expressiontypes/ClassMemberExpression.js deleted file mode 100644 index 725dd5a..0000000 --- a/langserver/java/expressiontypes/ClassMemberExpression.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent - * @typedef {import('../tokenizer').Token} Token - * @typedef {import('../body-types').ResolveInfo} ResolveInfo - */ -const { Expression } = require("./Expression"); -const { AnyType } = require('../anys'); -const ParseProblem = require('../parsetypes/parse-problem'); - -class ClassMemberExpression extends Expression { - /** - * @param {ResolvedIdent} instance - * @param {Token} class_token - */ - constructor(instance, class_token) { - super(); - this.instance = instance; - this.classToken = class_token; - } - - /** - * @param {ResolveInfo} ri - */ - resolveExpression(ri) { - const classType = ri.typemap.get('java/lang/Class'); - const type = this.instance.types[0]; - if (!type) { - ri.problems.push(ParseProblem.Error(this.instance.tokens, `Type expected`)); - } - return classType.specialise([type || AnyType.Instance]); - } - - tokens() { - return this.classToken; - } -} -exports.ClassMemberExpression = ClassMemberExpression; diff --git a/langserver/java/expressiontypes/MemberExpression.js b/langserver/java/expressiontypes/MemberExpression.js index 9f6a87c..04e990b 100644 --- a/langserver/java/expressiontypes/MemberExpression.js +++ b/langserver/java/expressiontypes/MemberExpression.js @@ -4,7 +4,7 @@ * @typedef {import('../tokenizer').Token} Token */ const { Expression } = require("./Expression"); -const { JavaType, CEIType } = require('java-mti'); +const { JavaType, CEIType, PrimitiveType } = require('java-mti'); const { AnyType, MethodType, PackageNameType, TypeIdentType } = require('../anys'); const { getTypeInheritanceList } = require('../expression-resolver'); const { resolveNextPackage } = require('../type-resolver'); @@ -68,6 +68,32 @@ class MemberExpression extends Expression { this.member.loc = this.dot.loc; const ident = this.member.value; + + if (ident === 'this') { + // if this has a type qualifier (Type.this), return the type, otherwise it's + // and error and return AnyType + return ((loc_key === 'fqs') && (instance instanceof CEIType)) ? instance : AnyType.Instance; + } + + if (ident === 'class') { + // if this has a type qualifier (Type.class), return the Class instance, otherwise it's + // and error and return AnyType + if (loc_key !== 'fqs') { + return AnyType.Instance; + } + let class_type = instance; + if (instance instanceof PrimitiveType) { + class_type = ri.typemap.get(`java/lang/${{ + B:'Byte',S:'Short',I:'Integer',J:'Long',F:'Float',D:'Double',C:'Character',Z:'Boolean',V:'Void' + }[instance.typeSignature]}`) + } + const clz = ri.typemap.get('java/lang/Class').specialise([class_type]); + if (!ri.typemap.has(clz.shortSignature)) { + ri.typemap.set(clz.shortSignature, clz); + } + return clz; + } + const field = instance.fields.find(f => f.name === ident); if (field) { return field.type; diff --git a/langserver/java/expressiontypes/ThisMemberExpression.js b/langserver/java/expressiontypes/ThisMemberExpression.js deleted file mode 100644 index d2e09be..0000000 --- a/langserver/java/expressiontypes/ThisMemberExpression.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent - * @typedef {import('../body-types').ResolveInfo} ResolveInfo - * @typedef {import('../tokenizer').Token} Token - */ -const { Expression } = require("./Expression"); -const { AnyType, TypeIdentType } = require('../anys'); - -class ThisMemberExpression extends Expression { - /** - * @param {ResolvedIdent} instance - * @param {Token} this_token - */ - constructor(instance, this_token) { - super(); - this.instance = instance; - this.thisToken = this_token; - } - - /** - * @param {ResolveInfo} ri - */ - resolveExpression(ri) { - // instance should be a type identifier - const typeident = this.instance.resolveExpression(ri); - if (typeident instanceof TypeIdentType) { - return typeident.type; - } - return AnyType.Instance; - } - - tokens() { - return this.thisToken; - } -} - -exports.ThisMemberExpression = ThisMemberExpression;