Skip to content

Commit 41bd2e4

Browse files
authored
[skip-changelog] legacy: Arduino preprocess subroutine refactorization (part 2) (#2191)
* Movec ctags-related structs in ctags package * Unified GCCPreprocRunner* functions There is no need to duplicate a function that basically does the same thing. * Added implementation of functional algorithms (until they are available in the golang standard library...) * legacy: use generic algos where possibile * Removed useless call to FilterSketchSource * Converted AddPrototypes into a function
1 parent ca60d4b commit 41bd2e4

24 files changed

+239
-198
lines changed

Diff for: internal/algorithms/slices.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2023 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package f
17+
18+
// Matcher is a function that tests if a given value match a certain criteria.
19+
type Matcher[T any] func(T) bool
20+
21+
// Reducer is a function that combines two values of the same type and return
22+
// the combined value.
23+
type Reducer[T any] func(T, T) T
24+
25+
// Mapper is a function that converts a value of one type to another type.
26+
type Mapper[T, U any] func(T) U
27+
28+
// Filter takes a slice of type []T and a Matcher[T]. It returns a newly
29+
// allocated slice containing only those elements of the input slice that
30+
// satisfy the matcher.
31+
func Filter[T any](values []T, matcher Matcher[T]) []T {
32+
res := []T{}
33+
for _, x := range values {
34+
if matcher(x) {
35+
res = append(res, x)
36+
}
37+
}
38+
return res
39+
}
40+
41+
// Map applies the Mapper function to each element of the slice and returns
42+
// a new slice with the results in the same order.
43+
func Map[T, U any](values []T, mapper Mapper[T, U]) []U {
44+
res := []U{}
45+
for _, x := range values {
46+
res = append(res, mapper(x))
47+
}
48+
return res
49+
}
50+
51+
// Reduce applies the Reducer function to all elements of the input values
52+
// and returns the result.
53+
func Reduce[T any](values []T, reducer Reducer[T]) T {
54+
var result T
55+
for _, v := range values {
56+
result = reducer(result, v)
57+
}
58+
return result
59+
}
60+
61+
// Equals return a Matcher that matches the given value
62+
func Equals[T comparable](value T) Matcher[T] {
63+
return func(x T) bool {
64+
return x == value
65+
}
66+
}
67+
68+
// NotEquals return a Matcher that does not match the given value
69+
func NotEquals[T comparable](value T) Matcher[T] {
70+
return func(x T) bool {
71+
return x != value
72+
}
73+
}

Diff for: internal/algorithms/slices_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2023 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package f_test
17+
18+
import (
19+
"strings"
20+
"testing"
21+
22+
f "github.com/arduino/arduino-cli/internal/algorithms"
23+
"github.com/stretchr/testify/require"
24+
)
25+
26+
func TestFilter(t *testing.T) {
27+
a := []string{"aaa", "bbb", "ccc"}
28+
require.Equal(t, []string{"bbb", "ccc"}, f.Filter(a, func(x string) bool { return x > "b" }))
29+
b := []int{5, 9, 15, 2, 4, -2}
30+
require.Equal(t, []int{5, 9, 15}, f.Filter(b, func(x int) bool { return x > 4 }))
31+
}
32+
33+
func TestIsEmpty(t *testing.T) {
34+
require.True(t, f.Equals(int(0))(0))
35+
require.False(t, f.Equals(int(1))(0))
36+
require.True(t, f.Equals("")(""))
37+
require.False(t, f.Equals("abc")(""))
38+
require.False(t, f.NotEquals(int(0))(0))
39+
require.True(t, f.NotEquals(int(1))(0))
40+
require.False(t, f.NotEquals("")(""))
41+
require.True(t, f.NotEquals("abc")(""))
42+
}
43+
44+
func TestMap(t *testing.T) {
45+
value := "hello, world , how are,you? "
46+
parts := f.Map(strings.Split(value, ","), strings.TrimSpace)
47+
48+
require.Equal(t, 4, len(parts))
49+
require.Equal(t, "hello", parts[0])
50+
require.Equal(t, "world", parts[1])
51+
require.Equal(t, "how are", parts[2])
52+
require.Equal(t, "you?", parts[3])
53+
}

Diff for: legacy/builder/add_additional_entries_to_context.go

-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ func (*AddAdditionalEntriesToContext) Run(ctx *types.Context) error {
5353
ctx.WarningsLevel = DEFAULT_WARNINGS_LEVEL
5454
}
5555

56-
ctx.CollectedSourceFiles = &types.UniqueSourceFileQueue{}
57-
5856
ctx.LibrariesResolutionResults = map[string]types.LibraryResolutionResult{}
5957

6058
return nil

Diff for: legacy/builder/builder_utils/utils.go

+5-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/arduino/arduino-cli/arduino/globals"
2828
"github.com/arduino/arduino-cli/i18n"
29+
f "github.com/arduino/arduino-cli/internal/algorithms"
2930
"github.com/arduino/arduino-cli/legacy/builder/constants"
3031
"github.com/arduino/arduino-cli/legacy/builder/types"
3132
"github.com/arduino/arduino-cli/legacy/builder/utils"
@@ -262,10 +263,10 @@ func ObjFileIsUpToDate(sourceFile, objectFile, dependencyFile *paths.Path) (bool
262263
return false, errors.WithStack(err)
263264
}
264265

265-
rows = utils.Map(rows, removeEndingBackSlash)
266-
rows = utils.Map(rows, strings.TrimSpace)
267-
rows = utils.Map(rows, unescapeDep)
268-
rows = utils.Filter(rows, nonEmptyString)
266+
rows = f.Map(rows, removeEndingBackSlash)
267+
rows = f.Map(rows, strings.TrimSpace)
268+
rows = f.Map(rows, unescapeDep)
269+
rows = f.Filter(rows, f.NotEquals(""))
269270

270271
if len(rows) == 0 {
271272
return true, nil
@@ -327,10 +328,6 @@ func removeEndingBackSlash(s string) string {
327328
return strings.TrimSuffix(s, "\\")
328329
}
329330

330-
func nonEmptyString(s string) bool {
331-
return s != constants.EMPTY_STRING
332-
}
333-
334331
func CoreOrReferencedCoreHasChanged(corePath, targetCorePath, targetFile *paths.Path) bool {
335332

336333
targetFileStat, err := targetFile.Stat()

Diff for: legacy/builder/container_add_prototypes.go

+6-12
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ func PreprocessSketchWithCtags(ctx *types.Context) error {
3939

4040
// Run preprocessor
4141
sourceFile := ctx.SketchBuildPath.Join(ctx.Sketch.MainFile.Base() + ".cpp")
42-
if err := GCCPreprocRunner(ctx, sourceFile, targetFilePath, ctx.IncludeFolders); err != nil {
42+
stderr, err := GCCPreprocRunner(ctx, sourceFile, targetFilePath, ctx.IncludeFolders)
43+
ctx.WriteStderr(stderr)
44+
if err != nil {
4345
if !ctx.OnlyUpdateCompilationDatabase {
4446
return errors.WithStack(err)
4547
}
@@ -60,18 +62,10 @@ func PreprocessSketchWithCtags(ctx *types.Context) error {
6062
ctx.SketchSourceAfterCppPreprocessing = filterSketchSource(ctx.Sketch, bytes.NewReader(src), false)
6163
}
6264

63-
commands := []types.Command{
64-
&CTagsRunner{Source: &ctx.SketchSourceAfterCppPreprocessing, TargetFileName: "sketch_merged.cpp"},
65-
&PrototypesAdder{},
66-
}
67-
68-
for _, command := range commands {
69-
PrintRingNameIfDebug(ctx, command)
70-
err := command.Run(ctx)
71-
if err != nil {
72-
return errors.WithStack(err)
73-
}
65+
if err := (&CTagsRunner{Source: &ctx.SketchSourceAfterCppPreprocessing, TargetFileName: "sketch_merged.cpp"}).Run(ctx); err != nil {
66+
return errors.WithStack(err)
7467
}
68+
ctx.SketchSourceAfterArduinoPreprocessing, ctx.PrototypesSection = PrototypesAdder(ctx.SketchSourceMerged, ctx.PrototypesLineWhereToInsert, ctx.LineOffset, ctx.Prototypes, ctx.DebugPreprocessor)
7569

7670
if err := bldr.SketchSaveItemCpp(ctx.Sketch.MainFile, []byte(ctx.SketchSourceAfterArduinoPreprocessing), ctx.SketchBuildPath); err != nil {
7771
return errors.WithStack(err)

Diff for: legacy/builder/container_find_includes.go

+14-12
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,24 @@ func (s *ContainerFindIncludes) findIncludes(ctx *types.Context) error {
143143
appendIncludeFolder(ctx, cache, nil, "", ctx.BuildProperties.GetPath("build.variant.path"))
144144
}
145145

146+
sourceFileQueue := &types.UniqueSourceFileQueue{}
147+
146148
if !ctx.UseCachedLibrariesResolution {
147149
sketch := ctx.Sketch
148150
mergedfile, err := types.MakeSourceFile(ctx, sketch, paths.New(sketch.MainFile.Base()+".cpp"))
149151
if err != nil {
150152
return errors.WithStack(err)
151153
}
152-
ctx.CollectedSourceFiles.Push(mergedfile)
154+
sourceFileQueue.Push(mergedfile)
153155

154-
sourceFilePaths := ctx.CollectedSourceFiles
155-
queueSourceFilesFromFolder(ctx, sourceFilePaths, sketch, ctx.SketchBuildPath, false /* recurse */)
156+
queueSourceFilesFromFolder(ctx, sourceFileQueue, sketch, ctx.SketchBuildPath, false /* recurse */)
156157
srcSubfolderPath := ctx.SketchBuildPath.Join("src")
157158
if srcSubfolderPath.IsDir() {
158-
queueSourceFilesFromFolder(ctx, sourceFilePaths, sketch, srcSubfolderPath, true /* recurse */)
159+
queueSourceFilesFromFolder(ctx, sourceFileQueue, sketch, srcSubfolderPath, true /* recurse */)
159160
}
160161

161-
for !sourceFilePaths.Empty() {
162-
err := findIncludesUntilDone(ctx, cache, sourceFilePaths.Pop())
162+
for !sourceFileQueue.Empty() {
163+
err := findIncludesUntilDone(ctx, cache, sourceFileQueue)
163164
if err != nil {
164165
cachePath.Remove()
165166
return errors.WithStack(err)
@@ -314,7 +315,8 @@ func writeCache(cache *includeCache, path *paths.Path) error {
314315
return nil
315316
}
316317

317-
func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile types.SourceFile) error {
318+
func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFileQueue *types.UniqueSourceFileQueue) error {
319+
sourceFile := sourceFileQueue.Pop()
318320
sourcePath := sourceFile.SourcePath(ctx)
319321
targetFilePath := paths.NullPath()
320322
depPath := sourceFile.DepfilePath(ctx)
@@ -367,7 +369,7 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile t
367369
ctx.Info(tr("Using cached library dependencies for file: %[1]s", sourcePath))
368370
}
369371
} else {
370-
preproc_stderr, preproc_err = GCCPreprocRunnerForDiscoveringIncludes(ctx, sourcePath, targetFilePath, includes)
372+
preproc_stderr, preproc_err = GCCPreprocRunner(ctx, sourcePath, targetFilePath, includes)
371373
// Unwrap error and see if it is an ExitError.
372374
_, is_exit_error := errors.Cause(preproc_err).(*exec.ExitError)
373375
if preproc_err == nil {
@@ -399,7 +401,7 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile t
399401
// return errors.WithStack(err)
400402
if preproc_err == nil || preproc_stderr == nil {
401403
// Filename came from cache, so run preprocessor to obtain error to show
402-
preproc_stderr, preproc_err = GCCPreprocRunnerForDiscoveringIncludes(ctx, sourcePath, targetFilePath, includes)
404+
preproc_stderr, preproc_err = GCCPreprocRunner(ctx, sourcePath, targetFilePath, includes)
403405
if preproc_err == nil {
404406
// If there is a missing #include in the cache, but running
405407
// gcc does not reproduce that, there is something wrong.
@@ -419,13 +421,13 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile t
419421
appendIncludeFolder(ctx, cache, sourcePath, include, library.SourceDir)
420422
sourceDirs := library.SourceDirs()
421423
for _, sourceDir := range sourceDirs {
422-
queueSourceFilesFromFolder(ctx, ctx.CollectedSourceFiles, library, sourceDir.Dir, sourceDir.Recurse)
424+
queueSourceFilesFromFolder(ctx, sourceFileQueue, library, sourceDir.Dir, sourceDir.Recurse)
423425
}
424426
first = false
425427
}
426428
}
427429

428-
func queueSourceFilesFromFolder(ctx *types.Context, queue *types.UniqueSourceFileQueue, origin interface{}, folder *paths.Path, recurse bool) error {
430+
func queueSourceFilesFromFolder(ctx *types.Context, sourceFileQueue *types.UniqueSourceFileQueue, origin interface{}, folder *paths.Path, recurse bool) error {
429431
sourceFileExtensions := []string{}
430432
for k := range globals.SourceFilesValidExtensions {
431433
sourceFileExtensions = append(sourceFileExtensions, k)
@@ -440,7 +442,7 @@ func queueSourceFilesFromFolder(ctx *types.Context, queue *types.UniqueSourceFil
440442
if err != nil {
441443
return errors.WithStack(err)
442444
}
443-
queue.Push(sourceFile)
445+
sourceFileQueue.Push(sourceFile)
444446
}
445447

446448
return nil

Diff for: legacy/builder/create_cmake_rule.go

-3
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
119119
return err
120120
}
121121

122-
// Use old ctags method to generate export file
123-
ctx.SketchSourceMerged = filterSketchSource(ctx.Sketch, strings.NewReader(ctx.SketchSourceMerged), true)
124-
125122
err = utils.CopyDir(ctx.SketchBuildPath.String(), cmakeFolder.Join("sketch").String(), validExportExtensions)
126123
if err != nil {
127124
fmt.Println(err)

Diff for: legacy/builder/ctags/ctags_has_issues.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ import (
1919
"bufio"
2020
"os"
2121
"strings"
22-
23-
"github.com/arduino/arduino-cli/legacy/builder/types"
2422
)
2523

2624
func (p *CTagsParser) FixCLinkageTagsDeclarations() {
@@ -42,7 +40,7 @@ func sliceContainsInt(s []int, e int) bool {
4240
return false
4341
}
4442

45-
func (p *CTagsParser) prototypeAndCodeDontMatch(tag *types.CTag) bool {
43+
func (p *CTagsParser) prototypeAndCodeDontMatch(tag *CTag) bool {
4644
if tag.SkipMe {
4745
return true
4846
}
@@ -107,7 +105,7 @@ func (p *CTagsParser) prototypeAndCodeDontMatch(tag *types.CTag) bool {
107105
return ret == -1
108106
}
109107

110-
func findTemplateMultiline(tag *types.CTag) string {
108+
func findTemplateMultiline(tag *CTag) string {
111109
code, _ := getFunctionProtoUntilTemplateToken(tag, tag.Code)
112110
return removeEverythingAfterClosingRoundBracket(code)
113111
}
@@ -117,7 +115,7 @@ func removeEverythingAfterClosingRoundBracket(s string) string {
117115
return s[0 : n+1]
118116
}
119117

120-
func getFunctionProtoUntilTemplateToken(tag *types.CTag, code string) (string, int) {
118+
func getFunctionProtoUntilTemplateToken(tag *CTag, code string) (string, int) {
121119

122120
/* FIXME I'm ugly */
123121
line := 0
@@ -150,7 +148,7 @@ func getFunctionProtoUntilTemplateToken(tag *types.CTag, code string) (string, i
150148
return code, line
151149
}
152150

153-
func getFunctionProtoWithNPreviousCharacters(tag *types.CTag, code string, n int) (string, int) {
151+
func getFunctionProtoWithNPreviousCharacters(tag *CTag, code string, n int) (string, int) {
154152

155153
/* FIXME I'm ugly */
156154
expectedPrototypeLen := len(code) + n
@@ -216,7 +214,7 @@ func removeComments(text string, multilinecomment bool) (string, bool) {
216214
/* This function scans the source files searching for "extern C" context
217215
* It save the line numbers in a map filename -> {lines...}
218216
*/
219-
func (p *CTagsParser) FindCLinkageLines(tags []*types.CTag) map[string][]int {
217+
func (p *CTagsParser) FindCLinkageLines(tags []*CTag) map[string][]int {
220218

221219
lines := make(map[string][]int)
222220

0 commit comments

Comments
 (0)