mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Show linter results after validation
This commit is contained in:
parent
2578f0a6b4
commit
ce14581bf4
@ -4,6 +4,7 @@ import com.annimon.ownlang.exceptions.OwnLangParserException;
|
||||
import com.annimon.ownlang.exceptions.StoppedException;
|
||||
import com.annimon.ownlang.parser.*;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.linters.LinterStage;
|
||||
import com.annimon.ownlang.stages.*;
|
||||
import com.annimon.ownlang.utils.Repl;
|
||||
import com.annimon.ownlang.utils.Sandbox;
|
||||
|
@ -1,38 +0,0 @@
|
||||
package com.annimon.ownlang.parser;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.Visitor;
|
||||
import com.annimon.ownlang.parser.linters.AssignValidator;
|
||||
import com.annimon.ownlang.parser.linters.DefaultFunctionsOverrideValidator;
|
||||
|
||||
public final class Linter {
|
||||
|
||||
public static void lint(Statement program) {
|
||||
new Linter(program).execute();
|
||||
}
|
||||
|
||||
private final Statement program;
|
||||
|
||||
private Linter(Statement program) {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
final Visitor[] validators = new Visitor[] {
|
||||
new AssignValidator(),
|
||||
new DefaultFunctionsOverrideValidator()
|
||||
};
|
||||
resetState();
|
||||
for (Visitor validator : validators) {
|
||||
program.accept(validator);
|
||||
resetState();
|
||||
}
|
||||
Console.println("Lint validation complete!");
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
ScopeHandler.resetScope();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Function;
|
||||
import com.annimon.ownlang.lib.ModuleLoader;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.modules.Module;
|
||||
@ -34,6 +35,15 @@ public final class UseStatement extends InterruptableNode implements Statement {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, Function> loadFunctions() {
|
||||
final var result = new LinkedHashMap<String, Function>();
|
||||
for (String moduleName : modules) {
|
||||
final Module module = ModuleLoader.load(moduleName);
|
||||
result.putAll(module.functions());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor visitor) {
|
||||
|
@ -1,23 +1,31 @@
|
||||
package com.annimon.ownlang.parser.linters;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
import com.annimon.ownlang.parser.ast.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class AssignValidator extends LintVisitor {
|
||||
final class AssignValidator extends LintVisitor {
|
||||
|
||||
private final Set<String> moduleConstants = new HashSet<>();
|
||||
|
||||
AssignValidator(Collection<LinterResult> results) {
|
||||
super(results);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignmentExpression s) {
|
||||
super.visit(s);
|
||||
if (s.target instanceof VariableExpression varExpr) {
|
||||
final String variable = varExpr.name;
|
||||
if (ScopeHandler.isConstantExists(variable)) {
|
||||
Console.error(String.format(
|
||||
"Warning: variable \"%s\" overrides constant", variable));
|
||||
if (moduleConstants.contains(variable)) {
|
||||
results.add(new LinterResult(LinterResult.Severity.WARNING,
|
||||
String.format("Variable \"%s\" overrides constant", variable)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,6 +39,6 @@ public final class AssignValidator extends LintVisitor {
|
||||
@Override
|
||||
public void visit(UseStatement st) {
|
||||
super.visit(st);
|
||||
st.execute();
|
||||
moduleConstants.addAll(st.loadConstants().keySet());
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,24 @@
|
||||
package com.annimon.ownlang.parser.linters;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
import com.annimon.ownlang.parser.ast.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class DefaultFunctionsOverrideValidator extends LintVisitor {
|
||||
final class DefaultFunctionsOverrideValidator extends LintVisitor {
|
||||
|
||||
private final Set<String> moduleFunctions = new HashSet<>();
|
||||
|
||||
DefaultFunctionsOverrideValidator(Collection<LinterResult> results) {
|
||||
super(results);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FunctionDefineStatement s) {
|
||||
super.visit(s);
|
||||
if (ScopeHandler.isFunctionExists(s.name)) {
|
||||
Console.error(String.format(
|
||||
"Warning: function \"%s\" overrides default module function", s.name));
|
||||
if (moduleFunctions.contains(s.name)) {
|
||||
results.add(new LinterResult(LinterResult.Severity.WARNING,
|
||||
String.format("Function \"%s\" overrides default module function", s.name)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +31,6 @@ public final class DefaultFunctionsOverrideValidator extends LintVisitor {
|
||||
@Override
|
||||
public void visit(UseStatement st) {
|
||||
super.visit(st);
|
||||
st.execute();
|
||||
moduleFunctions.addAll(st.loadFunctions().keySet());
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,14 @@ import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.Visitor;
|
||||
import com.annimon.ownlang.parser.visitors.AbstractVisitor;
|
||||
import com.annimon.ownlang.parser.visitors.VisitorUtils;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class LintVisitor extends AbstractVisitor {
|
||||
abstract class LintVisitor extends AbstractVisitor {
|
||||
protected final Collection<LinterResult> results;
|
||||
|
||||
LintVisitor(Collection<LinterResult> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
protected void applyVisitor(IncludeStatement s, Visitor visitor) {
|
||||
final Statement program = VisitorUtils.includeProgram(s);
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.annimon.ownlang.parser.linters;
|
||||
|
||||
record LinterResult(Severity severity, String message) {
|
||||
|
||||
enum Severity { ERROR, WARNING }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return severity.name() + ": " + message;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.annimon.ownlang.parser.linters;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.Visitor;
|
||||
import com.annimon.ownlang.stages.Stage;
|
||||
import com.annimon.ownlang.stages.StagesData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class LinterStage implements Stage<Statement, Statement> {
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
final List<LinterResult> results = new ArrayList<>();
|
||||
final Visitor[] validators = new Visitor[] {
|
||||
new AssignValidator(results),
|
||||
new DefaultFunctionsOverrideValidator(results)
|
||||
};
|
||||
|
||||
ScopeHandler.resetScope();
|
||||
for (Visitor validator : validators) {
|
||||
input.accept(validator);
|
||||
ScopeHandler.resetScope();
|
||||
}
|
||||
|
||||
results.sort(Comparator.comparing(LinterResult::severity));
|
||||
Console.println(String.format("Lint validation completed. %d results found!", results.size()));
|
||||
for (LinterResult r : results) {
|
||||
switch (r.severity()) {
|
||||
case ERROR -> Console.error(r.toString());
|
||||
case WARNING -> Console.println(r.toString());
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.annimon.ownlang.stages;
|
||||
|
||||
import com.annimon.ownlang.parser.Linter;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
|
||||
public class LinterStage implements Stage<Statement, Statement> {
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
Linter.lint(input);
|
||||
return input;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user