From 9ef0caa84a084d97576cb489b620fff231ac3b15 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 9 Mar 2021 14:36:32 -0800 Subject: [PATCH 1/2] Always discover subprojects The documentation of the `--project-type` flag promises that subprojects will also be discovered: ``` --project-type string Only lint projects of the specified type and their subprojects. Can be {sketch|library|platform|all}. (default "all") ``` Under a specific combination of configurations a bug caused subprojects to not be discovered: - `--project-type` flag set to specific project type. - `--recursive` flag not used. - `PROJECT_PATH` is a folder (rather than file). So, for example, given this project structure: FooLibrary |-- examples | `-- FooExample | `-- FooExample.ino |-- src | `-- FooLibrary.h `-- library.properties The following command only linted the library, and not the FooExample sketch: ``` arduino-lint --project-type library FooLibrary ``` Under any other configuration, subprojects were discovered and the FooExample sketch would be linted in the above example. --- internal/project/project.go | 15 ++-- internal/project/project_test.go | 144 ++++++++++++++++++------------- 2 files changed, 95 insertions(+), 64 deletions(-) diff --git a/internal/project/project.go b/internal/project/project.go index 735b647e..9a2a4db2 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -92,16 +92,13 @@ func findProjects(targetPath *paths.Path) ([]Type, error) { return nil, fmt.Errorf("Specified path %s is not an Arduino project", targetPath) } + var foundParentProjects []Type if configuration.SuperprojectTypeFilter() == projecttype.All || configuration.Recursive() { // Project discovery and/or type detection is required. - foundParentProjects := findProjectsUnderPath(targetPath, configuration.SuperprojectTypeFilter(), configuration.Recursive()) - for _, foundParentProject := range foundParentProjects { - foundProjects = append(foundProjects, foundParentProject) - foundProjects = append(foundProjects, findSubprojects(foundParentProject, foundParentProject.ProjectType)...) - } + foundParentProjects = findProjectsUnderPath(targetPath, configuration.SuperprojectTypeFilter(), configuration.Recursive()) } else { // Project was explicitly defined by user. - foundProjects = append(foundProjects, + foundParentProjects = append(foundParentProjects, Type{ Path: targetPath, ProjectType: configuration.SuperprojectTypeFilter(), @@ -110,6 +107,12 @@ func findProjects(targetPath *paths.Path) ([]Type, error) { ) } + // Discover subprojects of all found projects. + for _, foundParentProject := range foundParentProjects { + foundProjects = append(foundProjects, foundParentProject) + foundProjects = append(foundProjects, findSubprojects(foundParentProject, foundParentProject.ProjectType)...) + } + if foundProjects == nil { return nil, fmt.Errorf("No projects found under %s", targetPath) } diff --git a/internal/project/project_test.go b/internal/project/project_test.go index 3070f7f0..825e7ade 100644 --- a/internal/project/project_test.go +++ b/internal/project/project_test.go @@ -16,6 +16,7 @@ package project import ( + "fmt" "os" "reflect" "testing" @@ -53,16 +54,16 @@ func TestFindProjects(t *testing.T) { testTables := []struct { testName string - superprojectTypeFilter string - recursive string + superprojectTypeFilter []string + recursive []string projectPaths []string errorAssertion assert.ErrorAssertionFunc expectedProjects []Type }{ { "Sketch file", - "all", - "", + []string{"all", "sketch"}, + []string{"true", "false"}, []string{sketchPath.Join("Sketch.ino").String()}, assert.NoError, []Type{ @@ -75,8 +76,8 @@ func TestFindProjects(t *testing.T) { }, { "Library file", - "all", - "", + []string{"all", "library"}, + []string{"true", "false"}, []string{libraryPath.Join("Library.h").String()}, assert.NoError, []Type{ @@ -94,8 +95,8 @@ func TestFindProjects(t *testing.T) { }, { "Platform file", - "all", - "", + []string{"all", "platform"}, + []string{"true", "false"}, []string{platformPath.Join("boards.txt").String()}, assert.NoError, []Type{ @@ -118,8 +119,8 @@ func TestFindProjects(t *testing.T) { }, { "Package index file", - "all", - "", + []string{"all", "package-index"}, + []string{"true", "false"}, []string{packageIndexFilePath.String()}, assert.NoError, []Type{ @@ -132,8 +133,8 @@ func TestFindProjects(t *testing.T) { }, { "Explicit file", - "sketch", - "", + []string{"sketch"}, + []string{"true", "false"}, []string{libraryPath.Join("Library.h").String()}, assert.NoError, []Type{ @@ -146,8 +147,8 @@ func TestFindProjects(t *testing.T) { }, { "Sketch folder", - "all", - "", + []string{"all", "sketch"}, + []string{"true", "false"}, []string{sketchPath.String()}, assert.NoError, []Type{ @@ -160,8 +161,8 @@ func TestFindProjects(t *testing.T) { }, { "Library folder", - "all", - "", + []string{"all", "library"}, + []string{"true", "false"}, []string{libraryPath.String()}, assert.NoError, []Type{ @@ -179,8 +180,8 @@ func TestFindProjects(t *testing.T) { }, { "Platform folder", - "all", - "", + []string{"all", "platform"}, + []string{"true", "false"}, []string{platformPath.String()}, assert.NoError, []Type{ @@ -203,8 +204,8 @@ func TestFindProjects(t *testing.T) { }, { "Package index folder", - "all", - "", + []string{"all", "package-index"}, + []string{"true", "false"}, []string{packageIndexFolderPath.String()}, assert.NoError, []Type{ @@ -217,8 +218,8 @@ func TestFindProjects(t *testing.T) { }, { "Explicit folder", - "sketch", - "false", + []string{"sketch"}, + []string{"false"}, []string{libraryPath.String()}, assert.NoError, []Type{ @@ -230,9 +231,23 @@ func TestFindProjects(t *testing.T) { }, }, { - "Projects folder, recursive", - "all", - "true", + "Explicit folder", + []string{"sketch"}, + []string{"true"}, + []string{libraryPath.String()}, + assert.NoError, + []Type{ + { + Path: libraryExamplePath, + ProjectType: projecttype.Sketch, + SuperprojectType: projecttype.Sketch, + }, + }, + }, + { + "Projects folder", + []string{"all"}, + []string{"true"}, []string{projectsPath.String()}, assert.NoError, []Type{ @@ -253,18 +268,37 @@ func TestFindProjects(t *testing.T) { }, }, }, + { + "Projects folder", + []string{"sketch"}, + []string{"true"}, + []string{projectsPath.String()}, + assert.NoError, + []Type{ + { + Path: projectsPathLibraryExample, + ProjectType: projecttype.Sketch, + SuperprojectType: projecttype.Sketch, + }, + { + Path: projectsPathSketch, + ProjectType: projecttype.Sketch, + SuperprojectType: projecttype.Sketch, + }, + }, + }, { "Projects folder, non-recursive", - "all", - "false", + []string{"all"}, + []string{"false"}, []string{projectsPath.String()}, assert.Error, []Type{}, }, { "Multiple target folders", - "all", - "true", + []string{"all"}, + []string{"true"}, []string{projectsPath.String(), sketchPath.String()}, assert.NoError, []Type{ @@ -290,38 +324,32 @@ func TestFindProjects(t *testing.T) { }, }, }, - { - "superproject type filter", - "sketch", - "true", - []string{projectsPath.String()}, - assert.NoError, - []Type{ - { - Path: projectsPathLibraryExample, - ProjectType: projecttype.Sketch, - SuperprojectType: projecttype.Sketch, - }, - { - Path: projectsPathSketch, - ProjectType: projecttype.Sketch, - SuperprojectType: projecttype.Sketch, - }, - }, - }, } for _, testTable := range testTables { - flags := test.ConfigurationFlags() - flags.Set("project-type", testTable.superprojectTypeFilter) - if testTable.recursive != "" { - flags.Set("recursive", testTable.recursive) - } - configuration.Initialize(flags, testTable.projectPaths) - foundProjects, err := FindProjects() - testTable.errorAssertion(t, err) - if err == nil { - assert.True(t, reflect.DeepEqual(foundProjects, testTable.expectedProjects), testTable.testName) + for _, superprojectTypeFilter := range testTable.superprojectTypeFilter { + for _, recursive := range testTable.recursive { + flags := test.ConfigurationFlags() + flags.Set("project-type", superprojectTypeFilter) + if recursive != "" { + flags.Set("recursive", recursive) + } + configuration.Initialize(flags, testTable.projectPaths) + foundProjects, err := FindProjects() + testTable.errorAssertion(t, err) + if err == nil { + assert.True( + t, + reflect.DeepEqual(foundProjects, testTable.expectedProjects), + fmt.Sprintf( + "%s (%s project-type=%s recursive=%s)", + testTable.testName, + testTable.projectPaths, + superprojectTypeFilter, recursive, + ), + ) + } + } } } } From 8e5f33a55f976df8f894c41cfef13c4116344d73 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 9 Mar 2021 14:56:18 -0800 Subject: [PATCH 2/2] Refactor subproject discovery code Subproject discovery must be done under any circumstances. Previously, there was duplicate code to do this for both file project paths and folder project paths, resulting in the code being more difficult to maintain. In order to accomodate this change, the error message in the event of no projects being discovered was reworded to be applicable to either project path type. --- internal/project/project.go | 40 ++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/internal/project/project.go b/internal/project/project.go index 9a2a4db2..2d88a52d 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -53,7 +53,7 @@ func FindProjects() ([]Type, error) { // findProjects handles the recursion for FindProjects(). func findProjects(targetPath *paths.Path) ([]Type, error) { - var foundProjects []Type + var foundParentProjects []Type // If targetPath is a file, targetPath itself is the project, so it's only necessary to determine/verify the type. if targetPath.IsNotDir() { @@ -82,39 +82,33 @@ func findProjects(targetPath *paths.Path) ([]Type, error) { ProjectType: projectType, SuperprojectType: projectType, } - foundProjects = append(foundProjects, foundProject) - - foundProjects = append(foundProjects, findSubprojects(foundProject, projectType)...) - - return foundProjects, nil + foundParentProjects = append(foundParentProjects, foundProject) } - - return nil, fmt.Errorf("Specified path %s is not an Arduino project", targetPath) - } - - var foundParentProjects []Type - if configuration.SuperprojectTypeFilter() == projecttype.All || configuration.Recursive() { - // Project discovery and/or type detection is required. - foundParentProjects = findProjectsUnderPath(targetPath, configuration.SuperprojectTypeFilter(), configuration.Recursive()) } else { - // Project was explicitly defined by user. - foundParentProjects = append(foundParentProjects, - Type{ - Path: targetPath, - ProjectType: configuration.SuperprojectTypeFilter(), - SuperprojectType: configuration.SuperprojectTypeFilter(), - }, - ) + if configuration.SuperprojectTypeFilter() == projecttype.All || configuration.Recursive() { + // Project discovery and/or type detection is required. + foundParentProjects = findProjectsUnderPath(targetPath, configuration.SuperprojectTypeFilter(), configuration.Recursive()) + } else { + // Project was explicitly defined by user. + foundParentProjects = append(foundParentProjects, + Type{ + Path: targetPath, + ProjectType: configuration.SuperprojectTypeFilter(), + SuperprojectType: configuration.SuperprojectTypeFilter(), + }, + ) + } } // Discover subprojects of all found projects. + var foundProjects []Type for _, foundParentProject := range foundParentProjects { foundProjects = append(foundProjects, foundParentProject) foundProjects = append(foundProjects, findSubprojects(foundParentProject, foundParentProject.ProjectType)...) } if foundProjects == nil { - return nil, fmt.Errorf("No projects found under %s", targetPath) + return nil, fmt.Errorf("No projects found with project path %s", targetPath) } return foundProjects, nil