Skip to content

Commit

Permalink
Merge branch 'topic/fix_gnatcheck_testsuite' into 'master'
Browse files Browse the repository at this point in the history
Work on fixing gnatcheck-testsuite diffs in Java mode

See merge request eng/libadalang/langkit-query-language!72
  • Loading branch information
Roldak committed Jul 17, 2023
2 parents 5356d11 + e7b43d5 commit e68e7f8
Show file tree
Hide file tree
Showing 17 changed files with 263 additions and 94 deletions.
6 changes: 6 additions & 0 deletions lkql_checker/lalcheck/gnatcheck-compiler.adb
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@ package body Gnatcheck.Compiler is
if Index (Msg (Idx .. Msg'Last), ": violation of restriction") /= 0
then
Message_Kind := Restriction;
elsif Msg (Idx + 9 .. Idx + 19) = "cannot find" then
Message_Kind := Warning;
Report_Missing_File
(Gnatcheck.Source_Table.File_Name (SF),
Msg (Idx + 21 .. Msg'Last));
return;
else
Message_Kind := Warning;
end if;
Expand Down
20 changes: 19 additions & 1 deletion lkql_checker/lalcheck/gnatcheck-output.adb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ with Ada.Strings; use Ada.Strings;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;

with GNAT.OS_Lib; use GNAT.OS_Lib;
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
with GNAT.OS_Lib; use GNAT.OS_Lib;

with Gnatcheck.Options; use Gnatcheck.Options;
with Gnatcheck.String_Utilities; use Gnatcheck.String_Utilities;
Expand Down Expand Up @@ -426,6 +427,23 @@ package body Gnatcheck.Output is
Error (Exception_Information (Ex));
end Report_Unhandled_Exception;

-------------------------
-- Report_Missing_File --
-------------------------

procedure Report_Missing_File (From_File, Missing_File : String) is
function Format_Filename (F : String) return String is
(if Full_Source_Locations then F else Base_Name (F));
-- Formats filename
begin
Warning
(Format_Filename (From_File)
& ": cannot find "
& Format_Filename (Missing_File));

Missing_File_Detected := True;
end Report_Missing_File;

------------------
-- Set_Log_File --
------------------
Expand Down
3 changes: 3 additions & 0 deletions lkql_checker/lalcheck/gnatcheck-output.ads
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ package Gnatcheck.Output is
procedure Report_Unhandled_Exception (Ex : Exception_Occurrence);
-- Reports an unhandled exception into Standard_Error

procedure Report_Missing_File (From_File, Missing_File : String);
-- Reports that a required file could not be found

procedure Error (Message : String);
-- Sends into Stderr the error message in the form 'Tool_Name: Message'

Expand Down
15 changes: 7 additions & 8 deletions lkql_checker/lalcheck/gnatcheck-source_table.adb
Original file line number Diff line number Diff line change
Expand Up @@ -1838,16 +1838,15 @@ package body Gnatcheck.Source_Table is
Found : Boolean;
Is_Not_Found_Error : Boolean)
is
function Format_Filename (F : String) return String is
(if Full_Source_Locations then F else Base_Name (F));
-- Formats filename
begin
if not Found and then Is_Not_Found_Error then
Warning
(Format_Filename (From.Get_Filename)
& ": cannot find "
& Format_Filename (To_String (Name)));
Missing_File_Detected := True;
if Subprocess_Mode then
Put_Line
(From.Get_Filename & ":1:1: warning: cannot find "
& To_String (Name));
else
Report_Missing_File (From.Get_Filename, To_String (Name));
end if;
end if;
end Unit_Requested_Callback;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.graalvm.launcher.AbstractLanguageLauncher;
import org.graalvm.options.OptionCategory;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Source;

import java.io.*;
Expand Down Expand Up @@ -93,6 +94,11 @@ protected enum ArgumentStatus {
*/
private boolean verbose = false;

/**
* Whether to keep the engine running when a required file was not found
*/
private boolean keepGoingOnMissingFile = false;

// ----- Checker options -----

/**
Expand Down Expand Up @@ -213,6 +219,10 @@ protected int executeScript(Context.Builder contextBuilder) {
contextBuilder.option("lkql.verbose", "true");
}

if (this.keepGoingOnMissingFile) {
contextBuilder.option("lkql.keepGoingOnMissingFile", "true");
}

// Set the project file
if (this.projectFile != null) {
contextBuilder.option("lkql.projectFile", this.projectFile);
Expand Down Expand Up @@ -255,7 +265,9 @@ protected int executeScript(Context.Builder contextBuilder) {
// Return the success
return 0;
} catch (Exception e) {
if (this.verbose) {
if (e instanceof PolyglotException pe && pe.isExit()) {
return pe.getExitStatus();
} else if (this.verbose) {
e.printStackTrace();
} else {
System.err.println(e.getMessage());
Expand Down Expand Up @@ -354,6 +366,7 @@ protected String expandShortFlag(String shortFlag) {
case "v" -> "verbose";
case "r" -> "rules";
case "a" -> "rule-arg";
case "k" -> "keep-going-on-missing-file";
default -> null;
};
}
Expand All @@ -376,6 +389,10 @@ protected ArgumentStatus processFlag(String flag) {
this.verbose = true;
break;

case "keep-going-on-missing-file":
this.keepGoingOnMissingFile = true;
break;

// Default behavior
default:
return ArgumentStatus.Unhandled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ protected int executeScript(Context.Builder contextBuilder) {
// If no rules are provided, don't do anything
contextBuilder.option("lkql.fallbackToAllRules", "false");

// Do not stop the worker's execution when a source file is missing
contextBuilder.option("lkql.keepGoingOnMissingFile", "true");

// Set the context options
if (this.verbose) {
contextBuilder.option("lkql.verbose", "true");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.TruffleLanguage;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.*;
import java.util.*;
import java.util.function.Consumer;

Expand Down Expand Up @@ -140,6 +144,9 @@ public final class LKQLContext {
@CompilerDirectives.CompilationFinal
private Boolean isChecker = null;

@CompilerDirectives.CompilationFinal
private Boolean keepGoingOnMissingFile = null;

/**
* The project file to analyse
*/
Expand Down Expand Up @@ -285,6 +292,16 @@ public boolean isChecker() {
return this.isChecker;
}

/**
* Return true if the engine should keep running when a required file is not found.
*/
public boolean keepGoingOnMissingFile() {
if (this.keepGoingOnMissingFile == null) {
this.keepGoingOnMissingFile = this.env.getOptions().get(LKQLLanguage.keepGoingOnMissingFile);
}
return this.keepGoingOnMissingFile;
}

/**
* Return the project file of the language context
*
Expand Down Expand Up @@ -477,8 +494,8 @@ public void println(String toPrint) {
public CheckerUtils.DiagnosticEmitter getDiagnosticEmitter() {
if (this.emitter == null) {
this.emitter = switch (this.env.getOptions().get(LKQLLanguage.diagnosticOutputMode)) {
case PRETTY -> CheckerUtils::printRuleViolation;
case GNATCHECK -> CheckerUtils::printGNATcheckRuleViolation;
case PRETTY -> new CheckerUtils.DefaultEmitter();
case GNATCHECK -> new CheckerUtils.GNATcheckEmitter();
};
}
return this.emitter;
Expand Down Expand Up @@ -538,10 +555,9 @@ public void initSources() {

// If required, create an auto provider with the specified files.
if (this.env.getOptions().get(LKQLLanguage.useAutoProvider)) {
provider = Libadalang.createAutoProvider(
this.allSourceFiles.toArray(new String[0]),
charset
);
final List<String> allFiles = this.fetchAdaRuntimeFiles();
allFiles.addAll(this.allSourceFiles);
provider = Libadalang.createAutoProvider(allFiles.toArray(new String[0]), charset);
} else {
provider = null;
}
Expand All @@ -552,20 +568,62 @@ public void initSources() {
}
}

// Create the ada context
this.adaContext = Libadalang.AnalysisContext.create(
charset,
null,
provider,
null,
true,
8
);
// Setup the event handler
final Libadalang.EventHandler.UnitRequestedCallback unitRequested =
(ctx, name, from, found, not_found_is_error) -> {
if (!found && not_found_is_error) {
boolean isFatal = !this.keepGoingOnMissingFile();
this.getDiagnosticEmitter().emitMissingFile(from, name, isFatal, this);
if (isFatal) {
this.env.getContext().closeExited(null, 1);
}
}
};

try (Libadalang.EventHandler eventHandler =
Libadalang.EventHandler.create(unitRequested, null)) {
// Create the ada context
this.adaContext = Libadalang.AnalysisContext.create(
charset,
null,
provider,
eventHandler,
true,
8
);
}

// The retrieved source files are not yet parsed
this.parsed = false;
}

/**
* Return the list of files that belong to the available runtime. We only return specification files,
* as implementation are not useful for resolving names and types in the actual user sources.
* If a GNAT installation is not available in the PATH, this returns an empty list without error.
*/
@CompilerDirectives.TruffleBoundary
public List<String> fetchAdaRuntimeFiles() {
final List<String> runtimeFiles = new ArrayList<>();
try {
final Process gnatls = new ProcessBuilder("gnatls", "-v").start();
final BufferedReader reader = new BufferedReader(new InputStreamReader(gnatls.getInputStream()));
final Optional<String> adaIncludePath =
reader.lines().filter(line -> line.contains("adainclude")).findFirst();
adaIncludePath.ifPresent(path -> {
final Path adaIncludeDir = Paths.get(path.trim());
try (DirectoryStream<Path> stream = Files.newDirectoryStream(adaIncludeDir, "*.ads")) {
stream.forEach(file -> runtimeFiles.add(file.toString()));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (IOException ignored) {
// No runtime available, not a problem
}
return runtimeFiles;
}

/**
* Parse the ada source files and store analysis units and root nodes
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ public enum DiagnosticOutputMode {
)
static final OptionKey<Boolean> fallbackToAllRules = new OptionKey<>(true);

/**
* The option to control what should be done when a source file cannot be found
*/
@Option(
help = "If true, do not stop the engine when a source file cannot be found",
category = OptionCategory.USER,
stability = OptionStability.STABLE
)
static final OptionKey<Boolean> keepGoingOnMissingFile = new OptionKey<>(false);

/**
* The option to specify arguments for the rules
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ private static void reportViolation(
Libadalang.AdaNode definingName = basicDecl.pDefiningName();
node = definingName.isNone() ? node : definingName;
}
context.getDiagnosticEmitter().emit(
context.getDiagnosticEmitter().emitRuleViolation(
(String) rule.get("name"),
(String) rule.get("message"),
node.getSourceLocationRange(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import com.adacore.lkql_jit.utils.LKQLTypesHelper;
import com.adacore.lkql_jit.utils.util_classes.Iterator;
import com.adacore.lkql_jit.utils.util_functions.CheckerUtils;
import com.adacore.lkql_jit.utils.util_functions.StringUtils;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
Expand Down Expand Up @@ -264,7 +263,7 @@ private void applyUnitRule(
);
}

context.getDiagnosticEmitter().emit(
context.getDiagnosticEmitter().emitRuleViolation(
ruleName,
messageText,
slocRange,
Expand Down
Loading

0 comments on commit e68e7f8

Please sign in to comment.