diff --git a/check/checkconfigurations/checkconfigurations.go b/check/checkconfigurations/checkconfigurations.go index 7454fb20..e1774544 100644 --- a/check/checkconfigurations/checkconfigurations.go +++ b/check/checkconfigurations/checkconfigurations.go @@ -58,39 +58,204 @@ func Configurations() []Type { var configurations = []Type{ { ProjectType: projecttype.Library, - Category: "library.properties", + Category: "structure", Subcategory: "general", - ID: "LP001", - Brief: "missing", - Description: `Although not required for 1.0 format libraries (AKA "legacy") not in Library Manager, metadata is useful, so it is recommended.`, - MessageTemplate: "Library has no library.properties metadata file. This file provides useful information and is required for admission to the Library Manager index. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata", + ID: "LS001", + Brief: "invalid", + Description: "", + MessageTemplate: "Path does not contain a valid Arduino library. See: https://arduino.github.io/arduino-cli/latest/library-specification", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.LibraryInvalid, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "root folder", + ID: "LS002", + Brief: "folder name too long", + Description: "This will be problematic for people doing manual installation of the library.", + MessageTemplate: "Folder name {{.}} exceeds maximum length. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Permissive}, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.LibraryFolderNameGTMaxLength, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "root folder", + ID: "LS003", + Brief: "disallowed characters in folder name", + Description: "This will be problematic for people doing manual installation of the library.", + MessageTemplate: "Prohibited characters in folder name: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Permissive}, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.ProhibitedCharactersInLibraryFolderName, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "miscellaneous", + ID: "LS004", + Brief: "submodule", + Description: "", + MessageTemplate: `Git submodule detected. Library Manager installations and installations from GitHub's "Download ZIP" will only contain an empty folder in place of the submodule.`, + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: nil, + CheckFunction: checkfunctions.LibraryHasSubmodule, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "miscellaneous", + ID: "LS005", + Brief: "symlink", + Description: "", + MessageTemplate: "Symlink(s) found at {{.}}. These block acceptance to the Arduino Library Manager index.", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed}, + CheckFunction: checkfunctions.LibraryContainsSymlinks, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "miscellaneous", + ID: "LS006", + Brief: ".development file", + Description: "", + MessageTemplate: ".development flag file found. Presence of this file blocks addition to the Library Manager index.", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: []checkmode.Type{checkmode.Default}, ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed, checkmode.Strict}, - CheckFunction: checkfunctions.LibraryPropertiesMissing, + CheckFunction: checkfunctions.LibraryHasDotDevelopmentFile, }, { ProjectType: projecttype.Library, - Category: "library.properties", - Subcategory: "general", - ID: "LP001", - Brief: "invalid format", + Category: "structure", + Subcategory: "miscellaneous", + ID: "LS007", + Brief: ".exe file", Description: "", - MessageTemplate: "library.properties has an invalid format: {{.}}", + MessageTemplate: ".exe file(s) found: {{.}}. Presence of these files blocks inclusion in Library Manager index.", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed, checkmode.Strict}, + CheckFunction: checkfunctions.LibraryHasExe, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "source code", + ID: "LS008", + Brief: "name-header mismatch", + Description: `The name value determines the installation folder name and the folder match to the filename in the #include directive influences "folder name priority".`, + MessageTemplate: "No header file found matching library name ({{.}}). Best practices are for primary header filename to match library name.", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: []checkmode.Type{checkmode.Permissive}, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: nil, + CheckFunction: checkfunctions.LibraryPropertiesNameFieldHeaderMismatch, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "source code", + ID: "LS009", + Brief: "incorrect src folder case", + Description: "", + MessageTemplate: "Incorrect src folder case: {{.}}. This will cause the library to not be recognized on case-sensitive operating systems. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: nil, ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.LibraryPropertiesFormat, + CheckFunction: checkfunctions.IncorrectLibrarySrcFolderNameCase, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "source code", + ID: "LS010", + Brief: "recursive with utility folder", + Description: "", + MessageTemplate: `Utility folder found in "1.5" format library. Compilation of this folder is only supported on "1.0" format libraries. See: https://arduino.github.io/arduino-cli/latest/library-specification/#source-code`, + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Permissive}, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.RecursiveLibraryWithUtilityFolder, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "extras folder", + ID: "LS011", + Brief: "incorrect extras folder name", + Description: "", + MessageTemplate: "Potentially misspelled extras folder name found: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#extra-documentation", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.Strict}, + CheckFunction: checkfunctions.MisspelledExtrasFolderName, + }, + { + ProjectType: projecttype.Library, + Category: "structure", + Subcategory: "extras folder", + ID: "LS012", + Brief: "incorrect extras folder name case", + Description: "", + MessageTemplate: "Incorrect extras folder name case: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#extra-documentation", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Permissive}, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.IncorrectExtrasFolderNameCase, + }, + { + ProjectType: projecttype.Library, + Category: "library.properties", + Subcategory: "general", + ID: "LP001", + Brief: "missing", + Description: `Although not required for 1.0 format libraries (AKA "legacy") not in Library Manager, metadata is useful, so it is recommended.`, + MessageTemplate: "Library has no library.properties metadata file. This file provides useful information and is required for admission to the Library Manager index. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed, checkmode.Strict}, + CheckFunction: checkfunctions.LibraryPropertiesMissing, }, { ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "general", - ID: "", + ID: "LP002", Brief: "incorrect library.properties file name", Description: "", MessageTemplate: "Incorrectly spelled library.properties file name found: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata", @@ -105,7 +270,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "general", - ID: "", + ID: "LP003", Brief: "incorrect library.properties file name case", Description: `This causes "1.5" format (AKA "recursive layout") libraries to not be recognized on filename case-sensitive operating systems.`, MessageTemplate: "Incorrect library.properties file name case: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata", @@ -120,7 +285,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "general", - ID: "", + ID: "LP004", Brief: "redundant", Description: "", MessageTemplate: "Redundant library.properties file found at {{.}}. Only the file in the root of the library is used. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata", @@ -131,11 +296,41 @@ var configurations = []Type{ ErrorModes: []checkmode.Type{checkmode.Default}, CheckFunction: checkfunctions.RedundantLibraryProperties, }, + { + ProjectType: projecttype.Library, + Category: "library.properties", + Subcategory: "general", + ID: "LP005", + Brief: "invalid format", + Description: "", + MessageTemplate: "library.properties has an invalid format: {{.}}", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.LibraryPropertiesFormat, + }, + { + ProjectType: projecttype.Library, + Category: "library.properties", + Subcategory: "general", + ID: "LP006", + Brief: "misspelled field", + Description: "", + MessageTemplate: "Potentially misspelled library.properties field name detected. See: https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.Strict}, + CheckFunction: checkfunctions.LibraryPropertiesMisspelledOptionalField, + }, { ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "LP002", + ID: "LP007", Brief: "missing name field", Description: "", MessageTemplate: "missing name field in library.properties", @@ -150,7 +345,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP008", Brief: "name < min length", Description: "", MessageTemplate: "library.properties name value is less than minimum length.", @@ -165,7 +360,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP009", Brief: "name > max length", Description: "", MessageTemplate: "library.properties name value {{.}} is longer than maximum length.", @@ -180,7 +375,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP010", Brief: "name > recommended length", Description: "", MessageTemplate: "library.properties name value {{.}} is longer than recommended max length.", @@ -195,7 +390,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "LP003", + ID: "LP011", Brief: "disallowed characters", Description: "", MessageTemplate: "disallowed characters in library.properties name value: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -210,22 +405,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", - Brief: "contains spaces", - Description: "Best practices is for the name value, installation folder, and primary header filename to all match, but this is not possible with names containing spaces.", - MessageTemplate: "library.properties name {{.}} contains spaces. Although supported, best practices is to not use spaces.", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.LibraryPropertiesNameFieldHasSpaces, - }, - { - ProjectType: projecttype.Library, - Category: "library.properties", - Subcategory: "name field", - ID: "", + ID: "LP012", Brief: `starts with "Arduino"`, Description: `Case insensitive. 3rd party libraries added to Library Manager index prior to the enactment of this rule are "grandfathered".`, MessageTemplate: `Library name {{.}} starts with "Arduino". These names are reserved for official libraries.`, @@ -240,7 +420,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP013", Brief: "missing official prefix", Description: "", MessageTemplate: `Library name {{.}} is missing the "Arduino_" prefix. All new official library names must use this prefix.`, @@ -255,7 +435,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP014", Brief: `contains "Arduino"`, Description: "Case insensitive", MessageTemplate: `Library name {{.}} contains "Arduino". This is superfluous.`, @@ -270,7 +450,22 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "", + ID: "LP015", + Brief: "contains spaces", + Description: "Best practices is for the name value, installation folder, and primary header filename to all match, but this is not possible with names containing spaces.", + MessageTemplate: "library.properties name {{.}} contains spaces. Although supported, best practices is to not use spaces.", + DisableModes: nil, + EnableModes: []checkmode.Type{checkmode.Default}, + InfoModes: nil, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.Strict}, + CheckFunction: checkfunctions.LibraryPropertiesNameFieldHasSpaces, + }, + { + ProjectType: projecttype.Library, + Category: "library.properties", + Subcategory: "name field", + ID: "LP016", Brief: `contains "library"`, Description: "Case insensitive", MessageTemplate: `Library name {{.}} contains "library". This is superfluous.`, @@ -285,7 +480,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "LP005", + ID: "LP017", Brief: "duplicate name", Description: "This requirement only applies to the library.properties name value. There is no requirement to change the repository or header file names.", MessageTemplate: "Library name {{.}} is in use by a library in the Library Manager index. Each library must have a unique name value.", @@ -300,7 +495,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "name field", - ID: "LP006", + ID: "LP018", Brief: "not in LM index", Description: "The name value is the identifier used to install the library and define dependencies, so it should not be changed.", MessageTemplate: "Library name {{.}} not found in the Library Manager index. Library names are not allowed to change after being added to the index. See: https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ#how-can-i-change-my-librarys-name", @@ -311,26 +506,11 @@ var configurations = []Type{ ErrorModes: []checkmode.Type{checkmode.Default}, CheckFunction: checkfunctions.LibraryPropertiesNameFieldNotInIndex, }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "general", - ID: "", - Brief: "name-header mismatch", - Description: `The name value determines the installation folder name and the folder match to the filename in the #include directive influences "folder name priority".`, - MessageTemplate: "No header file found matching library name ({{.}}). Best practices are for primary header filename to match library name.", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: []checkmode.Type{checkmode.Permissive}, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: nil, - CheckFunction: checkfunctions.LibraryPropertiesNameFieldHeaderMismatch, - }, { ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "version field", - ID: "LP004", + ID: "LP019", Brief: "missing version field", Description: "", MessageTemplate: "missing version field in library.properties", @@ -345,7 +525,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "version field", - ID: "", + ID: "LP020", Brief: "invalid", Description: `Must be compliant with "relaxed semver".`, MessageTemplate: "library.properties version value {{.}} is invalid. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -360,7 +540,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "version field", - ID: "", + ID: "LP021", Brief: "non-semver", Description: "", MessageTemplate: "library.properties version value {{.}} is not compliant with the semver specification. See https://semver.org/", @@ -375,7 +555,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "version field", - ID: "", + ID: "LP022", Brief: "tag mismatch", Description: "The Library Manager indexer will reject any tag that has a library.properties version equal to a previous tag in the index.", MessageTemplate: "The latest Git tag appears to be greater than the library.properties version value: {{.}}. You must update the version value before making the tag.", @@ -390,7 +570,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "author field", - ID: "", + ID: "LP023", Brief: "missing author field", Description: "", MessageTemplate: "missing required author field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -405,7 +585,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "author field", - ID: "", + ID: "LP024", Brief: "author < min length", Description: "", MessageTemplate: "library.properties author value is less than minimum length.", @@ -420,7 +600,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "maintainer field", - ID: "", + ID: "LP025", Brief: "missing maintainer field", Description: "", MessageTemplate: "missing required maintainer field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -435,7 +615,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "maintainer field", - ID: "", + ID: "LP026", Brief: "maintainer < min length", Description: "", MessageTemplate: "library.properties maintainer value is less than minimum length.", @@ -450,7 +630,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "maintainer field", - ID: "", + ID: "LP027", Brief: `starts with "Arduino"`, Description: "Case insensitive.", MessageTemplate: `library.properties maintainer value {{.}} starts with "Arduino". 3rd party libraries are not maintained by Arduino.`, @@ -465,7 +645,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "email field", - ID: "", + ID: "LP028", Brief: `"email" field used as alias for "maintainer"`, Description: "This was in an early draft of the beta 1.5 library specification.", MessageTemplate: `library.properties "email" field used as alias for "maintainer". This is deprecated.`, @@ -480,7 +660,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "email field", - ID: "", + ID: "LP029", Brief: "email < min length", Description: "", MessageTemplate: "library.properties email value is less than minimum length.", @@ -495,7 +675,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "email field", - ID: "", + ID: "LP030", Brief: `starts with "Arduino"`, Description: "Case insensitive.", MessageTemplate: `library.properties email value {{.}} starts with "Arduino". 3rd party libraries are not maintained by Arduino.`, @@ -510,7 +690,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "sentence field", - ID: "", + ID: "LP031", Brief: "missing sentence field", Description: "", MessageTemplate: "missing required sentence field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -525,7 +705,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "sentence field", - ID: "", + ID: "LP032", Brief: "sentence < min length", Description: "", MessageTemplate: "library.properties sentence value is less than minimum length.", @@ -540,7 +720,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "sentence field", - ID: "", + ID: "LP033", Brief: "sentence spell check", Description: "", MessageTemplate: "A commonly misspelled word was found in the library.properties sentence field. Suggested correction: {{.}}", @@ -555,7 +735,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "paragraph field", - ID: "", + ID: "LP034", Brief: "missing paragraph field", Description: "", MessageTemplate: "missing required paragraph field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -570,7 +750,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "paragraph field", - ID: "", + ID: "LP035", Brief: "paragraph spell check", Description: "", MessageTemplate: "A commonly misspelled word was found in the library.properties paragraph field. Suggested correction: {{.}}", @@ -585,7 +765,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "paragraph field", - ID: "", + ID: "LP036", Brief: "paragraph repeats sentence", Description: "", MessageTemplate: "The library.properties paragraph field repeats the sentence field. These are displayed together so redundancy is not needed.", @@ -600,7 +780,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "category field", - ID: "", + ID: "LP037", Brief: "missing category field", Description: `This can cause a warning and results in the default "Uncategorized" category being used.`, MessageTemplate: "missing category field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -615,7 +795,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "category field", - ID: "", + ID: "LP038", Brief: "invalid category value", Description: `This can cause a warning and results in the default "Uncategorized" category being used.`, MessageTemplate: "invalid category field value {{.}} in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -630,7 +810,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "category field", - ID: "", + ID: "LP039", Brief: `"Uncategorized" category value`, Description: "There is no good reason for using this non-specification compliant category value.", MessageTemplate: `Use of "Uncategorized" category value in library.properties. Please use one of the supported categories listed at https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format`, @@ -645,7 +825,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "url field", - ID: "", + ID: "LP040", Brief: "missing url field", Description: "", MessageTemplate: "missing required url field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -660,7 +840,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "url field", - ID: "", + ID: "LP041", Brief: "invalid url format", Description: "", MessageTemplate: "library.properties url field value {{.}} does not have a valid URL format.", @@ -675,7 +855,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "url field", - ID: "", + ID: "LP042", Brief: "Dead URL", Description: "", MessageTemplate: "Unable to load the library.properties url field: {{.}}", @@ -690,7 +870,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "architectures field", - ID: "", + ID: "LP043", Brief: "missing architectures field", Description: "Defaults to *, but it's better to explicitly define architectures.", MessageTemplate: "missing architectures field in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -705,7 +885,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "architectures field", - ID: "", + ID: "LP044", Brief: "architectures blank", Description: "Causes library to be considered incompatible with all architectures.", MessageTemplate: "Empty library.properties architectures field. Please define specific architectures or set to * if compatible with all. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -720,7 +900,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "architectures field", - ID: "", + ID: "LP045", Brief: "architecture alias", Description: "Alternative development frameworks diverged on architecture naming.", MessageTemplate: "Architecture alias(es) in library.properties architectures field: {{.}}. Please also specify the true Arduino architectures compatibilities of the library. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -735,7 +915,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "architectures field", - ID: "", + ID: "LP046", Brief: "miscased architecture", Description: "", MessageTemplate: "Incorrect case of library.properties architectures field item(s): {{.}}. Architectures are case sensitive. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -750,7 +930,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "depends field", - ID: "", + ID: "LP047", Brief: "disallowed characters", Description: "", MessageTemplate: "disallowed characters in library.properties depends field {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -765,7 +945,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "depends field", - ID: "LP012", + ID: "LP048", Brief: "Dependency not in index", Description: "", MessageTemplate: "library.properties depends field item(s) {{.}} not found in the Library Manager index.", @@ -780,7 +960,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "dot_a_linkage field", - ID: "", + ID: "LP049", Brief: "invalid value", Description: "", MessageTemplate: "invalid dot_a_linkage field value {{.}} in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -795,7 +975,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "dot_a_linkage field", - ID: "", + ID: "LP050", Brief: `"true" with "1.5" library format`, Description: `dot_a_linkage feature is only supported for the "1.5" or "recursive" library format.`, MessageTemplate: `library.properties dot_a_linkage field enabled but library is not in "1.5" format. See: https://arduino.github.io/arduino-cli/latest/library-specification/#source-code`, @@ -810,7 +990,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "includes field", - ID: "", + ID: "LP051", Brief: "includes blank", Description: `Caused the "Sketch > Include library" feature of previous IDE versions to add an empty #include directive to the sketch.`, MessageTemplate: "Empty library.properties includes field. Please either define includes or remove this optional field. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -825,7 +1005,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "includes field", - ID: "", + ID: "LP052", Brief: "includes file not in library", Description: `People often think this is the way to define their library's dependencies, which breaks the "Sketch > Include Library" feature for that library.`, MessageTemplate: "library.properties includes field item(s) {{.}} not found in library.", @@ -840,7 +1020,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "precompiled field", - ID: "", + ID: "LP053", Brief: "invalid value", Description: "", MessageTemplate: "invalid precompiled field value {{.}} in library.properties. See https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", @@ -855,7 +1035,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "precompiled field", - ID: "", + ID: "LP054", Brief: "precompiled with flat layout", Description: `precompiled feature is only supported for the "1.5" or "recursive" library format.`, MessageTemplate: `library.properties precompiled field value {{.}}, is not supported with "1.0" format. See: https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format`, @@ -870,7 +1050,7 @@ var configurations = []Type{ ProjectType: projecttype.Library, Category: "library.properties", Subcategory: "ldflags field", - ID: "", + ID: "LP055", Brief: "ldflags < min length", Description: "", MessageTemplate: "library.properties ldflags value is less than minimum length.", @@ -883,129 +1063,24 @@ var configurations = []Type{ }, { ProjectType: projecttype.Library, - Category: "library.properties", - Subcategory: "general", - ID: "", - Brief: "misspelled field", - Description: "", - MessageTemplate: "Potentially misspelled library.properties field name detected. See: https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.LibraryPropertiesMisspelledOptionalField, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "invalid", - Description: "", - MessageTemplate: "Path does not contain a valid Arduino library. See: https://arduino.github.io/arduino-cli/latest/library-specification", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: nil, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.LibraryInvalid, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "submodule", - Description: "", - MessageTemplate: `Git submodule detected. Library Manager installations and installations from GitHub's "Download ZIP" will only contain an empty folder in place of the submodule.`, - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: nil, - CheckFunction: checkfunctions.LibraryHasSubmodule, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "general", - ID: "", - Brief: "symlink", - Description: "", - MessageTemplate: "Symlink(s) found at {{.}}. These block acceptance to the Arduino Library Manager index.", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed}, - CheckFunction: checkfunctions.LibraryContainsSymlinks, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: ".development file", - Description: "", - MessageTemplate: ".development flag file found. Presence of this file blocks addition to the Library Manager index.", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed, checkmode.Strict}, - CheckFunction: checkfunctions.LibraryHasDotDevelopmentFile, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: ".exe file", - Description: "", - MessageTemplate: ".exe file(s) found: {{.}}. Presence of these files blocks inclusion in Library Manager index.", + Category: "code", + Subcategory: "miscellaneous", + ID: "LC001", + Brief: "incorrect Arduino.h case", + Description: "This causes compilation failure on filename case-sensitive OS (e.g., Linux).", + MessageTemplate: "Incorrect of Arduino.h filename case detected in #include directive: {{.}}", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.LibraryManagerSubmission, checkmode.LibraryManagerIndexed, checkmode.Strict}, - CheckFunction: checkfunctions.LibraryHasExe, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "stray sketch", - Description: "", - MessageTemplate: "Sketch(es) found outside examples and extras folders: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.LibraryHasStraySketches, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "disallowed characters in folder name", - Description: "This will be problematic for people doing manual installation of the library.", - MessageTemplate: "Prohibited characters in folder name: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.ProhibitedCharactersInLibraryFolderName, + ErrorModes: []checkmode.Type{checkmode.Strict}, + CheckFunction: checkfunctions.IncorrectArduinoDotHFileNameCase, }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "miscellaneous", + ID: "LD001", Brief: "no readme", Description: "", MessageTemplate: "No readme found. Please document your library. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-readmes", @@ -1018,9 +1093,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "miscellaneous", + ID: "LD002", Brief: "no license file", Description: "", MessageTemplate: "No license file found. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/licensing-a-repository#detecting-a-license", @@ -1031,56 +1106,26 @@ var configurations = []Type{ ErrorModes: []checkmode.Type{checkmode.Strict}, CheckFunction: checkfunctions.MissingLicenseFile, }, - { - ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "disallowed characters in file name", - Description: "", - MessageTemplate: "Prohibited characters in file name(s): {{.}}. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#sketch-root-folder", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: nil, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.ProhibitedCharactersInSketchFileName, - }, - { - ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "folder name too long", - Description: "This will be problematic for people doing manual installation of the library.", - MessageTemplate: "Folder name {{.}} exceeds maximum length. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.LibraryFolderNameGTMaxLength, - }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "incorrect src folder case", + Category: "documentation", + Subcategory: "examples", + ID: "LD003", + Brief: "stray sketch", Description: "", - MessageTemplate: "Incorrect src folder case: {{.}}. This will cause the library to not be recognized on case-sensitive operating systems. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder", + MessageTemplate: "Sketch(es) found outside examples and extras folders: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, - WarningModes: nil, + WarningModes: []checkmode.Type{checkmode.Permissive}, ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.IncorrectLibrarySrcFolderNameCase, + CheckFunction: checkfunctions.LibraryHasStraySketches, }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "examples", + ID: "LD004", Brief: "no examples", Description: "", MessageTemplate: "No example sketches found. Please provide examples. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples", @@ -1093,9 +1138,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "examples", + ID: "LD005", Brief: "incorrect examples folder name", Description: "", MessageTemplate: "Potentially misspelled examples folder name found: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples", @@ -1108,9 +1153,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Library, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "examples", + ID: "LD006", Brief: "incorrect examples folder name case", Description: "", MessageTemplate: "Incorrect examples folder name case: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples", @@ -1122,70 +1167,70 @@ var configurations = []Type{ CheckFunction: checkfunctions.IncorrectExamplesFolderNameCase, }, { - ProjectType: projecttype.Library, + ProjectType: projecttype.Sketch, Category: "structure", - Subcategory: "", - ID: "", - Brief: "incorrect extras folder name", + Subcategory: "root folder", + ID: "SS001", + Brief: "name mismatch", Description: "", - MessageTemplate: "Potentially misspelled extras folder name found: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#extra-documentation", + MessageTemplate: "Sketch file/folder name mismatch. The primary sketch file name must match the folder: {{.}}. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#primary-sketch-file", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.MisspelledExtrasFolderName, + WarningModes: []checkmode.Type{checkmode.Permissive}, + ErrorModes: []checkmode.Type{checkmode.Default}, + CheckFunction: checkfunctions.SketchNameMismatch, }, { - ProjectType: projecttype.Library, + ProjectType: projecttype.Sketch, Category: "structure", - Subcategory: "", - ID: "", - Brief: "incorrect extras folder name case", + Subcategory: "file name", + ID: "SS002", + Brief: "disallowed characters in file name", Description: "", - MessageTemplate: "Incorrect extras folder name case: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#extra-documentation", + MessageTemplate: "Prohibited characters in file name(s): {{.}}. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#sketch-root-folder", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, + WarningModes: nil, ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.IncorrectExtrasFolderNameCase, + CheckFunction: checkfunctions.ProhibitedCharactersInSketchFileName, }, { - ProjectType: projecttype.Library, + ProjectType: projecttype.Sketch, Category: "structure", - Subcategory: "", - ID: "", - Brief: "recursive with utility folder", + Subcategory: "file name", + ID: "SS003", + Brief: "file name too long", Description: "", - MessageTemplate: `Utility folder found in "1.5" format library. Compilation of this folder is only supported on "1.0" format libraries. See: https://arduino.github.io/arduino-cli/latest/library-specification/#source-code`, + MessageTemplate: "File name(s): {{.}} exceed maximum length. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#sketch-root-folder", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, + WarningModes: nil, ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.RecursiveLibraryWithUtilityFolder, + CheckFunction: checkfunctions.SketchFileNameGTMaxLength, }, { - ProjectType: projecttype.Library, - Category: "code", - Subcategory: "", - ID: "", - Brief: "incorrect Arduino.h case", - Description: "This causes compilation failure on filename case-sensitive OS (e.g., Linux).", - MessageTemplate: "Incorrect of Arduino.h filename case detected in #include directive: {{.}}", + ProjectType: projecttype.Sketch, + Category: "structure", + Subcategory: "file name", + ID: "SS004", + Brief: ".pde extension", + Description: "The .pde extension is used by both Processing sketches and Arduino sketches. Processing sketches should either be in the \"data\" subfolder of the sketch or in the \"extras\" folder of the library. Arduino sketches should use the modern .ino extension.", + MessageTemplate: "{{.}} uses deprecated .pde file extension. Use .ino for Arduino sketches.", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: []checkmode.Type{checkmode.Default}, ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.IncorrectArduinoDotHFileNameCase, + CheckFunction: checkfunctions.PdeSketchExtension, }, { ProjectType: projecttype.Sketch, Category: "structure", - Subcategory: "", - ID: "", + Subcategory: "miscellaneous", + ID: "SS005", Brief: "incorrect src folder case", Description: "", MessageTemplate: "Incorrect src folder case: {{.}}. This will cause the source files under it to not be compiled on case-sensitive operating systems. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#src-subfolder", @@ -1198,39 +1243,24 @@ var configurations = []Type{ }, { ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "file name too long", - Description: "", - MessageTemplate: "File name(s): {{.}} exceed maximum length. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#sketch-root-folder", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: nil, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.SketchFileNameGTMaxLength, - }, - { - ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "SS001", - Brief: ".pde extension", - Description: "The .pde extension is used by both Processing sketches and Arduino sketches. Processing sketches should either be in the \"data\" subfolder of the sketch or in the \"extras\" folder of the library. Arduino sketches should use the modern .ino extension.", - MessageTemplate: "{{.}} uses deprecated .pde file extension. Use .ino for Arduino sketches.", + Category: "code", + Subcategory: "miscellaneous", + ID: "SC001", + Brief: "incorrect Arduino.h case", + Description: "This causes compilation failure on filename case-sensitive OS (e.g., Linux).", + MessageTemplate: "Incorrect of Arduino.h filename case detected in #include directive: {{.}}", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: []checkmode.Type{checkmode.Default}, ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.PdeSketchExtension, + CheckFunction: checkfunctions.IncorrectArduinoDotHFileNameCase, }, { ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "miscellaneous", + ID: "SD001", Brief: "no readme", Description: "", MessageTemplate: "No readme found. Please document your sketch. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-readmes", @@ -1243,9 +1273,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "", + Category: "documentation", + Subcategory: "miscellaneous", + ID: "SD002", Brief: "no license file", Description: "", MessageTemplate: "No license file found. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/licensing-a-repository#detecting-a-license", @@ -1258,9 +1288,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Sketch, - Category: "metadata", - Subcategory: "sketch.json", - ID: "", + Category: "sketch.json", + Subcategory: "general", + ID: "SM001", Brief: "invalid sketch.json JSON format", Description: "", MessageTemplate: "sketch.json is not a valid JSON document. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#metadata", @@ -1273,9 +1303,9 @@ var configurations = []Type{ }, { ProjectType: projecttype.Sketch, - Category: "metadata", - Subcategory: "sketch.json", - ID: "", + Category: "sketch.json", + Subcategory: "general", + ID: "SM002", Brief: "invalid sketch.json data format", Description: "", MessageTemplate: "sketch.json has an invalid data format: {{.}}. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#metadata", @@ -1287,40 +1317,40 @@ var configurations = []Type{ CheckFunction: checkfunctions.SketchDotJSONFormat, }, { - ProjectType: projecttype.Sketch, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "name mismatch", + ProjectType: projecttype.Platform, + Category: "documentation", + Subcategory: "miscellaneous", + ID: "PD001", + Brief: "no readme", Description: "", - MessageTemplate: "Sketch file/folder name mismatch. The primary sketch file name must match the folder: {{.}}. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#primary-sketch-file", + MessageTemplate: "No readme found. Please document your library. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-readmes", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Permissive}, - ErrorModes: []checkmode.Type{checkmode.Default}, - CheckFunction: checkfunctions.SketchNameMismatch, + WarningModes: []checkmode.Type{checkmode.Default}, + ErrorModes: []checkmode.Type{checkmode.Strict}, + CheckFunction: checkfunctions.MissingReadme, }, { - ProjectType: projecttype.Sketch, - Category: "code", - Subcategory: "", - ID: "", - Brief: "incorrect Arduino.h case", - Description: "This causes compilation failure on filename case-sensitive OS (e.g., Linux).", - MessageTemplate: "Incorrect of Arduino.h filename case detected in #include directive: {{.}}", + ProjectType: projecttype.Platform, + Category: "documentation", + Subcategory: "miscellaneous", + ID: "PD002", + Brief: "no license file", + Description: "", + MessageTemplate: "No license file found. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/licensing-a-repository#detecting-a-license", DisableModes: nil, EnableModes: []checkmode.Type{checkmode.Default}, InfoModes: nil, WarningModes: []checkmode.Type{checkmode.Default}, ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.IncorrectArduinoDotHFileNameCase, + CheckFunction: checkfunctions.MissingLicenseFile, }, { ProjectType: projecttype.Platform, Category: "configuration files", Subcategory: "boards.txt", - ID: "", + ID: "PF001", Brief: "missing", Description: "", MessageTemplate: "Required boards.txt is missing. Expected at: {{.}}", @@ -1335,7 +1365,7 @@ var configurations = []Type{ ProjectType: projecttype.Platform, Category: "configuration files", Subcategory: "boards.txt", - ID: "", + ID: "PF002", Brief: "Invalid boards.txt", Description: "", MessageTemplate: "boards.txt has an invalid format: {{.}}", @@ -1346,41 +1376,11 @@ var configurations = []Type{ ErrorModes: []checkmode.Type{checkmode.Default}, CheckFunction: checkfunctions.BoardsTxtFormat, }, - { - ProjectType: projecttype.Platform, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "no readme", - Description: "", - MessageTemplate: "No readme found. Please document your library. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-readmes", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.MissingReadme, - }, - { - ProjectType: projecttype.Platform, - Category: "structure", - Subcategory: "", - ID: "", - Brief: "no license file", - Description: "", - MessageTemplate: "No license file found. See: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/licensing-a-repository#detecting-a-license", - DisableModes: nil, - EnableModes: []checkmode.Type{checkmode.Default}, - InfoModes: nil, - WarningModes: []checkmode.Type{checkmode.Default}, - ErrorModes: []checkmode.Type{checkmode.Strict}, - CheckFunction: checkfunctions.MissingLicenseFile, - }, { ProjectType: projecttype.Platform, Category: "code", - Subcategory: "", - ID: "", + Subcategory: "miscellaneous", + ID: "PC001", Brief: "incorrect Arduino.h case", Description: "This causes compilation failure on filename case-sensitive OS (e.g., Linux).", MessageTemplate: "Incorrect of Arduino.h filename case detected in #include directive: {{.}}", @@ -1394,8 +1394,8 @@ var configurations = []Type{ { ProjectType: projecttype.PackageIndex, Category: "data", - Subcategory: "", - ID: "", + Subcategory: "general", + ID: "ID001", Brief: "Invalid JSON format", Description: "", MessageTemplate: "Invalid JSON format.", @@ -1409,8 +1409,8 @@ var configurations = []Type{ { ProjectType: projecttype.PackageIndex, Category: "data", - Subcategory: "", - ID: "", + Subcategory: "general", + ID: "ID002", Brief: "Invalid format", Description: "", MessageTemplate: "Invalid package index format: {{.}}", diff --git a/check/checkconfigurations/checkconfigurations_test.go b/check/checkconfigurations/checkconfigurations_test.go index a39d7793..48933f72 100644 --- a/check/checkconfigurations/checkconfigurations_test.go +++ b/check/checkconfigurations/checkconfigurations_test.go @@ -23,7 +23,9 @@ import ( "github.com/arduino/arduino-lint/check/checkconfigurations" "github.com/arduino/arduino-lint/check/checklevel" "github.com/arduino/arduino-lint/configuration/checkmode" + "github.com/arduino/arduino-lint/project/projecttype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestConfigurationResolution(t *testing.T) { @@ -65,3 +67,31 @@ func checkModeConflict(configurations ...[]checkmode.Type) (bool, checkmode.Type } return false, checkmode.Default } + +func TestIncorrectCheckIDPrefix(t *testing.T) { + for checkIndex, checkConfiguration := range checkconfigurations.Configurations() { + var IDPrefix byte + switch checkConfiguration.ProjectType { + case projecttype.Sketch: + IDPrefix = 'S' + case projecttype.Library: + IDPrefix = 'L' + case projecttype.Platform: + IDPrefix = 'P' + case projecttype.PackageIndex: + IDPrefix = 'I' + default: + panic(fmt.Errorf("No prefix configured for project type %s", checkConfiguration.ProjectType)) + } + require.NotEmptyf(t, checkConfiguration.ID, "No check ID defined for check configuration #%v", checkIndex) + assert.Equalf(t, IDPrefix, checkConfiguration.ID[0], "Check ID %s has incorrect prefix for project type %s.", checkConfiguration.ID, checkConfiguration.ProjectType) + } +} + +func TestDuplicateCheckID(t *testing.T) { + checkIDMap := make(map[string]bool) + for checkIndex, checkConfiguration := range checkconfigurations.Configurations() { + checkIDMap[checkConfiguration.ID] = true + require.Equalf(t, checkIndex+1, len(checkIDMap), "ID %s of check #%v is a duplicate", checkConfiguration.ID, checkIndex) + } +} diff --git a/check/checkfunctions/checkfunctions.go b/check/checkfunctions/checkfunctions.go index 444dccb9..100259d8 100644 --- a/check/checkfunctions/checkfunctions.go +++ b/check/checkfunctions/checkfunctions.go @@ -32,43 +32,6 @@ import ( // The `output` result is the contextual information that will be inserted into the check's message template. type Type func() (result checkresult.Type, output string) -// validProjectPathBaseName checks whether the provided library folder or sketch filename contains prohibited characters. -func validProjectPathBaseName(name string) bool { - baseNameRegexp := regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$") - return baseNameRegexp.MatchString(name) -} - -func containsMisspelledPathBaseName(pathList paths.PathList, correctBaseName string, misspellingQuery string) (*paths.Path, bool) { - misspellingRegexp := regexp.MustCompile(misspellingQuery) - for _, path := range pathList { - if path.Base() == correctBaseName { - return nil, false - } - - if misspellingRegexp.MatchString(path.Base()) { - return path, true - } - } - - return nil, false -} - -func containsIncorrectPathBaseCase(pathList paths.PathList, correctBaseName string) (*paths.Path, bool) { - for _, path := range pathList { - if path.Base() == correctBaseName { - // There was a case-sensitive match (paths package's Exist() is not always case-sensitive, so can't be used here). - return nil, false - } - - if strings.EqualFold(path.Base(), correctBaseName) { - // There was a case-insensitive match. - return path, true - } - } - - return nil, false -} - // MissingReadme checks if the project has a readme that will be recognized by GitHub. func MissingReadme() (result checkresult.Type, output string) { if checkdata.ProjectType() != checkdata.SuperProjectType() { @@ -138,6 +101,43 @@ func IncorrectArduinoDotHFileNameCase() (result checkresult.Type, output string) return checkresult.Pass, "" } +// validProjectPathBaseName checks whether the provided library folder or sketch filename contains prohibited characters. +func validProjectPathBaseName(name string) bool { + baseNameRegexp := regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$") + return baseNameRegexp.MatchString(name) +} + +func containsMisspelledPathBaseName(pathList paths.PathList, correctBaseName string, misspellingQuery string) (*paths.Path, bool) { + misspellingRegexp := regexp.MustCompile(misspellingQuery) + for _, path := range pathList { + if path.Base() == correctBaseName { + return nil, false + } + + if misspellingRegexp.MatchString(path.Base()) { + return path, true + } + } + + return nil, false +} + +func containsIncorrectPathBaseCase(pathList paths.PathList, correctBaseName string) (*paths.Path, bool) { + for _, path := range pathList { + if path.Base() == correctBaseName { + // There was a case-sensitive match (paths package's Exist() is not always case-sensitive, so can't be used here). + return nil, false + } + + if strings.EqualFold(path.Base(), correctBaseName) { + // There was a case-insensitive match. + return path, true + } + } + + return nil, false +} + // pathContainsRegexpMatch checks if the provided path contains a file name matching the given regular expression. func pathContainsRegexpMatch(path *paths.Path, pathRegexp *regexp.Regexp) bool { listing, err := path.ReadDir() diff --git a/check/checkfunctions/library.go b/check/checkfunctions/library.go index 2c69fae6..987fd386 100644 --- a/check/checkfunctions/library.go +++ b/check/checkfunctions/library.go @@ -39,14 +39,199 @@ import ( semver "go.bug.st/relaxed-semver" ) -// LibraryPropertiesFormat checks for invalid library.properties format. -func LibraryPropertiesFormat() (result checkresult.Type, output string) { - if checkdata.LoadedLibrary() != nil && checkdata.LoadedLibrary().IsLegacy { - return checkresult.Skip, "Library has no library.properties" +// LibraryInvalid checks whether the provided path is a valid library. +func LibraryInvalid() (result checkresult.Type, output string) { + if checkdata.LoadedLibrary() != nil && library.ContainsHeaderFile(checkdata.LoadedLibrary().SourceDir) { + return checkresult.Pass, "" + } + + return checkresult.Fail, "" +} + +// LibraryFolderNameGTMaxLength checks if the library folder name exceeds the maximum length. +func LibraryFolderNameGTMaxLength() (result checkresult.Type, output string) { + if len(checkdata.ProjectPath().Base()) > 63 { + return checkresult.Fail, checkdata.ProjectPath().Base() + } + + return checkresult.Pass, "" +} + +// ProhibitedCharactersInLibraryFolderName checks for prohibited characters in the library folder name. +func ProhibitedCharactersInLibraryFolderName() (result checkresult.Type, output string) { + if !validProjectPathBaseName(checkdata.ProjectPath().Base()) { + return checkresult.Fail, checkdata.ProjectPath().Base() + } + + return checkresult.Pass, "" +} + +// LibraryHasSubmodule checks whether the library contains a Git submodule. +func LibraryHasSubmodule() (result checkresult.Type, output string) { + dotGitmodulesPath := checkdata.ProjectPath().Join(".gitmodules") + hasDotGitmodules, err := dotGitmodulesPath.ExistCheck() + if err != nil { + panic(err) } + if hasDotGitmodules && dotGitmodulesPath.IsNotDir() { + return checkresult.Fail, "" + } + + return checkresult.Pass, "" +} + +// LibraryContainsSymlinks checks if the library folder contains symbolic links. +func LibraryContainsSymlinks() (result checkresult.Type, output string) { + projectPathListing, err := checkdata.ProjectPath().ReadDirRecursive() + if err != nil { + panic(err) + } + projectPathListing.FilterOutDirs() + + symlinkPaths := []string{} + for _, projectPathItem := range projectPathListing { + projectPathItemStat, err := os.Lstat(projectPathItem.String()) + if err != nil { + panic(err) + } + + if projectPathItemStat.Mode()&os.ModeSymlink != 0 { + symlinkPaths = append(symlinkPaths, projectPathItem.String()) + } + } + + if len(symlinkPaths) > 0 { + return checkresult.Fail, strings.Join(symlinkPaths, ", ") + } + + return checkresult.Pass, "" +} + +// LibraryHasDotDevelopmentFile checks whether the library contains a .development flag file. +func LibraryHasDotDevelopmentFile() (result checkresult.Type, output string) { + dotDevelopmentPath := checkdata.ProjectPath().Join(".development") + hasDotDevelopment, err := dotDevelopmentPath.ExistCheck() + if err != nil { + panic(err) + } + + if hasDotDevelopment && dotDevelopmentPath.IsNotDir() { + return checkresult.Fail, "" + } + + return checkresult.Pass, "" +} + +// LibraryHasExe checks whether the library contains files with .exe extension. +func LibraryHasExe() (result checkresult.Type, output string) { + projectPathListing, err := checkdata.ProjectPath().ReadDirRecursive() + if err != nil { + panic(err) + } + projectPathListing.FilterOutDirs() + + exePaths := []string{} + for _, projectPathItem := range projectPathListing { + if projectPathItem.Ext() == ".exe" { + exePaths = append(exePaths, projectPathItem.String()) + } + } + + if len(exePaths) > 0 { + return checkresult.Fail, strings.Join(exePaths, ", ") + } + + return checkresult.Pass, "" +} + +// LibraryPropertiesNameFieldHeaderMismatch checks whether the filename of one of the library's header files matches the Library Manager installation folder name. +func LibraryPropertiesNameFieldHeaderMismatch() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { - return checkresult.Fail, checkdata.LibraryPropertiesLoadError().Error() + return checkresult.NotRun, "Couldn't load library.properties" + } + + name, ok := checkdata.LibraryProperties().GetOk("name") + if !ok { + return checkresult.NotRun, "Field not present" + } + + sanitizedName := utils.SanitizeName(name) + for _, header := range checkdata.SourceHeaders() { + if strings.TrimSuffix(header, filepath.Ext(header)) == sanitizedName { + return checkresult.Pass, "" + } + } + + return checkresult.Fail, sanitizedName + ".h" +} + +// IncorrectLibrarySrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries. +func IncorrectLibrarySrcFolderNameCase() (result checkresult.Type, output string) { + if library.ContainsMetadataFile(checkdata.ProjectPath()) && library.ContainsHeaderFile(checkdata.ProjectPath()) { + // Flat layout, so no special treatment of src subfolder. + return checkresult.Skip, "Not applicable due to layout type" + } + + // The library is intended to have the recursive layout. + directoryListing, err := checkdata.ProjectPath().ReadDir() + if err != nil { + panic(err) + } + directoryListing.FilterDirs() + + path, found := containsIncorrectPathBaseCase(directoryListing, "src") + if found { + return checkresult.Fail, path.String() + } + + return checkresult.Pass, "" +} + +// RecursiveLibraryWithUtilityFolder checks for presence of a `utility` subfolder in a recursive layout library. +func RecursiveLibraryWithUtilityFolder() (result checkresult.Type, output string) { + if checkdata.LoadedLibrary() == nil { + return checkresult.NotRun, "Library not loaded" + } + + if checkdata.LoadedLibrary().Layout == libraries.FlatLayout { + return checkresult.Skip, "Not applicable due to layout type" + } + + if checkdata.ProjectPath().Join("utility").Exist() { + return checkresult.Fail, "" + } + + return checkresult.Pass, "" +} + +// MisspelledExtrasFolderName checks for incorrectly spelled `extras` folder name. +func MisspelledExtrasFolderName() (result checkresult.Type, output string) { + directoryListing, err := checkdata.ProjectPath().ReadDir() + if err != nil { + panic(err) + } + directoryListing.FilterDirs() + + path, found := containsMisspelledPathBaseName(directoryListing, "extras", "(?i)^extra$") + if found { + return checkresult.Fail, path.String() + } + + return checkresult.Pass, "" +} + +// IncorrectExtrasFolderNameCase checks for incorrect `extras` folder name case. +func IncorrectExtrasFolderNameCase() (result checkresult.Type, output string) { + directoryListing, err := checkdata.ProjectPath().ReadDir() + if err != nil { + panic(err) + } + directoryListing.FilterDirs() + + path, found := containsIncorrectPathBaseCase(directoryListing, "extras") + if found { + return checkresult.Fail, path.String() } return checkresult.Pass, "" @@ -107,6 +292,19 @@ func RedundantLibraryProperties() (result checkresult.Type, output string) { return checkresult.Pass, "" } +// LibraryPropertiesFormat checks for invalid library.properties format. +func LibraryPropertiesFormat() (result checkresult.Type, output string) { + if checkdata.LoadedLibrary() != nil && checkdata.LoadedLibrary().IsLegacy { + return checkresult.Skip, "Library has no library.properties" + } + + if checkdata.LibraryPropertiesLoadError() != nil { + return checkresult.Fail, checkdata.LibraryPropertiesLoadError().Error() + } + + return checkresult.Pass, "" +} + // LibraryPropertiesNameFieldMissing checks for missing library.properties "name" field. func LibraryPropertiesNameFieldMissing() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { @@ -194,8 +392,8 @@ func LibraryPropertiesNameFieldDisallowedCharacters() (result checkresult.Type, return checkresult.Pass, "" } -// LibraryPropertiesNameFieldHasSpaces checks if the library.properties "name" value contains spaces. -func LibraryPropertiesNameFieldHasSpaces() (result checkresult.Type, output string) { +// LibraryPropertiesNameFieldStartsWithArduino checks if the library.properties "name" value starts with "Arduino". +func LibraryPropertiesNameFieldStartsWithArduino() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { return checkresult.NotRun, "Couldn't load library.properties" } @@ -205,15 +403,15 @@ func LibraryPropertiesNameFieldHasSpaces() (result checkresult.Type, output stri return checkresult.NotRun, "Field not present" } - if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notContainsSpaces", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Strict]) { + if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notStartsWithArduino", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Specification]) { return checkresult.Fail, name } return checkresult.Pass, "" } -// LibraryPropertiesNameFieldStartsWithArduino checks if the library.properties "name" value starts with "Arduino". -func LibraryPropertiesNameFieldStartsWithArduino() (result checkresult.Type, output string) { +// LibraryPropertiesNameFieldMissingOfficialPrefix checks whether the library.properties `name` value uses the prefix required of all new official Arduino libraries. +func LibraryPropertiesNameFieldMissingOfficialPrefix() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { return checkresult.NotRun, "Couldn't load library.properties" } @@ -223,15 +421,14 @@ func LibraryPropertiesNameFieldStartsWithArduino() (result checkresult.Type, out return checkresult.NotRun, "Field not present" } - if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notStartsWithArduino", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Specification]) { - return checkresult.Fail, name + if strings.HasPrefix(name, "Arduino_") { + return checkresult.Pass, "" } - - return checkresult.Pass, "" + return checkresult.Fail, name } -// LibraryPropertiesNameFieldMissingOfficialPrefix checks whether the library.properties `name` value uses the prefix required of all new official Arduino libraries. -func LibraryPropertiesNameFieldMissingOfficialPrefix() (result checkresult.Type, output string) { +// LibraryPropertiesNameFieldContainsArduino checks if the library.properties "name" value contains "Arduino". +func LibraryPropertiesNameFieldContainsArduino() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { return checkresult.NotRun, "Couldn't load library.properties" } @@ -241,14 +438,15 @@ func LibraryPropertiesNameFieldMissingOfficialPrefix() (result checkresult.Type, return checkresult.NotRun, "Field not present" } - if strings.HasPrefix(name, "Arduino_") { - return checkresult.Pass, "" + if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notContainsArduino", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Strict]) { + return checkresult.Fail, name } - return checkresult.Fail, name + + return checkresult.Pass, "" } -// LibraryPropertiesNameFieldContainsArduino checks if the library.properties "name" value contains "Arduino". -func LibraryPropertiesNameFieldContainsArduino() (result checkresult.Type, output string) { +// LibraryPropertiesNameFieldHasSpaces checks if the library.properties "name" value contains spaces. +func LibraryPropertiesNameFieldHasSpaces() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { return checkresult.NotRun, "Couldn't load library.properties" } @@ -258,7 +456,7 @@ func LibraryPropertiesNameFieldContainsArduino() (result checkresult.Type, outpu return checkresult.NotRun, "Field not present" } - if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notContainsArduino", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Strict]) { + if schema.ValidationErrorMatch("^#/name$", "/patternObjects/notContainsSpaces", "", "", checkdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Strict]) { return checkresult.Fail, name } @@ -319,27 +517,6 @@ func LibraryPropertiesNameFieldNotInIndex() (result checkresult.Type, output str return checkresult.Fail, name } -// LibraryPropertiesNameFieldHeaderMismatch checks whether the filename of one of the library's header files matches the Library Manager installation folder name. -func LibraryPropertiesNameFieldHeaderMismatch() (result checkresult.Type, output string) { - if checkdata.LibraryPropertiesLoadError() != nil { - return checkresult.NotRun, "Couldn't load library.properties" - } - - name, ok := checkdata.LibraryProperties().GetOk("name") - if !ok { - return checkresult.NotRun, "Field not present" - } - - sanitizedName := utils.SanitizeName(name) - for _, header := range checkdata.SourceHeaders() { - if strings.TrimSuffix(header, filepath.Ext(header)) == sanitizedName { - return checkresult.Pass, "" - } - } - - return checkresult.Fail, sanitizedName + ".h" -} - // LibraryPropertiesVersionFieldMissing checks for missing library.properties "version" field. func LibraryPropertiesVersionFieldMissing() (result checkresult.Type, output string) { if checkdata.LibraryPropertiesLoadError() != nil { @@ -1171,94 +1348,6 @@ func LibraryPropertiesMisspelledOptionalField() (result checkresult.Type, output return checkresult.Pass, "" } -// LibraryInvalid checks whether the provided path is a valid library. -func LibraryInvalid() (result checkresult.Type, output string) { - if checkdata.LoadedLibrary() != nil && library.ContainsHeaderFile(checkdata.LoadedLibrary().SourceDir) { - return checkresult.Pass, "" - } - - return checkresult.Fail, "" -} - -// LibraryHasSubmodule checks whether the library contains a Git submodule. -func LibraryHasSubmodule() (result checkresult.Type, output string) { - dotGitmodulesPath := checkdata.ProjectPath().Join(".gitmodules") - hasDotGitmodules, err := dotGitmodulesPath.ExistCheck() - if err != nil { - panic(err) - } - - if hasDotGitmodules && dotGitmodulesPath.IsNotDir() { - return checkresult.Fail, "" - } - - return checkresult.Pass, "" -} - -// LibraryContainsSymlinks checks if the library folder contains symbolic links. -func LibraryContainsSymlinks() (result checkresult.Type, output string) { - projectPathListing, err := checkdata.ProjectPath().ReadDirRecursive() - if err != nil { - panic(err) - } - projectPathListing.FilterOutDirs() - - symlinkPaths := []string{} - for _, projectPathItem := range projectPathListing { - projectPathItemStat, err := os.Lstat(projectPathItem.String()) - if err != nil { - panic(err) - } - - if projectPathItemStat.Mode()&os.ModeSymlink != 0 { - symlinkPaths = append(symlinkPaths, projectPathItem.String()) - } - } - - if len(symlinkPaths) > 0 { - return checkresult.Fail, strings.Join(symlinkPaths, ", ") - } - - return checkresult.Pass, "" -} - -// LibraryHasDotDevelopmentFile checks whether the library contains a .development flag file. -func LibraryHasDotDevelopmentFile() (result checkresult.Type, output string) { - dotDevelopmentPath := checkdata.ProjectPath().Join(".development") - hasDotDevelopment, err := dotDevelopmentPath.ExistCheck() - if err != nil { - panic(err) - } - - if hasDotDevelopment && dotDevelopmentPath.IsNotDir() { - return checkresult.Fail, "" - } - - return checkresult.Pass, "" -} - -// LibraryHasExe checks whether the library contains files with .exe extension. -func LibraryHasExe() (result checkresult.Type, output string) { - projectPathListing, err := checkdata.ProjectPath().ReadDirRecursive() - if err != nil { - panic(err) - } - projectPathListing.FilterOutDirs() - - exePaths := []string{} - for _, projectPathItem := range projectPathListing { - if projectPathItem.Ext() == ".exe" { - exePaths = append(exePaths, projectPathItem.String()) - } - } - - if len(exePaths) > 0 { - return checkresult.Fail, strings.Join(exePaths, ", ") - } - - return checkresult.Pass, "" -} - // LibraryHasStraySketches checks for sketches outside the `examples` and `extras` folders. func LibraryHasStraySketches() (result checkresult.Type, output string) { straySketchPaths := []string{} @@ -1298,46 +1387,6 @@ func LibraryHasStraySketches() (result checkresult.Type, output string) { return checkresult.Pass, "" } -// ProhibitedCharactersInLibraryFolderName checks for prohibited characters in the library folder name. -func ProhibitedCharactersInLibraryFolderName() (result checkresult.Type, output string) { - if !validProjectPathBaseName(checkdata.ProjectPath().Base()) { - return checkresult.Fail, checkdata.ProjectPath().Base() - } - - return checkresult.Pass, "" -} - -// LibraryFolderNameGTMaxLength checks if the library folder name exceeds the maximum length. -func LibraryFolderNameGTMaxLength() (result checkresult.Type, output string) { - if len(checkdata.ProjectPath().Base()) > 63 { - return checkresult.Fail, checkdata.ProjectPath().Base() - } - - return checkresult.Pass, "" -} - -// IncorrectLibrarySrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries. -func IncorrectLibrarySrcFolderNameCase() (result checkresult.Type, output string) { - if library.ContainsMetadataFile(checkdata.ProjectPath()) && library.ContainsHeaderFile(checkdata.ProjectPath()) { - // Flat layout, so no special treatment of src subfolder. - return checkresult.Skip, "Not applicable due to layout type" - } - - // The library is intended to have the recursive layout. - directoryListing, err := checkdata.ProjectPath().ReadDir() - if err != nil { - panic(err) - } - directoryListing.FilterDirs() - - path, found := containsIncorrectPathBaseCase(directoryListing, "src") - if found { - return checkresult.Fail, path.String() - } - - return checkresult.Pass, "" -} - // MissingExamples checks whether the library is missing examples. func MissingExamples() (result checkresult.Type, output string) { for _, examplesFolderName := range library.ExamplesFolderSupportedNames() { @@ -1392,37 +1441,17 @@ func IncorrectExamplesFolderNameCase() (result checkresult.Type, output string) return checkresult.Pass, "" } -// MisspelledExtrasFolderName checks for incorrectly spelled `extras` folder name. -func MisspelledExtrasFolderName() (result checkresult.Type, output string) { - directoryListing, err := checkdata.ProjectPath().ReadDir() - if err != nil { - panic(err) - } - directoryListing.FilterDirs() - - path, found := containsMisspelledPathBaseName(directoryListing, "extras", "(?i)^extra$") - if found { - return checkresult.Fail, path.String() - } - - return checkresult.Pass, "" -} - -// RecursiveLibraryWithUtilityFolder checks for presence of a `utility` subfolder in a recursive layout library. -func RecursiveLibraryWithUtilityFolder() (result checkresult.Type, output string) { - if checkdata.LoadedLibrary() == nil { - return checkresult.NotRun, "Library not loaded" - } - - if checkdata.LoadedLibrary().Layout == libraries.FlatLayout { - return checkresult.Skip, "Not applicable due to layout type" - } - - if checkdata.ProjectPath().Join("utility").Exist() { - return checkresult.Fail, "" +// nameInLibraryManagerIndex returns whether there is a library in Library Manager index using the given name. +func nameInLibraryManagerIndex(name string) bool { + libraries := checkdata.LibraryManagerIndex()["libraries"].([]interface{}) + for _, libraryInterface := range libraries { + library := libraryInterface.(map[string]interface{}) + if library["name"].(string) == name { + return true + } } - return checkresult.Pass, "" + return false } // spellCheckLibraryPropertiesFieldValue returns the value of the provided library.properties field with commonly misspelled words corrected. @@ -1444,35 +1473,6 @@ func spellCheckLibraryPropertiesFieldValue(fieldName string) (result checkresult return checkresult.Pass, "" } -// IncorrectExtrasFolderNameCase checks for incorrect `extras` folder name case. -func IncorrectExtrasFolderNameCase() (result checkresult.Type, output string) { - directoryListing, err := checkdata.ProjectPath().ReadDir() - if err != nil { - panic(err) - } - directoryListing.FilterDirs() - - path, found := containsIncorrectPathBaseCase(directoryListing, "extras") - if found { - return checkresult.Fail, path.String() - } - - return checkresult.Pass, "" -} - -// nameInLibraryManagerIndex returns whether there is a library in Library Manager index using the given name. -func nameInLibraryManagerIndex(name string) bool { - libraries := checkdata.LibraryManagerIndex()["libraries"].([]interface{}) - for _, libraryInterface := range libraries { - library := libraryInterface.(map[string]interface{}) - if library["name"].(string) == name { - return true - } - } - - return false -} - // commaSeparatedToList returns the list equivalent of a comma-separated string. func commaSeparatedToList(commaSeparated string) []string { list := []string{} diff --git a/check/checkfunctions/library_test.go b/check/checkfunctions/library_test.go index 9b65be3e..5974516e 100644 --- a/check/checkfunctions/library_test.go +++ b/check/checkfunctions/library_test.go @@ -64,22 +64,135 @@ func checkLibraryCheckFunction(checkFunction Type, testTables []libraryCheckFunc } } -func TestMisspelledLibraryPropertiesFileName(t *testing.T) { +func TestLibraryInvalid(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ - {"Incorrect", "MisspelledLibraryProperties", checkresult.Fail, ""}, - {"Correct", "Recursive", checkresult.Pass, ""}, + {"Invalid library.properties", "InvalidLibraryProperties", checkresult.Fail, ""}, + {"Invalid flat layout", "FlatWithoutHeader", checkresult.Fail, ""}, + {"Invalid recursive layout", "RecursiveWithoutLibraryProperties", checkresult.Fail, ""}, + {"Valid library", "Recursive", checkresult.Pass, ""}, } - checkLibraryCheckFunction(MisspelledLibraryPropertiesFileName, testTables, t) + checkLibraryCheckFunction(LibraryInvalid, testTables, t) } -func TestIncorrectLibraryPropertiesFileNameCase(t *testing.T) { +func TestLibraryFolderNameGTMaxLength(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ - {"Incorrect", "IncorrectLibraryPropertiesCase", checkresult.Fail, ""}, - {"Correct", "Recursive", checkresult.Pass, ""}, + {"Has folder name > max length", "FolderNameTooLong12345678901234567890123456789012345678901234567890", checkresult.Fail, "^FolderNameTooLong12345678901234567890123456789012345678901234567890$"}, + {"Folder name <= max length", "Recursive", checkresult.Pass, ""}, } - checkLibraryCheckFunction(IncorrectLibraryPropertiesFileNameCase, testTables, t) + checkLibraryCheckFunction(LibraryFolderNameGTMaxLength, testTables, t) +} + +func TestProhibitedCharactersInLibraryFolderName(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Has prohibited characters", "Prohibited CharactersInFolderName", checkresult.Fail, ""}, + {"No prohibited characters", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(ProhibitedCharactersInLibraryFolderName, testTables, t) +} + +func TestLibraryHasSubmodule(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Has submodule", "Submodule", checkresult.Fail, ""}, + {"No submodule", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryHasSubmodule, testTables, t) +} + +func TestLibraryContainsSymlinks(t *testing.T) { + testLibrary := "Recursive" + symlinkPath := librariesTestDataPath.Join(testLibrary, "test-symlink") + // It's probably most friendly to developers using Windows to create the symlink needed for the test on demand. + err := os.Symlink(librariesTestDataPath.Join(testLibrary, "library.properties").String(), symlinkPath.String()) + require.Nil(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.") + defer symlinkPath.RemoveAll() // clean up + + testTables := []libraryCheckFunctionTestTable{ + {"Has symlink", testLibrary, checkresult.Fail, ""}, + } + + checkLibraryCheckFunction(LibraryContainsSymlinks, testTables, t) + + err = symlinkPath.RemoveAll() + require.Nil(t, err) + + testTables = []libraryCheckFunctionTestTable{ + {"No symlink", testLibrary, checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryContainsSymlinks, testTables, t) +} + +func TestLibraryHasDotDevelopmentFile(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Has .development file", "DotDevelopment", checkresult.Fail, ""}, + {"No .development file", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryHasDotDevelopmentFile, testTables, t) +} + +func TestLibraryHasExe(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Has .exe file", "Exe", checkresult.Fail, ""}, + {"No .exe files", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryHasExe, testTables, t) +} + +func TestLibraryPropertiesNameFieldHeaderMismatch(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, + {"Mismatch", "NameHeaderMismatch", checkresult.Fail, "^NameHeaderMismatch.h$"}, + {"Match", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryPropertiesNameFieldHeaderMismatch, testTables, t) +} + +func TestIncorrectLibrarySrcFolderNameCase(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Flat, not precompiled", "Flat", checkresult.Skip, ""}, + {"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""}, + {"Correct case", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(IncorrectLibrarySrcFolderNameCase, testTables, t) +} + +func TestRecursiveLibraryWithUtilityFolder(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, + {"Flat", "Flat", checkresult.Skip, ""}, + {"Recursive with utility", "RecursiveWithUtilityFolder", checkresult.Fail, ""}, + {"Recursive without utility", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(RecursiveLibraryWithUtilityFolder, testTables, t) +} + +func TestMisspelledExtrasFolderName(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Correctly spelled", "ExtrasFolder", checkresult.Pass, ""}, + {"Misspelled", "MisspelledExtrasFolder", checkresult.Fail, ""}, + {"No extras folder", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(MisspelledExtrasFolderName, testTables, t) +} + +func TestIncorrectExtrasFolderNameCase(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Correct case", "ExtrasFolder", checkresult.Pass, ""}, + {"Incorrect case", "IncorrectExtrasFolderCase", checkresult.Fail, ""}, + {"No extras folder", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(IncorrectExtrasFolderNameCase, testTables, t) } func TestLibraryPropertiesMissing(t *testing.T) { @@ -93,6 +206,24 @@ func TestLibraryPropertiesMissing(t *testing.T) { checkLibraryCheckFunction(LibraryPropertiesMissing, testTables, t) } +func TestMisspelledLibraryPropertiesFileName(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Incorrect", "MisspelledLibraryProperties", checkresult.Fail, ""}, + {"Correct", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(MisspelledLibraryPropertiesFileName, testTables, t) +} + +func TestIncorrectLibraryPropertiesFileNameCase(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Incorrect", "IncorrectLibraryPropertiesCase", checkresult.Fail, ""}, + {"Correct", "Recursive", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(IncorrectLibraryPropertiesFileNameCase, testTables, t) +} + func TestRedundantLibraryProperties(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ {"Redundant", "RedundantLibraryProperties", checkresult.Fail, ""}, @@ -143,16 +274,6 @@ func TestLibraryPropertiesNameFieldNotInIndex(t *testing.T) { checkLibraryCheckFunction(LibraryPropertiesNameFieldNotInIndex, testTables, t) } -func TestLibraryPropertiesNameFieldHeaderMismatch(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, - {"Mismatch", "NameHeaderMismatch", checkresult.Fail, "^NameHeaderMismatch.h$"}, - {"Match", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryPropertiesNameFieldHeaderMismatch, testTables, t) -} - func TestLibraryPropertiesVersionFieldBehindTag(t *testing.T) { // Set up the test repository folders. TagPrereleaseGreaterPath := librariesTestDataPath.Join("TagPrereleaseGreater") @@ -257,6 +378,17 @@ func TestLibraryPropertiesVersionFieldBehindTag(t *testing.T) { checkLibraryCheckFunction(LibraryPropertiesVersionFieldBehindTag, testTables, t) } +func TestLibraryPropertiesEmailFieldAsMaintainerAlias(t *testing.T) { + testTables := []libraryCheckFunctionTestTable{ + {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, + {"No email field", "MissingFields", checkresult.Skip, ""}, + {"email in place of maintainer", "EmailOnly", checkresult.Fail, ""}, + {"email and maintainer", "EmailAndMaintainer", checkresult.Pass, ""}, + } + + checkLibraryCheckFunction(LibraryPropertiesEmailFieldAsMaintainerAlias, testTables, t) +} + func TestLibraryPropertiesSentenceFieldSpellCheck(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, @@ -281,17 +413,6 @@ func TestLibraryPropertiesParagraphFieldSpellCheck(t *testing.T) { checkLibraryCheckFunction(LibraryPropertiesParagraphFieldSpellCheck, testTables, t) } -func TestLibraryPropertiesEmailFieldAsMaintainerAlias(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, - {"No email field", "MissingFields", checkresult.Skip, ""}, - {"email in place of maintainer", "EmailOnly", checkresult.Fail, ""}, - {"email and maintainer", "EmailAndMaintainer", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryPropertiesEmailFieldAsMaintainerAlias, testTables, t) -} - func TestLibraryPropertiesParagraphFieldRepeatsSentence(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, @@ -396,68 +517,6 @@ func TestLibraryPropertiesPrecompiledFieldEnabledWithFlatLayout(t *testing.T) { checkLibraryCheckFunction(LibraryPropertiesPrecompiledFieldEnabledWithFlatLayout, testTables, t) } -func TestLibraryInvalid(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Invalid library.properties", "InvalidLibraryProperties", checkresult.Fail, ""}, - {"Invalid flat layout", "FlatWithoutHeader", checkresult.Fail, ""}, - {"Invalid recursive layout", "RecursiveWithoutLibraryProperties", checkresult.Fail, ""}, - {"Valid library", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryInvalid, testTables, t) -} - -func TestLibraryHasSubmodule(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Has submodule", "Submodule", checkresult.Fail, ""}, - {"No submodule", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryHasSubmodule, testTables, t) -} - -func TestLibraryContainsSymlinks(t *testing.T) { - testLibrary := "Recursive" - symlinkPath := librariesTestDataPath.Join(testLibrary, "test-symlink") - // It's probably most friendly to developers using Windows to create the symlink needed for the test on demand. - err := os.Symlink(librariesTestDataPath.Join(testLibrary, "library.properties").String(), symlinkPath.String()) - require.Nil(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.") - defer symlinkPath.RemoveAll() // clean up - - testTables := []libraryCheckFunctionTestTable{ - {"Has symlink", testLibrary, checkresult.Fail, ""}, - } - - checkLibraryCheckFunction(LibraryContainsSymlinks, testTables, t) - - err = symlinkPath.RemoveAll() - require.Nil(t, err) - - testTables = []libraryCheckFunctionTestTable{ - {"No symlink", testLibrary, checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryContainsSymlinks, testTables, t) -} - -func TestLibraryHasDotDevelopmentFile(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Has .development file", "DotDevelopment", checkresult.Fail, ""}, - {"No .development file", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryHasDotDevelopmentFile, testTables, t) -} - -func TestLibraryHasExe(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Has .exe file", "Exe", checkresult.Fail, ""}, - {"No .exe files", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryHasExe, testTables, t) -} - func TestLibraryHasStraySketches(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ {"Sketch in root", "SketchInRoot", checkresult.Fail, ""}, @@ -469,34 +528,6 @@ func TestLibraryHasStraySketches(t *testing.T) { checkLibraryCheckFunction(LibraryHasStraySketches, testTables, t) } -func TestProhibitedCharactersInLibraryFolderName(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Has prohibited characters", "Prohibited CharactersInFolderName", checkresult.Fail, ""}, - {"No prohibited characters", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(ProhibitedCharactersInLibraryFolderName, testTables, t) -} - -func TestLibraryFolderNameGTMaxLength(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Has folder name > max length", "FolderNameTooLong12345678901234567890123456789012345678901234567890", checkresult.Fail, "^FolderNameTooLong12345678901234567890123456789012345678901234567890$"}, - {"Folder name <= max length", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(LibraryFolderNameGTMaxLength, testTables, t) -} - -func TestIncorrectLibrarySrcFolderNameCase(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Flat, not precompiled", "Flat", checkresult.Skip, ""}, - {"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""}, - {"Correct case", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(IncorrectLibrarySrcFolderNameCase, testTables, t) -} - func TestMissingExamples(t *testing.T) { testTables := []libraryCheckFunctionTestTable{ {"Has examples", "ExamplesFolder", checkresult.Pass, ""}, @@ -526,34 +557,3 @@ func TestIncorrectExamplesFolderNameCase(t *testing.T) { checkLibraryCheckFunction(IncorrectExamplesFolderNameCase, testTables, t) } - -func TestMisspelledExtrasFolderName(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Correctly spelled", "ExtrasFolder", checkresult.Pass, ""}, - {"Misspelled", "MisspelledExtrasFolder", checkresult.Fail, ""}, - {"No extras folder", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(MisspelledExtrasFolderName, testTables, t) -} - -func TestIncorrectExtrasFolderNameCase(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Correct case", "ExtrasFolder", checkresult.Pass, ""}, - {"Incorrect case", "IncorrectExtrasFolderCase", checkresult.Fail, ""}, - {"No extras folder", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(IncorrectExtrasFolderNameCase, testTables, t) -} - -func TestRecursiveLibraryWithUtilityFolder(t *testing.T) { - testTables := []libraryCheckFunctionTestTable{ - {"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""}, - {"Flat", "Flat", checkresult.Skip, ""}, - {"Recursive with utility", "RecursiveWithUtilityFolder", checkresult.Fail, ""}, - {"Recursive without utility", "Recursive", checkresult.Pass, ""}, - } - - checkLibraryCheckFunction(RecursiveLibraryWithUtilityFolder, testTables, t) -} diff --git a/check/checkfunctions/sketch.go b/check/checkfunctions/sketch.go index 66c6b36f..20851c60 100644 --- a/check/checkfunctions/sketch.go +++ b/check/checkfunctions/sketch.go @@ -26,20 +26,21 @@ import ( "github.com/arduino/arduino-lint/project/sketch" ) -// IncorrectSketchSrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries. -func IncorrectSketchSrcFolderNameCase() (result checkresult.Type, output string) { - directoryListing, err := checkdata.ProjectPath().ReadDir() - if err != nil { - panic(err) - } - directoryListing.FilterDirs() +// SketchNameMismatch checks for mismatch between sketch folder name and primary file name. +func SketchNameMismatch() (result checkresult.Type, output string) { + for extension := range globals.MainFileValidExtensions { + validPrimarySketchFilePath := checkdata.ProjectPath().Join(checkdata.ProjectPath().Base() + extension) + exist, err := validPrimarySketchFilePath.ExistCheck() + if err != nil { + panic(err) + } - path, found := containsIncorrectPathBaseCase(directoryListing, "src") - if found { - return checkresult.Fail, path.String() + if exist { + return checkresult.Pass, "" + } } - return checkresult.Pass, "" + return checkresult.Fail, checkdata.ProjectPath().Base() + ".ino" } // ProhibitedCharactersInSketchFileName checks for prohibited characters in the sketch file names. @@ -102,6 +103,22 @@ func PdeSketchExtension() (result checkresult.Type, output string) { return checkresult.Pass, "" } +// IncorrectSketchSrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries. +func IncorrectSketchSrcFolderNameCase() (result checkresult.Type, output string) { + directoryListing, err := checkdata.ProjectPath().ReadDir() + if err != nil { + panic(err) + } + directoryListing.FilterDirs() + + path, found := containsIncorrectPathBaseCase(directoryListing, "src") + if found { + return checkresult.Fail, path.String() + } + + return checkresult.Pass, "" +} + // SketchDotJSONJSONFormat checks whether the sketch.json metadata file is a valid JSON document. func SketchDotJSONJSONFormat() (result checkresult.Type, output string) { metadataPath := sketch.MetadataPath(checkdata.ProjectPath()) @@ -129,20 +146,3 @@ func SketchDotJSONFormat() (result checkresult.Type, output string) { return checkresult.Fail, checkdata.MetadataLoadError().Error() } - -// SketchNameMismatch checks for mismatch between sketch folder name and primary file name. -func SketchNameMismatch() (result checkresult.Type, output string) { - for extension := range globals.MainFileValidExtensions { - validPrimarySketchFilePath := checkdata.ProjectPath().Join(checkdata.ProjectPath().Base() + extension) - exist, err := validPrimarySketchFilePath.ExistCheck() - if err != nil { - panic(err) - } - - if exist { - return checkresult.Pass, "" - } - } - - return checkresult.Fail, checkdata.ProjectPath().Base() + ".ino" -} diff --git a/check/checkfunctions/sketch_test.go b/check/checkfunctions/sketch_test.go index 4fa2d537..66b6b260 100644 --- a/check/checkfunctions/sketch_test.go +++ b/check/checkfunctions/sketch_test.go @@ -60,13 +60,13 @@ func checkSketchCheckFunction(checkFunction Type, testTables []sketchCheckFuncti } } -func TestIncorrectSketchSrcFolderNameCase(t *testing.T) { +func TestSketchNameMismatch(t *testing.T) { testTables := []sketchCheckFunctionTestTable{ - {"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""}, - {"Correct case", "Valid", checkresult.Pass, ""}, + {"Valid", "Valid", checkresult.Pass, ""}, + {"Mismatch", "NameMismatch", checkresult.Fail, ""}, } - checkSketchCheckFunction(IncorrectSketchSrcFolderNameCase, testTables, t) + checkSketchCheckFunction(SketchNameMismatch, testTables, t) } func TestProhibitedCharactersInSketchFileName(t *testing.T) { @@ -96,6 +96,15 @@ func TestPdeSketchExtension(t *testing.T) { checkSketchCheckFunction(PdeSketchExtension, testTables, t) } +func TestIncorrectSketchSrcFolderNameCase(t *testing.T) { + testTables := []sketchCheckFunctionTestTable{ + {"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""}, + {"Correct case", "Valid", checkresult.Pass, ""}, + } + + checkSketchCheckFunction(IncorrectSketchSrcFolderNameCase, testTables, t) +} + func TestSketchDotJSONJSONFormat(t *testing.T) { testTables := []sketchCheckFunctionTestTable{ {"No metadata file", "NoMetadataFile", checkresult.Skip, ""}, @@ -116,12 +125,3 @@ func TestSketchDotJSONFormat(t *testing.T) { checkSketchCheckFunction(SketchDotJSONFormat, testTables, t) } - -func TestSketchNameMismatch(t *testing.T) { - testTables := []sketchCheckFunctionTestTable{ - {"Valid", "Valid", checkresult.Pass, ""}, - {"Mismatch", "NameMismatch", checkresult.Fail, ""}, - } - - checkSketchCheckFunction(SketchNameMismatch, testTables, t) -}