Skip to content

Commit

Permalink
Merge branch 'topic/aggregate_projects' into 'master'
Browse files Browse the repository at this point in the history
JGNATcheck: Add support for aggregate projects.

Closes #76

See merge request eng/libadalang/langkit-query-language!81
  • Loading branch information
Roldak committed Jul 31, 2023
2 parents 54637c4 + 9221150 commit 9f2ded7
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ public class GNATCheckWorker extends AbstractLanguageLauncher {
*/
private String projectFile = null;

/**
* The name of the subproject to analyse, if any.
* This implies that `projectFile` designates an aggregate project.
*/
private String subprojectFile = null;

/**
* The project's scenario variables
*/
Expand Down Expand Up @@ -169,6 +175,10 @@ protected int executeScript(Context.Builder contextBuilder) {
contextBuilder.option("lkql.projectFile", this.projectFile);
}

if (this.subprojectFile != null) {
contextBuilder.option("lkql.subprojectFile", this.subprojectFile);
}

if (this.scenarioVars != null) {
contextBuilder.option("lkql.scenarioVars", this.scenarioVars);
}
Expand Down Expand Up @@ -292,8 +302,8 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
}

if (currentArg.equals("-A")) {
// Use the specified aggregated project file instead of the aggregate project itself
this.projectFile = iterator.next();
// Use the specified aggregated project (`projectFile` holds the aggregate project)
this.subprojectFile = iterator.next();

// TODO: handle "-o=..." and "-ox=..."
iterator.next();
Expand Down Expand Up @@ -370,7 +380,7 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
*
* @param filename The filename containing the rule specifications for this run
* @param allRules The list in which to add all parsed rules
* @param allArgs The list in which to add all parsed rule arguments
* @param allArgs The list in which to add all parsed rule arguments
*/
private static void processRuleSpecificationFile(
String filename,
Expand All @@ -391,10 +401,10 @@ private static void processRuleSpecificationFile(
* <p>
* A GNATcheck rule specification can also specify arguments for that rule, so these are parsed as well
* and added to the list of rule arguments.
*
* @param ruleSpec The rule specification to parse
* @param allRules The list of all currently parsed rules, in which we'll add this one
* @param allArgs The list of all currently specified rule arguments, which might be expanded here
* @param allArgs The list of all currently specified rule arguments, which might be expanded here
*/
private static void processRuleSpecification(
String ruleSpec,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,21 +534,24 @@ public void initSources() {
// Create the project manager
this.projectManager = Libadalang.ProjectManager.create(projectFileName, this.getScenarioVars(), "", "");

final String subprojectName = this.env.getOptions().get(LKQLLanguage.subprojectFile);
final String[] subprojects = subprojectName.isEmpty() ? null : new String[] {subprojectName};

// If no files were specified by the user, the files to analyze are those of the root project
// (i.e. without recusing into project dependencies)
if (this.specifiedSourceFiles.isEmpty()) {
this.specifiedSourceFiles = Arrays.stream(
this.projectManager.getFiles(Libadalang.SourceFileMode.ROOT_PROJECT)
this.projectManager.getFiles(Libadalang.SourceFileMode.ROOT_PROJECT, subprojects)
).toList();
}

// The `units()` built-in function must return all units of the project including units from its
// dependencies. So let's retrieve all those files as well.
this.allSourceFiles = Arrays.stream(
this.projectManager.getFiles(Libadalang.SourceFileMode.WHOLE_PROJECT)
this.projectManager.getFiles(Libadalang.SourceFileMode.WHOLE_PROJECT, subprojects)
).toList();

provider = this.projectManager.getProvider();
provider = this.projectManager.getProvider(subprojectName.isEmpty() ? null : subprojectName);
} else {
// When no project is specified, `units()` should return the same set of units as `specified_units()`.
this.allSourceFiles = this.specifiedSourceFiles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ public enum DiagnosticOutputMode {
)
static final OptionKey<String> projectFile = new OptionKey<>("");

/**
* The name of the subproject to analyze. If empty, use the root project instead
*/
@Option(
help = "The name of the subproject to analyze.",
category = OptionCategory.USER,
stability = OptionStability.STABLE
)
static final OptionKey<String> subprojectFile = new OptionKey<>("");

/**
* The scenario variables to load the project file with, where "key=value" variable specifications
* are encoded as Base64 and separated by semicolons.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project A is
Dir := External ("SRC_DIR", "src_1");

for Source_Dirs use (Dir);
end A;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
aggregate project Agg is
for External ("SRC_DIR") use "src_2";

for Project_Files use ("a.gpr", "b.gpr");
end Agg;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project B is
Dir := External ("SRC_DIR", "src_1");

for Source_Dirs use (Dir);
end B;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
procedure Test is
begin
null;
end Test;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package Test is
package Local is
end Local;
end Test;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

Processing aggregated project /a.gpr
Expected report file: /gnatcheck_1.out
Exit code is 1 (rule violation(s) detected)

Processing aggregated project /b.gpr
Expected report file: /gnatcheck_2.out
Exit code is 1 (rule violation(s) detected)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This test checks that aggregate project containing multiple aggregated
# projects are handled correctly:
# 1. Each aggregated project is analyzed independently.
# 2. External attributes clauses in the aggregate project are correctly taken
# into account in aggregated projects.

driver: gnatcheck
project: agg.gpr
rules:
- +Rlocal_packages

0 comments on commit 9f2ded7

Please sign in to comment.