remove local modifier validation during parse

add parameter modifier checking to validation
This commit is contained in:
Dave Holoway
2020-06-15 17:16:39 +01:00
parent 4af183e4e1
commit 14582503da
2 changed files with 24 additions and 32 deletions

View File

@@ -352,7 +352,8 @@ function statement(tokens, mdecls, method, imports, typemap) {
} }
// modifiers are only allowed on local variable decls // modifiers are only allowed on local variable decls
if (modifiers.length) { if (modifiers.length) {
s = var_decl(modifiers, tokens, mdecls, method, imports, typemap); const type = typeIdent(tokens, method, imports, typemap);
s = var_ident_list(modifiers, type, null, tokens, mdecls, method, imports, typemap)
addLocals(tokens, mdecls, s); addLocals(tokens, mdecls, s);
semicolon(tokens); semicolon(tokens);
return s; return s;
@@ -789,7 +790,6 @@ function parameterDeclaration(type_vars, owner, tokens, imports, typemap) {
modifiers.push(tokens.current); modifiers.push(tokens.current);
tokens.inc(); tokens.inc();
} }
checkLocalModifiers(tokens, modifiers);
let type_ident = typeIdent(tokens, owner, imports, typemap, { no_array_qualifiers: false, type_vars }); let type_ident = typeIdent(tokens, owner, imports, typemap, { no_array_qualifiers: false, type_vars });
const varargs = tokens.isValue('...'); const varargs = tokens.isValue('...');
let name_token = tokens.current; let name_token = tokens.current;
@@ -1148,7 +1148,6 @@ function catchFinallyBlocks(s, tokens, mdecls, method, imports, typemap) {
mdecls.pushScope(); mdecls.pushScope();
let exceptionVar; let exceptionVar;
if (catchinfo.types[0] && catchinfo.name) { if (catchinfo.types[0] && catchinfo.name) {
checkLocalModifiers(tokens, mods);
exceptionVar = new Local(mods, catchinfo.name.value, catchinfo.name, catchinfo.types[0], 0); exceptionVar = new Local(mods, catchinfo.name.value, catchinfo.name, catchinfo.types[0], 0);
mdecls.locals.push(exceptionVar); mdecls.locals.push(exceptionVar);
} }
@@ -1360,19 +1359,6 @@ function checkThrowExpression(tokens, throw_expression, typemap) {
} }
} }
/**
* @param {TokenList} tokens
* @param {MethodDeclarations} mdecls
* @param {Scope} scope
* @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap
* @returns {Local[]}
*/
function var_decl(mods, tokens, mdecls, scope, imports, typemap) {
const type = typeIdent(tokens, scope, imports, typemap);
return var_ident_list(mods, type, null, tokens, mdecls, scope, imports, typemap)
}
/** /**
* *
* @param {Token[]} mods * @param {Token[]} mods
@@ -1385,7 +1371,6 @@ function var_decl(mods, tokens, mdecls, scope, imports, typemap) {
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
*/ */
function var_ident_list(mods, type, first_ident, tokens, mdecls, scope, imports, typemap) { function var_ident_list(mods, type, first_ident, tokens, mdecls, scope, imports, typemap) {
checkLocalModifiers(tokens, mods);
const new_locals = []; const new_locals = [];
for (;;) { for (;;) {
let name; let name;
@@ -1467,20 +1452,6 @@ function expression_list_or_var_decl(tokens, mdecls, scope, imports, typemap) {
return expressions; return expressions;
} }
/**
* @param {Token[]} mods
*/
function checkLocalModifiers(tokens, mods) {
for (let i=0; i < mods.length; i++) {
if (mods[i].value !== 'final') {
addproblem(tokens, ParseProblem.Error(mods[i], `Modifier '${mods[i].source}' cannot be applied to local variable declarations.`));
} else if (mods.findIndex(m => m.source === 'final') < i) {
addproblem(tokens, ParseProblem.Error(mods[i], `Repeated 'final' modifier.`));
}
}
}
/** /**
* Operator precedence levels. * Operator precedence levels.
* Lower number = higher precedence. * Lower number = higher precedence.

View File

@@ -1,4 +1,4 @@
const { SourceType, SourceMethod, SourceField, SourceConstructor, SourceInitialiser } = require('../source-type'); const { SourceType, SourceMethod, SourceParameter, SourceField, SourceConstructor, SourceInitialiser } = require('../source-type');
const { Token } = require('../tokenizer'); const { Token } = require('../tokenizer');
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
@@ -68,6 +68,25 @@ function checkFieldModifiers(field, probs) {
} }
} }
/**
* @param {SourceParameter} param
* @param {ParseProblem[]} probs
*/
function checkParameterModifiers(param, probs) {
// the only permitted modifier is final
let has_final = false;
param.modifierTokens.forEach(mod => {
if (mod.value === 'final') {
if (has_final) {
probs.push(ParseProblem.Error(mod, `Repeated modifier: final`));
}
has_final = true;
return;
}
probs.push(ParseProblem.Error(mod, `Parameter declarations cannot be ${mod.value}`));
});
}
/** /**
* @param {SourceType} type * @param {SourceType} type
* @param {Map<string,*>} ownertypemods * @param {Map<string,*>} ownertypemods
@@ -78,6 +97,8 @@ function checkMethodModifiers(type, ownertypemods, method, probs) {
checkDuplicate(method.modifierTokens, probs); checkDuplicate(method.modifierTokens, probs);
checkConflictingAccess(method.modifierTokens, probs); checkConflictingAccess(method.modifierTokens, probs);
method.parameters.forEach(p => checkParameterModifiers(p, probs));
const allmods = new Map(method.modifierTokens.map(m => [m.source, m])); const allmods = new Map(method.modifierTokens.map(m => [m.source, m]));
const is_interface_kind = /@?interface/.test(type.typeKind); const is_interface_kind = /@?interface/.test(type.typeKind);
const has_body = method.hasImplementation; const has_body = method.hasImplementation;