Skip to content

Commit 9ce2904

Browse files
authored
[skip-changelog] legacy: Arduino preprocess subroutine refactorization (part 3) (arduino#2193)
* Converted CTagsRunner into a function * Removed useless tasks from ctags_runner test * Simplified ctags_runner test * Removed some ctags related fields from builder context The last piece in RunCTags: parser := &ctags.CTagsParser{} parser.Parse(ctagsStdout, sketch.MainFile) parser.FixCLinkageTagsDeclarations() prototypes, line := parser.GeneratePrototypes() if line != -1 { prototypesLineWhereToInsert = line } has been moved at the beginning of PrototypesAdder. RunCTags now returns the output of ctags instead of `prototypes` and `line`. This also allows to remove the context variables that keeps those information. * Simplified RunCTags / factored test subroutine * Removed DebugPreprocessor from builder ctx * Added executils.RunAndCaptureOutput * Moved RunCTags out of legacy package
1 parent 74dd907 commit 9ce2904

File tree

9 files changed

+151
-229
lines changed

9 files changed

+151
-229
lines changed

arduino/builder/preprocessor/ctags.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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 preprocessor
17+
18+
import (
19+
"context"
20+
"fmt"
21+
"strings"
22+
23+
"github.com/arduino/arduino-cli/executils"
24+
"github.com/arduino/arduino-cli/i18n"
25+
"github.com/arduino/go-paths-helper"
26+
"github.com/arduino/go-properties-orderedmap"
27+
"github.com/pkg/errors"
28+
)
29+
30+
var tr = i18n.Tr
31+
32+
// RunCTags performs a run of ctags on the given source file. Returns the ctags output and the stderr contents.
33+
func RunCTags(sourceFile *paths.Path, buildProperties *properties.Map) ([]byte, []byte, error) {
34+
ctagsBuildProperties := properties.NewMap()
35+
ctagsBuildProperties.Set("tools.ctags.path", "{runtime.tools.ctags.path}")
36+
ctagsBuildProperties.Set("tools.ctags.cmd.path", "{path}/ctags")
37+
ctagsBuildProperties.Set("tools.ctags.pattern", `"{cmd.path}" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "{source_file}"`)
38+
ctagsBuildProperties.Merge(buildProperties)
39+
ctagsBuildProperties.Merge(ctagsBuildProperties.SubTree("tools").SubTree("ctags"))
40+
ctagsBuildProperties.SetPath("source_file", sourceFile)
41+
42+
pattern := ctagsBuildProperties.Get("pattern")
43+
if pattern == "" {
44+
return nil, nil, errors.Errorf(tr("%s pattern is missing"), "ctags")
45+
}
46+
47+
commandLine := ctagsBuildProperties.ExpandPropsInString(pattern)
48+
parts, err := properties.SplitQuotedString(commandLine, `"'`, false)
49+
if err != nil {
50+
return nil, nil, err
51+
}
52+
proc, err := executils.NewProcess(nil, parts...)
53+
if err != nil {
54+
return nil, nil, err
55+
}
56+
stdout, stderr, err := proc.RunAndCaptureOutput(context.Background())
57+
58+
// Append ctags arguments to stderr
59+
args := fmt.Sprintln(strings.Join(parts, " "))
60+
stderr = append([]byte(args), stderr...)
61+
return stdout, stderr, err
62+
}

executils/process.go

+13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package executils
1717

1818
import (
19+
"bytes"
1920
"context"
2021
"io"
2122
"os"
@@ -174,3 +175,15 @@ func (p *Process) RunWithinContext(ctx context.Context) error {
174175
}()
175176
return p.Wait()
176177
}
178+
179+
// RunAndCaptureOutput starts the specified command and waits for it to complete. If the given context
180+
// is canceled before the normal process termination, the process is killed. The standard output and
181+
// standard error of the process are captured and returned at process termination.
182+
func (p *Process) RunAndCaptureOutput(ctx context.Context) ([]byte, []byte, error) {
183+
stdout := &bytes.Buffer{}
184+
stderr := &bytes.Buffer{}
185+
p.RedirectStdoutTo(stdout)
186+
p.RedirectStderrTo(stderr)
187+
err := p.RunWithinContext(ctx)
188+
return stdout.Bytes(), stderr.Bytes(), err
189+
}

legacy/builder/container_add_prototypes.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strings"
2525

2626
bldr "github.com/arduino/arduino-cli/arduino/builder"
27+
"github.com/arduino/arduino-cli/arduino/builder/preprocessor"
2728
"github.com/arduino/arduino-cli/arduino/sketch"
2829
"github.com/arduino/arduino-cli/legacy/builder/types"
2930
"github.com/arduino/go-paths-helper"
@@ -62,10 +63,18 @@ func PreprocessSketchWithCtags(ctx *types.Context) error {
6263
ctx.SketchSourceAfterCppPreprocessing = filterSketchSource(ctx.Sketch, bytes.NewReader(src), false)
6364
}
6465

65-
if err := (&CTagsRunner{Source: &ctx.SketchSourceAfterCppPreprocessing, TargetFileName: "sketch_merged.cpp"}).Run(ctx); err != nil {
66-
return errors.WithStack(err)
66+
if err := targetFilePath.WriteFile([]byte(ctx.SketchSourceAfterCppPreprocessing)); err != nil {
67+
return err
68+
}
69+
70+
ctagsStdout, ctagsStderr, err := preprocessor.RunCTags(targetFilePath, ctx.BuildProperties)
71+
if ctx.Verbose {
72+
ctx.WriteStderr(ctagsStderr)
73+
}
74+
if err != nil {
75+
return err
6776
}
68-
ctx.SketchSourceAfterArduinoPreprocessing, ctx.PrototypesSection = PrototypesAdder(ctx.SketchSourceMerged, ctx.PrototypesLineWhereToInsert, ctx.LineOffset, ctx.Prototypes, ctx.DebugPreprocessor)
77+
ctx.SketchSourceAfterArduinoPreprocessing = PrototypesAdder(ctx.Sketch, ctx.SketchSourceMerged, ctagsStdout, ctx.LineOffset)
6978

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

legacy/builder/ctags_runner.go

-89
This file was deleted.

legacy/builder/prototypes_adder.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,37 @@ import (
2020
"strconv"
2121
"strings"
2222

23+
"github.com/arduino/arduino-cli/arduino/sketch"
2324
"github.com/arduino/arduino-cli/legacy/builder/constants"
2425
"github.com/arduino/arduino-cli/legacy/builder/ctags"
2526
"github.com/arduino/arduino-cli/legacy/builder/utils"
2627
)
2728

28-
func PrototypesAdder(source string, firstFunctionLine, lineOffset int, prototypes []*ctags.Prototype, debugOutput bool) (preprocessedSource, prototypeSection string) {
29+
var DebugPreprocessor bool
30+
31+
func PrototypesAdder(sketch *sketch.Sketch, source string, ctagsStdout []byte, lineOffset int) string {
32+
parser := &ctags.CTagsParser{}
33+
parser.Parse(ctagsStdout, sketch.MainFile)
34+
parser.FixCLinkageTagsDeclarations()
35+
36+
prototypes, firstFunctionLine := parser.GeneratePrototypes()
37+
if firstFunctionLine == -1 {
38+
firstFunctionLine = 0
39+
}
40+
2941
source = strings.Replace(source, "\r\n", "\n", -1)
3042
source = strings.Replace(source, "\r", "\n", -1)
3143
sourceRows := strings.Split(source, "\n")
3244
if isFirstFunctionOutsideOfSource(firstFunctionLine, sourceRows) {
33-
return
45+
return ""
3446
}
3547

3648
insertionLine := firstFunctionLine + lineOffset - 1
3749
firstFunctionChar := len(strings.Join(sourceRows[:insertionLine], "\n")) + 1
38-
prototypeSection = composePrototypeSection(firstFunctionLine, prototypes)
39-
preprocessedSource = source[:firstFunctionChar] + prototypeSection + source[firstFunctionChar:]
50+
prototypeSection := composePrototypeSection(firstFunctionLine, prototypes)
51+
preprocessedSource := source[:firstFunctionChar] + prototypeSection + source[firstFunctionChar:]
4052

41-
if debugOutput {
53+
if DebugPreprocessor {
4254
fmt.Println("#PREPROCESSED SOURCE")
4355
prototypesRows := strings.Split(prototypeSection, "\n")
4456
prototypesRows = prototypesRows[:len(prototypesRows)-1]
@@ -53,7 +65,7 @@ func PrototypesAdder(source string, firstFunctionLine, lineOffset int, prototype
5365
}
5466
fmt.Println("#END OF PREPROCESSED SOURCE")
5567
}
56-
return
68+
return preprocessedSource
5769
}
5870

5971
func composePrototypeSection(line int, prototypes []*ctags.Prototype) string {

0 commit comments

Comments
 (0)