diff --git a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java index 555e3ce..0c2ca9e 100644 --- a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java +++ b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java @@ -147,7 +147,7 @@ public final class Parser { return useStatement(); } if (match(TokenType.INCLUDE)) { - return new IncludeStatement(expression()); + return includeStatement(); } if (match(TokenType.FOR)) { return forStatement(); @@ -167,6 +167,13 @@ public final class Parser { return assignmentStatement(); } + private IncludeStatement includeStatement() { + final var startTokenIndex = index - 1; + final var include = new IncludeStatement(expression()); + include.setRange(getRange(startTokenIndex, index)); + return include; + } + private UseStatement useStatement() { final var modules = new HashSet(); do { diff --git a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java index 0262a6f..45a95b3 100644 --- a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java +++ b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java @@ -6,6 +6,8 @@ import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage; import com.annimon.ownlang.stages.*; +import com.annimon.ownlang.util.Range; +import com.annimon.ownlang.util.SourceLocation; import com.annimon.ownlang.util.input.InputSourceFile; import com.annimon.ownlang.util.input.SourceLoaderStage; @@ -13,14 +15,24 @@ import com.annimon.ownlang.util.input.SourceLoaderStage; * * @author aNNiMON */ -public final class IncludeStatement extends InterruptableNode implements Statement { +public final class IncludeStatement extends InterruptableNode implements Statement, SourceLocation { public final Node expression; + private Range range; public IncludeStatement(Node expression) { this.expression = expression; } + public void setRange(Range range) { + this.range = range; + } + + @Override + public Range getRange() { + return range; + } + @Override public Value eval() { super.interruptionCheck(); @@ -31,6 +43,7 @@ public final class IncludeStatement extends InterruptableNode implements Stateme new SourceLoaderStage() .then(new LexerStage()) .then(new ParserStage()) + // TODO LinterStage based on main context .then(new FunctionAddingStage()) .then(new ExecutionStage()) .perform(stagesData, new InputSourceFile(path)); diff --git a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/IncludeSourceValidator.java b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/IncludeSourceValidator.java index 91c1a00..c02995b 100644 --- a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/IncludeSourceValidator.java +++ b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/IncludeSourceValidator.java @@ -23,11 +23,13 @@ final class IncludeSourceValidator extends LintVisitor { final String path = expr.eval().asString(); if (!detector.isReadable(path)) { results.add(LinterResult.error( - "Include statement path \"%s\" is not readable".formatted(path))); + "Include statement path \"%s\" is not readable".formatted(path), + s.getRange())); } } else { results.add(LinterResult.warning( - "Include statement path \"%s\" is not a constant string".formatted(s.expression))); + "Include statement path \"%s\" is not a constant string".formatted(s.expression), + s.getRange())); } } } diff --git a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/LinterResult.java b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/LinterResult.java index 5401677..f555456 100644 --- a/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/LinterResult.java +++ b/ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/LinterResult.java @@ -11,10 +11,18 @@ record LinterResult(Severity severity, String message, Range range) implements S return new LinterResult(Severity.WARNING, message); } + static LinterResult warning(String message, Range range) { + return new LinterResult(Severity.WARNING, message, range); + } + static LinterResult error(String message) { return new LinterResult(Severity.ERROR, message); } + static LinterResult error(String message, Range range) { + return new LinterResult(Severity.ERROR, message, range); + } + LinterResult(Severity severity, String message) { this(severity, message, null); }