Files
GGD/node_modules/java-parser/src/productions/packages-and-modules.js

274 lines
8.3 KiB
JavaScript

"use strict";
const { isRecognitionException, tokenMatcher, EOF } = require("chevrotain");
function defineRules($, t) {
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#CompilationUnit
$.RULE("compilationUnit", () => {
// custom optimized backtracking lookahead logic
const isModule = $.BACKTRACK_LOOKAHEAD($.isModuleCompilationUnit);
$.OR([
{
GATE: () => isModule === false,
ALT: () => $.SUBRULE($.ordinaryCompilationUnit)
},
{
ALT: () => $.SUBRULE($.modularCompilationUnit)
}
]);
// https://github.com/jhipster/prettier-java/pull/217
$.CONSUME(EOF);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-OrdinaryCompilationUnit
$.RULE("ordinaryCompilationUnit", () => {
$.OPTION({
GATE: $.BACKTRACK($.packageDeclaration),
DEF: () => {
$.SUBRULE($.packageDeclaration);
}
});
$.MANY(() => {
$.SUBRULE3($.importDeclaration);
});
$.MANY2(() => {
$.SUBRULE($.typeDeclaration);
});
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-ModularCompilationUnit
$.RULE("modularCompilationUnit", () => {
$.MANY(() => {
$.SUBRULE($.importDeclaration);
});
$.SUBRULE($.moduleDeclaration);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-PackageDeclaration
$.RULE("packageDeclaration", () => {
$.MANY(() => {
$.SUBRULE($.packageModifier);
});
$.CONSUME(t.Package);
$.CONSUME(t.Identifier);
$.MANY2(() => {
$.CONSUME(t.Dot);
$.CONSUME2(t.Identifier);
});
$.CONSUME2(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-PackageModifier
$.RULE("packageModifier", () => {
$.SUBRULE($.annotation);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-ImportDeclaration
$.RULE("importDeclaration", () => {
// Spec Deviation: The spec defines four different kinds of import declarations.
// Our grammar however combines those into a single rule due to difficulties
// distinguishing between the alternatives due to unbound common prefix.
// TODO: A post parsing step is required to align with the official specs.
// The Identifier "var" is not allowed in all positions and variations of the importDeclaration
$.OR([
{
ALT: () => {
$.CONSUME(t.Import);
$.OPTION(() => {
$.CONSUME(t.Static);
});
$.SUBRULE($.packageOrTypeName);
$.OPTION2(() => {
$.CONSUME(t.Dot);
$.CONSUME(t.Star);
});
$.CONSUME(t.Semicolon);
}
},
// Spec Deviation: The spec do not allow empty statement in between imports.
// However Java compiler consider empty statements valid, we chose
// to support that case, thus deviate from the spec.
// See here: https://github.com/jhipster/prettier-java/pull/158
{
ALT: () => $.SUBRULE($.emptyStatement)
}
]);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-TypeDeclaration
$.RULE("typeDeclaration", () => {
// TODO: consider extracting the prefix modifiers here to avoid backtracking
const isClassDeclaration = this.BACKTRACK_LOOKAHEAD($.isClassDeclaration);
$.OR([
{
GATE: () => isClassDeclaration,
ALT: () => $.SUBRULE($.classDeclaration)
},
{ ALT: () => $.SUBRULE($.interfaceDeclaration) },
{ ALT: () => $.CONSUME(t.Semicolon) }
]);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-ModuleDeclaration
$.RULE("moduleDeclaration", () => {
$.MANY(() => {
$.SUBRULE($.annotation);
});
$.OPTION(() => {
$.CONSUME(t.Open);
});
$.CONSUME(t.Module);
$.CONSUME(t.Identifier);
$.MANY2(() => {
$.CONSUME(t.Dot);
$.CONSUME2(t.Identifier);
});
$.CONSUME(t.LCurly);
$.MANY3(() => {
$.SUBRULE($.moduleDirective);
});
$.CONSUME(t.RCurly);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-ModuleDirective
$.RULE("moduleDirective", () => {
// Spec Deviation: Each of the alternatives of "moduleDirective" was extracted
// to its own nonTerminal, to reduce verbosity.
$.OR([
{ ALT: () => $.SUBRULE($.requiresModuleDirective) },
{ ALT: () => $.SUBRULE($.exportsModuleDirective) },
{ ALT: () => $.SUBRULE($.opensModuleDirective) },
{ ALT: () => $.SUBRULE($.usesModuleDirective) },
{ ALT: () => $.SUBRULE($.providesModuleDirective) }
]);
});
$.RULE("requiresModuleDirective", () => {
// Spec Deviation: extracted from "moduleDirective"
$.CONSUME(t.Requires);
$.MANY({
GATE: () => {
/**
* https://docs.oracle.com/javase/specs/jls/se16/html/jls-3.html#jls-3.9 -
* There is one exception: immediately to the right of the character sequence `requires` in the ModuleDirective production,
* the character sequence `transitive` is tokenized as a keyword unless it is followed by a separator,
* in which case it is tokenized as an identifier.
*/
return (
(tokenMatcher($.LA(1).tokenType, t.Transitive) &&
tokenMatcher($.LA(2).tokenType, t.Separators)) === false
);
},
DEF: () => {
$.SUBRULE($.requiresModifier);
}
});
$.SUBRULE($.moduleName);
$.CONSUME(t.Semicolon);
});
$.RULE("exportsModuleDirective", () => {
// Spec Deviation: extracted from "moduleDirective"
$.CONSUME(t.Exports);
$.SUBRULE($.packageName);
$.OPTION(() => {
$.CONSUME(t.To);
$.SUBRULE($.moduleName);
$.MANY(() => {
$.CONSUME(t.Comma);
$.SUBRULE2($.moduleName);
});
});
$.CONSUME(t.Semicolon);
});
$.RULE("opensModuleDirective", () => {
// Spec Deviation: extracted from "moduleDirective"
$.CONSUME(t.Opens);
$.SUBRULE($.packageName);
$.OPTION(() => {
$.CONSUME(t.To);
$.SUBRULE($.moduleName);
$.MANY(() => {
$.CONSUME(t.Comma);
$.SUBRULE2($.moduleName);
});
});
$.CONSUME(t.Semicolon);
});
$.RULE("usesModuleDirective", () => {
// Spec Deviation: extracted from "moduleDirective"
$.CONSUME(t.Uses);
$.SUBRULE($.typeName);
$.CONSUME(t.Semicolon);
});
$.RULE("providesModuleDirective", () => {
// Spec Deviation: extracted from "moduleDirective"
$.CONSUME(t.Provides);
$.SUBRULE($.typeName);
$.CONSUME(t.With);
$.SUBRULE2($.typeName);
$.MANY(() => {
$.CONSUME(t.Comma);
$.SUBRULE3($.typeName);
});
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-RequiresModifier
$.RULE("requiresModifier", () => {
$.OR([
{ ALT: () => $.CONSUME(t.Transitive) },
{ ALT: () => $.CONSUME(t.Static) }
]);
});
$.RULE("isModuleCompilationUnit", () => {
$.OPTION(() => {
$.SUBRULE($.packageDeclaration);
// TODO: this return must be outside the OPTION at the top level rule
// a Java Module source code may not contain a package declaration.
return false;
});
try {
// the "{importDeclaration}" is a common prefix
$.MANY(() => {
$.SUBRULE2($.importDeclaration);
});
$.MANY2({
// To avoid ambiguity with @interface ("AnnotationTypeDeclaration" vs "Annotaion")
GATE: () =>
(tokenMatcher($.LA(1).tokenType, t.At) &&
tokenMatcher($.LA(2).tokenType, t.Interface)) === false,
DEF: () => {
$.SUBRULE($.annotation);
}
});
} catch (e) {
// This means we had a syntax error in the imports or annotations
// So we can't keep parsing deep enough to make the decision
if (isRecognitionException(e)) {
// TODO: add original syntax error?
throw "Cannot Identify if the source code is an OrdinaryCompilationUnit or ModularCompilationUnit";
} else {
throw e;
}
}
const nextTokenType = this.LA(1).tokenType;
return (
tokenMatcher(nextTokenType, t.Open) ||
tokenMatcher(nextTokenType, t.Module)
);
});
}
module.exports = {
defineRules
};