Skip to content

Commit b5ee35d

Browse files
committed
Add check for includes missing from library
1 parent 0824294 commit b5ee35d

File tree

6 files changed

+90
-0
lines changed

6 files changed

+90
-0
lines changed

check/checkconfigurations/checkconfigurations.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,21 @@ var configurations = []Type{
701701
ErrorModes: []checkmode.Type{checkmode.Default},
702702
CheckFunction: checkfunctions.LibraryPropertiesIncludesFieldLTMinLength,
703703
},
704+
{
705+
ProjectType: projecttype.Library,
706+
Category: "library.properties",
707+
Subcategory: "includes field",
708+
ID: "",
709+
Brief: "includes file not in library",
710+
Description: `People often think this is the way to define their library's dependencies, which breaks the "Sketch > Include Library" feature for that library.`,
711+
MessageTemplate: "library.properties includes field item(s) {{.}} not found in library.",
712+
DisableModes: nil,
713+
EnableModes: []checkmode.Type{checkmode.All},
714+
InfoModes: nil,
715+
WarningModes: []checkmode.Type{checkmode.Permissive},
716+
ErrorModes: []checkmode.Type{checkmode.Default},
717+
CheckFunction: checkfunctions.LibraryPropertiesIncludesFieldItemNotFound,
718+
},
704719
{
705720
ProjectType: projecttype.Library,
706721
Category: "library.properties",

check/checkdata/library.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ func InitializeForLibrary(project project.Type, schemasPath *paths.Path) {
5050
if err != nil {
5151
logrus.Errorf("Error loading library from %s: %s", project.Path, err)
5252
loadedLibrary = nil
53+
sourceHeaders = nil
54+
} else {
55+
sourceHeaders, err = loadedLibrary.SourceHeaders()
56+
if err != nil {
57+
panic(err)
58+
}
5359
}
5460

5561
if libraryManagerIndex == nil { // Only download the Library Manager index once
@@ -106,6 +112,13 @@ func LoadedLibrary() *libraries.Library {
106112
return loadedLibrary
107113
}
108114

115+
var sourceHeaders []string
116+
117+
// SourceHeaders returns the list of library source header filenames discovered by Arduino CLI.
118+
func SourceHeaders() []string {
119+
return sourceHeaders
120+
}
121+
109122
var libraryManagerIndex map[string]interface{}
110123

111124
// LibraryManagerIndex returns the Library Manager index data.

check/checkfunctions/library.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,47 @@ func LibraryPropertiesIncludesFieldLTMinLength() (result checkresult.Type, outpu
723723
return checkresult.Pass, ""
724724
}
725725

726+
// LibraryPropertiesIncludesFieldItemNotFound checks whether the header files specified in the library.properties `includes` field are in the library.
727+
func LibraryPropertiesIncludesFieldItemNotFound() (result checkresult.Type, output string) {
728+
if checkdata.LibraryPropertiesLoadError() != nil {
729+
return checkresult.NotRun, ""
730+
}
731+
732+
includes, ok := checkdata.LibraryProperties().GetOk("includes")
733+
if !ok {
734+
return checkresult.NotRun, ""
735+
}
736+
737+
includesList, err := properties.SplitQuotedString(includes, "", false)
738+
if err != nil {
739+
panic(err)
740+
}
741+
742+
findInclude := func(include string) bool {
743+
for _, header := range checkdata.SourceHeaders() {
744+
logrus.Tracef("Comparing include %s with header file %s", include, header)
745+
if include == header {
746+
logrus.Tracef("match!")
747+
return true
748+
}
749+
}
750+
return false
751+
}
752+
753+
includesNotInLibrary := []string{}
754+
for _, include := range includesList {
755+
if !findInclude(include) {
756+
includesNotInLibrary = append(includesNotInLibrary, include)
757+
}
758+
}
759+
760+
if len(includesNotInLibrary) > 0 {
761+
return checkresult.Fail, strings.Join(includesNotInLibrary, ", ")
762+
}
763+
764+
return checkresult.Pass, ""
765+
}
766+
726767
// LibraryPropertiesPrecompiledFieldInvalid checks for invalid value in the library.properties "precompiled" field.
727768
func LibraryPropertiesPrecompiledFieldInvalid() (result checkresult.Type, output string) {
728769
if checkdata.LibraryPropertiesLoadError() != nil {

check/checkfunctions/library_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ func TestLibraryPropertiesDotALinkageFieldTrueWithFlatLayout(t *testing.T) {
158158
checkCheckFunction(LibraryPropertiesDotALinkageFieldTrueWithFlatLayout, testTables, t)
159159
}
160160

161+
func TestLibraryPropertiesIncludesFieldItemNotFound(t *testing.T) {
162+
testTables := []checkFunctionTestTable{
163+
{"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""},
164+
{"Not defined", "MissingFields", checkresult.NotRun, ""},
165+
{"Missing includes", "MissingIncludes", checkresult.Fail, "^Nonexistent.h$"},
166+
{"Present includes", "Recursive", checkresult.Pass, ""},
167+
}
168+
169+
checkCheckFunction(LibraryPropertiesIncludesFieldItemNotFound, testTables, t)
170+
}
171+
161172
func TestLibraryPropertiesPrecompiledFieldEnabledWithFlatLayout(t *testing.T) {
162173
testTables := []checkFunctionTestTable{
163174
{"Unable to load", "InvalidLibraryProperties", checkresult.NotRun, ""},
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name=MissingIncludes
2+
version=1.0.0
3+
author=Cristian Maglie <[email protected]>, Pippo Pluto <[email protected]>
4+
maintainer=Cristian Maglie <[email protected]>
5+
sentence=A library that makes coding a web server a breeze.
6+
paragraph=Supports HTTP1.1 and you can do GET and POST.
7+
category=Communication
8+
url=http://example.com/
9+
architectures=avr
10+
includes=Nonexistent.h

check/checkfunctions/testdata/libraries/MissingIncludes/src/MissingIncludes.h

Whitespace-only changes.

0 commit comments

Comments
 (0)