diff --git a/lkql_checker/share/examples/README.gnatcheck b/lkql_checker/share/examples/README.md similarity index 51% rename from lkql_checker/share/examples/README.gnatcheck rename to lkql_checker/share/examples/README.md index 25ac71b7a..37bc8c4a2 100644 --- a/lkql_checker/share/examples/README.gnatcheck +++ b/lkql_checker/share/examples/README.md @@ -1,40 +1,36 @@ - G N A T C H E C K E X A M P L E - ================================== +GNATcheck Example +================= This directory contains a simple example of using GNATcheck. This example is derived from one of the examples included in the GNAT compiler distribution (see the subdirectory share/examples/gnat/simple_project of your compiler installation if you have one). -Compared to the original example, the following two things have been added: +Compared to the original example, a sample GNATcheck coding standard file named +`rules.lkql` has been added. This is an LKQL file containing a set of GNATcheck +rules and their configuration. -- A sample GNATcheck coding standard file named 'coding_standard.rules'; this - is a text file containing a set of GNATcheck rule options). - -- The original project file now contains the package 'Check'; this package - tells GNATcheck to use the coding standard file mentioned above. - -If you want to try out GNATcheck on any other project - just copy the sample -coding standard file to another project's directory, and add the -'Check' package to this project file. +If you want to try out GNATcheck on any other project, simply copy the sample +coding standard file to the project's directory, besides the GPR file. +GNATcheck will use it by default when running on this project file. You can also modify the coding standard file in any way you want - you can add new rules, change rule parameters, disable some rules. Please refer to the GNATcheck Reference Manual for more details. - Using GNATcheck from the command line ------------------------------------- $ gnatcheck -P simple.gpr GNATcheck will output messages in your command shell, and will also generate -the report file "gnatcheck.out" in the project's objects directory. +the report file `gnatcheck/gnatcheck.out` in the project's object directory. + Using GNATcheck from GPS ------------------------ Open the project file in GPS, then choose the command -'Analyze->Coding Standard->Check Root Project". You will see the diagnoses +`Analyze->Coding Standard->Check Root Project`. You will see the diagnoses generated by gnatcheck in the 'Locations' GPS window. diff --git a/lkql_checker/share/examples/coding_standard.rules b/lkql_checker/share/examples/coding_standard.rules deleted file mode 100644 index e04b5c6b4..000000000 --- a/lkql_checker/share/examples/coding_standard.rules +++ /dev/null @@ -1,70 +0,0 @@ -+R Abstract_Type_Declarations -+R Anonymous_Arrays -+R Anonymous_Subtypes -+R Blocks - -+R Boolean_Relational_Operators --- Flag each call to a predefined relational operator --- (<, >, <=, >=, = and /=) for the predefined Boolean type. - -+R Complex_Inlined_Subprograms : 3 --- Flag a subprogram (or generic subprogram, or instantiation of a --- subprogram) if pragma Inline is applied to it and at least one of the --- following conditions is met: --- * it contains at least one complex declaration such as a subprogram --- body, package, task, protected declaration, or a generic instantiation --- (except instantiation of Ada.Unchecked_Conversion); --- * it contains at least one complex statement such as a loop, a case or --- an if statement; --- * the number of statements exceeds 3 - -+R Controlled_Type_Declarations - -+R Deep_Inheritance_Hierarchies : 5 --- Flag a tagged derived type declaration or an interface type declaration --- if its depth (in its inheritance hierarchy) exceeds 5 - -+R Deeply_Nested_Generics : 3 --- Flag a generic declaration nested in another generic declaration if the --- nesting level of the inner generic exceeds 3 - -+R Identifier_Casing : Others = mixed --- Flag any defining identifier if it casing does not follow the rules: the --- first letter and every letter after underscore are uppercase, all the --- other lettres are lowercase - -+R Identifier_Suffixes : Type_Suffix = _Type -+R Identifier_Suffixes : Access_Suffix = _Access_Type -+R Identifier_Suffixes : Class_Access_Suffix = _Class_Type --- Flag any defining identifier if it corresponds to the given kind of --- entities but does not have a specified suffix - -+R Identifier_Prefixes : Type = T_, - Access = A_, - constant = C_ --- Flag any defining identifier if it corresponds to the given kind of --- entities but does not have a specified prefix - -+R Non_Qualified_Aggregates -+R Non_Short_Circuit_Operators - -+R OTHERS_In_Aggregates -+R OTHERS_In_CASE_Statements -+R OTHERS_In_Exception_Handlers - -+R Warnings:km --- Include warnings generated by the compiler with '-gnatwk' (variables that --- could be constants) and '-gnatwm' (modified but unreferenced variables) --- into generated gnatcheck report - -+R Style_Checks: u -+R Style_Checks: O --- Include warnings generated by the compiler style checks '-gnatyu' --- (unnecessary blank lines) and '-gnatyO' (overriding subprograms are --- not explicitly marked as such.) into generated gnatcheck report - -+R Restrictions: No_Allocators, - No_Tasking -+R Restrictions : No_Dependence => Ada.Containers --- Include warnings generated by the compiler with the specified restrictions --- into generated gnatcheck report diff --git a/lkql_checker/share/examples/rules.lkql b/lkql_checker/share/examples/rules.lkql new file mode 100644 index 000000000..526eecc95 --- /dev/null +++ b/lkql_checker/share/examples/rules.lkql @@ -0,0 +1,73 @@ +val rules = @{ + Abstract_Type_Declarations, + Anonymous_Arrays, + Anonymous_Subtypes, + Blocks, + + Boolean_Relational_Operators, + # Flag each call to a predefined relational operator + # (<, >, <=, >=, = and /=) for the predefined Boolean type. + + Complex_Inlined_Subprograms: {N: 3}, + # Flag a subprogram (or generic subprogram, or instantiation of a + # subprogram) if pragma Inline is applied to it and at least one of the + # following conditions is met: + # * it contains at least one complex declaration such as a subprogram + # body, package, task, protected declaration, or a generic instantiation + # (except instantiation of Ada.Unchecked_Conversion); + # * it contains at least one complex statement such as a loop, a case or + # an if statement; + # * the number of statements exceeds 3 + + Controlled_Type_Declarations, + + Deep_Inheritance_Hierarchies: {N: 5}, + # Flag a tagged derived type declaration or an interface type declaration + # if its depth (in its inheritance hierarchy) exceeds 5 + + Deeply_Nested_Generics: {N: 3}, + # Flag a generic declaration nested in another generic declaration if the + # nesting level of the inner generic exceeds 3 + + Identifier_Casing: {Others: "mixed"}, + # Flag any defining identifier if it casing does not follow the rules: the + # first letter and every letter after underscore are uppercase, all the + # other lettres are lowercase + + Identifier_Suffixes: { + Type_Suffix: "_Type", + Access_Suffix: "_Access_Type", + Class_Access_Suffix: "_Class_Type" + }, + # Flag any defining identifier if it corresponds to the given kind of + # entities but does not have a specified suffix + + Identifier_Prefixes: { + Type: "T_", + Access: "A_", + Constant: "C_" + }, + # Flag any defining identifier if it corresponds to the given kind of + # entities but does not have a specified prefix + + Non_Qualified_Aggregates, + Non_Short_Circuit_Operators, + + OTHERS_In_Aggregates, + OTHERS_In_CASE_Statements, + OTHERS_In_Exception_Handlers, + + Warnings: "km", + # Include warnings generated by the compiler with '-gnatwk' (variables that + # could be constants) and '-gnatwm' (modified but unreferenced variables) + # into generated gnatcheck report + + Style_Checks: "uO", + # Include warnings generated by the compiler style checks '-gnatyu' + # (unnecessary blank lines) and '-gnatyO' (overriding subprograms are + # not explicitly marked as such.) into generated gnatcheck report + + Restrictions: {Arg: ["No_Allocators", "No_Tasking", "No_Dependence => Ada.Containers"]} + # Include warnings generated by the compiler with the specified restrictions + # into generated gnatcheck report +} diff --git a/lkql_checker/share/examples/simple.gpr b/lkql_checker/share/examples/simple.gpr index 0acd9ceb7..95367d309 100644 --- a/lkql_checker/share/examples/simple.gpr +++ b/lkql_checker/share/examples/simple.gpr @@ -50,10 +50,4 @@ Project Simple is -- This attribute contains the switches used for "diners" only end Builder; - package Check is - for Default_Switches ("ada") use ("-rules", "-from=coding_standard.rules"); - -- This attribute contains the switches used by the coding standard - -- verifier - end Check; - end Simple; diff --git a/lkql_checker/src/gnatcheck-projects.adb b/lkql_checker/src/gnatcheck-projects.adb index 42c836af5..a052b81f8 100644 --- a/lkql_checker/src/gnatcheck-projects.adb +++ b/lkql_checker/src/gnatcheck-projects.adb @@ -369,10 +369,13 @@ package body Gnatcheck.Projects is (My_Project : Arg_Project_Type; Filename : String) return String is begin - if Gnatcheck.Options.Gnatcheck_Prj.Is_Specified then + if Gnatcheck.Options.Gnatcheck_Prj.Is_Specified + and then Gnatcheck.Options.Gnatcheck_Prj.Tree.Is_Defined + then return Normalize_Pathname (GNAT.Directory_Operations.Dir_Name - (Gnatcheck.Options.Gnatcheck_Prj.Source_Prj.all) & Filename); + (Gnatcheck_Prj.Tree.Root_Project.Path_Name.String_Value) & + Filename); else return Normalize_Pathname (Filename); end if; diff --git a/testsuite/tests/gnatcheck/example/test.out b/testsuite/tests/gnatcheck/example/test.out new file mode 100644 index 000000000..c9a7bb3db --- /dev/null +++ b/testsuite/tests/gnatcheck/example/test.out @@ -0,0 +1,76 @@ +chop.adb:14:11: PIck_Up does not have casing specified (mixed) +chop.ads:11:18: Stick does not start with subtype prefix T_ +phil.adb:21:11: Think_Times does not start with subtype prefix T_ +phil.adb:25:11: Meal_Times does not start with subtype prefix T_ +phil.adb:31:13: Life_Time does not start with subtype prefix T_ +phil.adb:33:05: "Who_Am_I" is not modified, could be declared constant +phil.ads:12:03: violation of restriction "No_Tasking" +phil.ads:12:13: Philosopher does not start with subtype prefix T_ +phil.ads:12:26: My_ID does not have casing specified (mixed) +phil.ads:19:08: States does not end with type suffix _Type +phil.ads:19:08: States does not start with subtype prefix T_ +random_generic.ads:5:08: Result_Subtype does not end with type suffix _Type +random_generic.ads:5:08: Result_Subtype does not start with subtype prefix T_ +room.adb:19:03: violation of restriction "No_Tasking" +room.adb:19:23: anonymous subtype +room.adb:20:03: violation of restriction "No_Tasking" +room.adb:20:23: anonymous subtype +room.adb:21:03: violation of restriction "No_Tasking" +room.adb:21:23: anonymous subtype +room.adb:22:03: violation of restriction "No_Tasking" +room.adb:22:23: anonymous subtype +room.adb:23:03: violation of restriction "No_Tasking" +room.adb:23:23: anonymous subtype +room.adb:25:08: Philosopher_Ptr does not end with access suffix _Access_Type +room.adb:25:08: Philosopher_Ptr does not start with access prefix A_ +room.adb:27:11: anonymous array type +room.adb:28:18: anonymous array type +room.adb:29:16: anonymous array type +room.adb:35:05: Blanks does not start with constant prefix C_ +room.adb:55:22: aggregate is not a part of a qualified expression +room.adb:56:22: aggregate is not a part of a qualified expression +room.adb:57:22: aggregate is not a part of a qualified expression +room.adb:58:22: aggregate is not a part of a qualified expression +room.adb:59:22: aggregate is not a part of a qualified expression +room.adb:60:01: multiple blank lines +room.adb:62:25: anonymous subtype +room.ads:18:03: Table_Size does not start with constant prefix C_ +room.ads:19:11: Table_Type does not start with subtype prefix T_ +room.ads:21:12: anonymous array type +room.ads:23:03: violation of restriction "No_Tasking" +screen.adb:15:11: Int_IO does not have casing specified (mixed) +screen.adb:22:13: ClearScreen does not have casing specified (mixed) +screen.adb:28:13: MoveCursor does not have casing specified (mixed) +screen.ads:10:03: ScreenHeight does not have casing specified (mixed) +screen.ads:10:03: ScreenHeight does not start with constant prefix C_ +screen.ads:11:03: ScreenWidth does not have casing specified (mixed) +screen.ads:11:03: ScreenWidth does not start with constant prefix C_ +screen.ads:13:11: Height does not start with subtype prefix T_ +screen.ads:14:11: Width does not start with subtype prefix T_ +screen.ads:16:08: Position does not end with type suffix _Type +screen.ads:16:08: Position does not start with subtype prefix T_ +screen.ads:25:13: ClearScreen does not have casing specified (mixed) +screen.ads:29:13: MoveCursor does not have casing specified (mixed) +society.ads:11:11: Unique_DNA_Codes does not have casing specified (mixed) +society.ads:11:11: Unique_DNA_Codes does not start with subtype prefix T_ +society.ads:13:19: anonymous array type +society.ads:13:46: anonymous subtype +windows.adb:11:18: UpperLeft does not have casing specified (mixed) +windows.adb:18:22: aggregate is not a part of a qualified expression +windows.adb:23:13: EraseToEndOfLine does not have casing specified (mixed) +windows.adb:26:18: anonymous subtype +windows.adb:62:18: anonymous subtype +windows.adb:93:20: anonymous subtype +windows.adb:107:18: anonymous subtype +windows.adb:113:18: anonymous subtype +windows.adb:114:26: aggregate is not a part of a qualified expression +windows.adb:116:26: aggregate is not a part of a qualified expression +windows.adb:121:24: aggregate is not a part of a qualified expression +windows.adb:123:18: anonymous subtype +windows.adb:129:17: aggregate is not a part of a qualified expression +windows.adb:130:17: aggregate is not a part of a qualified expression +windows.adb:134:13: MoveCursor does not have casing specified (mixed) +windows.ads:11:08: Window does not end with type suffix _Type +windows.ads:11:08: Window does not start with subtype prefix T_ +windows.ads:13:18: UpperLeft does not have casing specified (mixed) +windows.ads:33:13: MoveCursor does not have casing specified (mixed) diff --git a/testsuite/tests/gnatcheck/example/test.yaml b/testsuite/tests/gnatcheck/example/test.yaml new file mode 100644 index 000000000..8612b7e66 --- /dev/null +++ b/testsuite/tests/gnatcheck/example/test.yaml @@ -0,0 +1,4 @@ +driver: gnatcheck +format: brief +project: simple +check_flags: False diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index bd14ddabe..9e7470f99 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -163,6 +163,15 @@ def set_up(self) -> None: # Directory that contains GPR files, shared by testcases os.environ['GPR_PROJECT_PATH'] = P.pathsep.join([ P.join(self.root_dir, 'ada_projects'), + P.abspath( + P.join( + self.root_dir, + '..', + 'lkql_checker', + 'share', + 'examples' + ) + ), os.environ.get('GPR_PROJECT_PATH', ''), ])