From 8af70b5bb8516e377ed58bc9a7af362d1c20535b Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 4 Jul 2019 16:34:13 +0200 Subject: [PATCH 01/15] changed SketchSaver command into builder function --- arduino/builder/sketch.go | 40 +++++++++++++++ arduino/builder/sketch_test.go | 47 ++++++++++++++++++ arduino/builder/testdata/TestSaveSketch.ino | 6 +++ legacy/builder/container_add_prototypes.go | 6 ++- .../container_merge_copy_sketch_files.go | 20 ++++---- legacy/builder/create_cmake_rule.go | 1 - legacy/builder/preprocess_sketch.go | 16 +++--- legacy/builder/sketch_saver.go | 49 ------------------- 8 files changed, 116 insertions(+), 69 deletions(-) create mode 100644 arduino/builder/sketch.go create mode 100644 arduino/builder/sketch_test.go create mode 100644 arduino/builder/testdata/TestSaveSketch.ino delete mode 100644 legacy/builder/sketch_saver.go diff --git a/arduino/builder/sketch.go b/arduino/builder/sketch.go new file mode 100644 index 00000000000..b9e3d92aa1c --- /dev/null +++ b/arduino/builder/sketch.go @@ -0,0 +1,40 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to modify or +// otherwise use the software for commercial activities involving the Arduino +// software without disclosing the source code of your own applications. To purchase +// a commercial license, send an email to license@arduino.cc. + +package builder + +import ( + "io/ioutil" + "os" + "path/filepath" + + "github.com/pkg/errors" +) + +// SaveSketch saves a preprocessed .cpp sketch file on disk +func SaveSketch(sketchName string, source string, buildPath string) error { + + if err := os.MkdirAll(buildPath, os.FileMode(0755)); err != nil { + return errors.Wrap(err, "unable to create a folder to save the sketch") + } + + destFile := filepath.Join(buildPath, sketchName+".cpp") + + if err := ioutil.WriteFile(destFile, []byte(source), os.FileMode(0644)); err != nil { + return errors.Wrap(err, "unable to save the sketch on disk") + } + + return nil +} diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go new file mode 100644 index 00000000000..0552da78926 --- /dev/null +++ b/arduino/builder/sketch_test.go @@ -0,0 +1,47 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to modify or +// otherwise use the software for commercial activities involving the Arduino +// software without disclosing the source code of your own applications. To purchase +// a commercial license, send an email to license@arduino.cc. + +package builder_test + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/arduino/arduino-cli/arduino/builder" + "github.com/stretchr/testify/assert" +) + +func TestSaveSketch(t *testing.T) { + sketchName := t.Name() + ".ino" + outName := sketchName + ".cpp" + sketchFile := filepath.Join("testdata", sketchName) + tmp := tmpDirOrDie() + defer os.RemoveAll(tmp) + source, err := ioutil.ReadFile(sketchFile) + if err != nil { + t.Fatalf("unable to read golden file %s: %v", sketchFile, err) + } + + builder.SaveSketch(sketchName, string(source), tmp) + + out, err := ioutil.ReadFile(filepath.Join(tmp, outName)) + if err != nil { + t.Fatalf("unable to read output file %s: %v", outName, err) + } + + assert.Equal(t, source, out) +} diff --git a/arduino/builder/testdata/TestSaveSketch.ino b/arduino/builder/testdata/TestSaveSketch.ino new file mode 100644 index 00000000000..105b1014b73 --- /dev/null +++ b/arduino/builder/testdata/TestSaveSketch.ino @@ -0,0 +1,6 @@ +#include +#include +#include + +void setup() {} +void loop() {} \ No newline at end of file diff --git a/legacy/builder/container_add_prototypes.go b/legacy/builder/container_add_prototypes.go index 615dc8d5086..2d86fed6665 100644 --- a/legacy/builder/container_add_prototypes.go +++ b/legacy/builder/container_add_prototypes.go @@ -30,6 +30,7 @@ package builder import ( + bldr "github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/legacy/builder/constants" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" @@ -56,7 +57,6 @@ func (s *ContainerAddPrototypes) Run(ctx *types.Context) error { &CTagsTargetFileSaver{Source: &ctx.SourceGccMinusE, TargetFileName: constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E}, &CTagsRunner{}, &PrototypesAdder{}, - &SketchSaver{}, } for _, command := range commands { @@ -67,5 +67,9 @@ func (s *ContainerAddPrototypes) Run(ctx *types.Context) error { } } + if err := bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()); err != nil { + return i18n.WrapError(err) + } + return nil } diff --git a/legacy/builder/container_merge_copy_sketch_files.go b/legacy/builder/container_merge_copy_sketch_files.go index 52be057810e..30ac0dc9e8f 100644 --- a/legacy/builder/container_merge_copy_sketch_files.go +++ b/legacy/builder/container_merge_copy_sketch_files.go @@ -30,6 +30,7 @@ package builder import ( + bldr "github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" ) @@ -37,20 +38,17 @@ import ( type ContainerMergeCopySketchFiles struct{} func (s *ContainerMergeCopySketchFiles) Run(ctx *types.Context) error { - commands := []types.Command{ - &SketchSourceMerger{}, - &SketchSaver{}, - &AdditionalSketchFilesCopier{}, + if err := new(SketchSourceMerger).Run(ctx); err != nil { + return i18n.WrapError(err) } - for _, command := range commands { - PrintRingNameIfDebug(ctx, command) - err := command.Run(ctx) - if err != nil { - return i18n.WrapError(err) - } + if err := bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()); err != nil { + return i18n.WrapError(err) } - return nil + if err := new(AdditionalSketchFilesCopier).Run(ctx); err != nil { + return i18n.WrapError(err) + } + return nil } diff --git a/legacy/builder/create_cmake_rule.go b/legacy/builder/create_cmake_rule.go index 5fc54a32b60..5207eebb1b2 100644 --- a/legacy/builder/create_cmake_rule.go +++ b/legacy/builder/create_cmake_rule.go @@ -130,7 +130,6 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { //&ContainerMergeCopySketchFiles{}, &ContainerAddPrototypes{}, //&FilterSketchSource{Source: &ctx.Source, RemoveLineMarkers: true}, - //&SketchSaver{}, } for _, command := range commands { diff --git a/legacy/builder/preprocess_sketch.go b/legacy/builder/preprocess_sketch.go index dc94b2cabfa..1f961a2637a 100644 --- a/legacy/builder/preprocess_sketch.go +++ b/legacy/builder/preprocess_sketch.go @@ -37,6 +37,7 @@ import ( "runtime" "strings" + bldr "github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/legacy/builder/constants" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" @@ -66,12 +67,6 @@ func (s *PreprocessSketchArduino) Run(ctx *types.Context) error { return i18n.WrapError(err) } - if ctx.CodeCompleteAt != "" { - commands = append(commands, &OutputCodeCompletions{}) - } else { - commands = append(commands, &SketchSaver{}) - } - GCCPreprocRunner(ctx, sourceFile, ctx.PreprocPath.Join(constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E), ctx.IncludeFolders) for _, command := range commands { @@ -82,7 +77,14 @@ func (s *PreprocessSketchArduino) Run(ctx *types.Context) error { } } - return nil + var err error + if ctx.CodeCompleteAt != "" { + err = new(OutputCodeCompletions).Run(ctx) + } else { + err = bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()) + } + + return err } type ArduinoPreprocessorRunner struct{} diff --git a/legacy/builder/sketch_saver.go b/legacy/builder/sketch_saver.go deleted file mode 100644 index 59a9517a28d..00000000000 --- a/legacy/builder/sketch_saver.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of Arduino Builder. - * - * Arduino Builder is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - * - * Copyright 2015 Arduino LLC (http://www.arduino.cc/) - */ - -package builder - -import ( - "github.com/arduino/arduino-cli/legacy/builder/i18n" - "github.com/arduino/arduino-cli/legacy/builder/types" -) - -type SketchSaver struct{} - -func (s *SketchSaver) Run(ctx *types.Context) error { - sketch := ctx.Sketch - sketchBuildPath := ctx.SketchBuildPath - - if err := sketchBuildPath.MkdirAll(); err != nil { - return i18n.WrapError(err) - } - - err := sketchBuildPath.Join(sketch.MainFile.Name.Base() + ".cpp").WriteFile([]byte(ctx.Source)) - return i18n.WrapError(err) -} From 6fb3d48137dce50ad990d91037d676afb695b706 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 5 Jul 2019 14:37:22 +0200 Subject: [PATCH 02/15] added dedicated package to sketch file wrapper --- arduino/globals/globals.go | 43 ++++++++ arduino/sketch/sketch.go | 114 ++++++++++++++++++++ arduino/sketch/sketch_test.go | 67 ++++++++++++ arduino/sketch/testdata/TestNew/TestNew.ino | 12 +++ arduino/sketch/testdata/TestNew/other.cpp | 11 ++ arduino/sketch/testdata/TestNewItem.ino | 1 + 6 files changed, 248 insertions(+) create mode 100644 arduino/globals/globals.go create mode 100644 arduino/sketch/sketch.go create mode 100644 arduino/sketch/sketch_test.go create mode 100644 arduino/sketch/testdata/TestNew/TestNew.ino create mode 100644 arduino/sketch/testdata/TestNew/other.cpp create mode 100644 arduino/sketch/testdata/TestNewItem.ino diff --git a/arduino/globals/globals.go b/arduino/globals/globals.go new file mode 100644 index 00000000000..3725afddb64 --- /dev/null +++ b/arduino/globals/globals.go @@ -0,0 +1,43 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to modify or +// otherwise use the software for commercial activities involving the Arduino +// software without disclosing the source code of your own applications. To purchase +// a commercial license, send an email to license@arduino.cc. + +package globals + +var ( + empty struct{} + + // MainFileValidExtensions lists valid extensions for a sketch file + MainFileValidExtensions = map[string]struct{}{ + ".ino": empty, + ".pde": empty, + } + + // AdditionalFileValidExtensions lists any file extension the builder considers as valid + AdditionalFileValidExtensions = map[string]struct{}{ + ".h": empty, + ".c": empty, + ".hpp": empty, + ".hh": empty, + ".cpp": empty, + ".s": empty, + } + + // SourceFilesValidExtensions lists valid extensions for source files (no headers) + SourceFilesValidExtensions = map[string]struct{}{ + ".c": empty, + ".cpp": empty, + ".s": empty, + } +) diff --git a/arduino/sketch/sketch.go b/arduino/sketch/sketch.go new file mode 100644 index 00000000000..1b90916f34e --- /dev/null +++ b/arduino/sketch/sketch.go @@ -0,0 +1,114 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to modify or +// otherwise use the software for commercial activities involving the Arduino +// software without disclosing the source code of your own applications. To purchase +// a commercial license, send an email to license@arduino.cc. + +package sketch + +import ( + "io/ioutil" + "path/filepath" + "sort" + "strings" + + "github.com/arduino/arduino-cli/arduino/globals" + "github.com/pkg/errors" +) + +// Item holds the source and the path for a single sketch file +type Item struct { + Path string + Source []byte +} + +// NewItem reads the source code for a sketch item and returns an +// Item instance +func NewItem(itemPath string) (*Item, error) { + // read the file + source, err := ioutil.ReadFile(itemPath) + if err != nil { + return nil, errors.Wrap(err, "error reading source file") + } + + return &Item{itemPath, source}, nil +} + +// ItemByPath implements sort.Interface for []Item based on +// lexicographic order of the path string. +type ItemByPath []*Item + +func (ibn ItemByPath) Len() int { return len(ibn) } +func (ibn ItemByPath) Swap(i, j int) { ibn[i], ibn[j] = ibn[j], ibn[i] } +func (ibn ItemByPath) Less(i, j int) bool { return ibn[i].Path < ibn[j].Path } + +// Sketch holds all the files composing a sketch +type Sketch struct { + MainFile *Item + OtherSketchFiles []*Item + AdditionalFiles []*Item +} + +// New creates an Sketch instance by reading all the files composing a sketch and grouping them +// by file type. +func New(sketchFolderPath, mainFilePath, buildPath string, allFilesPaths []string) (*Sketch, error) { + var mainFile *Item + + // read all the sketch contents and create sketch Items + pathToItem := make(map[string]*Item) + for _, p := range allFilesPaths { + // create an Item + item, err := NewItem(p) + if err != nil { + return nil, errors.Wrap(err, "error creating the sketch") + } + + if p == mainFilePath { + // store the main sketch file + mainFile = item + } else { + // map the file path to sketch.Item + pathToItem[p] = item + } + } + + // organize the Items + additionalFiles := []*Item{} + otherSketchFiles := []*Item{} + for p, item := range pathToItem { + ext := strings.ToLower(filepath.Ext(p)) + if _, found := globals.MainFileValidExtensions[ext]; found { + // item is a valid main file, see if it's stored at the + // sketch root and ignore if it's not. + if filepath.Dir(p) == sketchFolderPath { + otherSketchFiles = append(otherSketchFiles, item) + } + } else if _, found := globals.AdditionalFileValidExtensions[ext]; found { + // item is a valid sketch file, grab it only if the buildPath is empty + // or the file is within the buildPath + if buildPath == "" || !strings.Contains(filepath.Dir(p), buildPath) { + additionalFiles = append(additionalFiles, item) + } + } else { + return nil, errors.Errorf("unknown sketch file extension '%s'", ext) + } + } + + sort.Sort(ItemByPath(additionalFiles)) + sort.Sort(ItemByPath(otherSketchFiles)) + + return &Sketch{ + MainFile: mainFile, + OtherSketchFiles: otherSketchFiles, + AdditionalFiles: additionalFiles, + }, nil +} diff --git a/arduino/sketch/sketch_test.go b/arduino/sketch/sketch_test.go new file mode 100644 index 00000000000..833c384e747 --- /dev/null +++ b/arduino/sketch/sketch_test.go @@ -0,0 +1,67 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to modify or +// otherwise use the software for commercial activities involving the Arduino +// software without disclosing the source code of your own applications. To purchase +// a commercial license, send an email to license@arduino.cc. + +package sketch_test + +import ( + "path/filepath" + "sort" + "testing" + + "github.com/arduino/arduino-cli/arduino/sketch" + "github.com/stretchr/testify/assert" +) + +func TestNewItem(t *testing.T) { + sketchItem := filepath.Join("testdata", t.Name()+".ino") + item, err := sketch.NewItem(sketchItem) + assert.Nil(t, err) + assert.Equal(t, sketchItem, item.Path) + assert.Equal(t, []byte(`#include `), item.Source) + + item, err = sketch.NewItem("doesnt/exist") + assert.Nil(t, item) + assert.NotNil(t, err) +} + +func TestSort(t *testing.T) { + items := []*sketch.Item{ + &sketch.Item{"foo", nil}, + &sketch.Item{"baz", nil}, + &sketch.Item{"bar", nil}, + } + + sort.Sort(sketch.ItemByPath(items)) + + assert.Equal(t, "bar", items[0].Path) + assert.Equal(t, "baz", items[1].Path) + assert.Equal(t, "foo", items[2].Path) +} + +func TestNew(t *testing.T) { + sketchFolderPath := filepath.Join("testdata", t.Name()) + mainFilePath := filepath.Join(sketchFolderPath, t.Name()+".ino") + otherFile := filepath.Join(sketchFolderPath, "other.cpp") + allFilesPaths := []string{ + mainFilePath, + otherFile, + } + + sketch, err := sketch.New(sketchFolderPath, mainFilePath, "", allFilesPaths) + assert.Nil(t, err) + assert.Equal(t, mainFilePath, sketch.MainFile.Path) + assert.Len(t, sketch.OtherSketchFiles, 0) + assert.Len(t, sketch.AdditionalFiles, 1) +} diff --git a/arduino/sketch/testdata/TestNew/TestNew.ino b/arduino/sketch/testdata/TestNew/TestNew.ino new file mode 100644 index 00000000000..24a585772c3 --- /dev/null +++ b/arduino/sketch/testdata/TestNew/TestNew.ino @@ -0,0 +1,12 @@ +#include +#include "subfolder/other.h" +#include "src/subfolder/other.h" + +MyClass myClass; + +void setup() { + myClass.init ( &Serial ); +} + +void loop() { +} diff --git a/arduino/sketch/testdata/TestNew/other.cpp b/arduino/sketch/testdata/TestNew/other.cpp new file mode 100644 index 00000000000..ea74d5a00fb --- /dev/null +++ b/arduino/sketch/testdata/TestNew/other.cpp @@ -0,0 +1,11 @@ +#include // Arduino 1.0 +#include + +#include "other.h" + +MyClass::MyClass() { +} + +void MyClass::init ( Stream *stream ) { + controllerStream = stream; +} diff --git a/arduino/sketch/testdata/TestNewItem.ino b/arduino/sketch/testdata/TestNewItem.ino new file mode 100644 index 00000000000..871c34f5612 --- /dev/null +++ b/arduino/sketch/testdata/TestNewItem.ino @@ -0,0 +1 @@ +#include \ No newline at end of file From 2a6a03e4bc0d2588487181da72b5478563613e07 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 5 Jul 2019 15:06:00 +0200 Subject: [PATCH 03/15] use sketch.Item --- arduino/builder/sketch.go | 88 ++++++++++++++++++- arduino/builder/sketch_test.go | 3 +- go.sum | 1 + legacy/builder/container_add_prototypes.go | 3 +- .../container_merge_copy_sketch_files.go | 3 +- legacy/builder/preprocess_sketch.go | 3 +- 6 files changed, 94 insertions(+), 7 deletions(-) diff --git a/arduino/builder/sketch.go b/arduino/builder/sketch.go index b9e3d92aa1c..46c61e5fa62 100644 --- a/arduino/builder/sketch.go +++ b/arduino/builder/sketch.go @@ -19,12 +19,18 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" + + "github.com/arduino/arduino-cli/arduino/globals" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/pkg/errors" ) -// SaveSketch saves a preprocessed .cpp sketch file on disk -func SaveSketch(sketchName string, source string, buildPath string) error { +// SaveSketchItemCpp saves a preprocessed .cpp sketch file on disk +func SaveSketchItemCpp(item *sketch.Item, buildPath string) error { + + sketchName := filepath.Base(item.Path) if err := os.MkdirAll(buildPath, os.FileMode(0755)); err != nil { return errors.Wrap(err, "unable to create a folder to save the sketch") @@ -32,9 +38,85 @@ func SaveSketch(sketchName string, source string, buildPath string) error { destFile := filepath.Join(buildPath, sketchName+".cpp") - if err := ioutil.WriteFile(destFile, []byte(source), os.FileMode(0644)); err != nil { + if err := ioutil.WriteFile(destFile, item.Source, os.FileMode(0644)); err != nil { return errors.Wrap(err, "unable to save the sketch on disk") } return nil } + +// LoadSketch collects all the files composing a sketch. +// The parameter `sketchPath` holds a path pointing to a single sketch file or a sketch folder, +// the path must be absolute. +func LoadSketch(sketchPath, buildPath string) (*sketch.Sketch, error) { + stat, err := os.Stat(sketchPath) + if err != nil { + return nil, errors.Wrap(err, "unable to stat Sketch location") + } + + var sketchFolder, mainSketchFile string + + // if a sketch folder was passed, save the parent and point sketchPath to the main .ino file + if stat.IsDir() { + sketchFolder = sketchPath + mainSketchFile = filepath.Join(sketchPath, stat.Name()+".ino") + // in the case a dir was passed, ensure the main file exists and is readable + f, err := os.Open(mainSketchFile) + if err != nil { + return nil, errors.Wrap(err, "unable to find the main sketch file") + } + f.Close() + } else { + sketchFolder = filepath.Dir(sketchPath) + mainSketchFile = sketchPath + } + + // collect all the sketch files + var files []string + err = filepath.Walk(sketchFolder, func(path string, info os.FileInfo, err error) error { + // ignore hidden files and skip hidden directories + if strings.HasPrefix(info.Name(), ".") { + if info.IsDir() { + return filepath.SkipDir + } + return nil + } + + // skip legacy SCM directories + if info.IsDir() && strings.HasPrefix(info.Name(), "CVS") || strings.HasPrefix(info.Name(), "RCS") { + return filepath.SkipDir + } + + // ignore directory entries + if info.IsDir() { + return nil + } + + // ignore if file extension doesn't match + ext := strings.ToLower(filepath.Ext(path)) + _, isMain := globals.MainFileValidExtensions[ext] + _, isAdditional := globals.AdditionalFileValidExtensions[ext] + if !(isMain || isAdditional) { + return nil + } + + // check if file is readable + f, err := os.Open(path) + if err != nil { + return nil + } + f.Close() + + // collect the file + files = append(files, path) + + // done + return nil + }) + + if err != nil { + return nil, errors.Wrap(err, "there was an error while collecting the sketch files") + } + + return sketch.New(sketchFolder, mainSketchFile, buildPath, files) +} diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index 0552da78926..1623ea4b245 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/arduino/arduino-cli/arduino/builder" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/stretchr/testify/assert" ) @@ -36,7 +37,7 @@ func TestSaveSketch(t *testing.T) { t.Fatalf("unable to read golden file %s: %v", sketchFile, err) } - builder.SaveSketch(sketchName, string(source), tmp) + builder.SaveSketchItemCpp(&sketch.Item{Path: sketchName, Source: source}, tmp) out, err := ioutil.ReadFile(filepath.Join(tmp, outName)) if err != nil { diff --git a/go.sum b/go.sum index ddc8a81d7eb..5375daa7a0c 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U= bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/arduino/arduino v0.0.0-20190521072917-00a7546fb43e h1:5TJufBg+nZAFruNEALBVHDPRMtMDbRg7Hox/WA4ZI40= github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c h1:agh2JT96G8egU7FEb13L4dq3fnCN7lxXhJ86t69+W7s= github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8= github.com/arduino/go-paths-helper v0.0.0-20190214132331-c3c98d1bf2e1 h1:S0NpDSqjlkNA510vmRCP5Cq9mPgu3rWDSdeN4SI1Mwc= diff --git a/legacy/builder/container_add_prototypes.go b/legacy/builder/container_add_prototypes.go index 2d86fed6665..93d1069283a 100644 --- a/legacy/builder/container_add_prototypes.go +++ b/legacy/builder/container_add_prototypes.go @@ -31,6 +31,7 @@ package builder import ( bldr "github.com/arduino/arduino-cli/arduino/builder" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/legacy/builder/constants" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" @@ -67,7 +68,7 @@ func (s *ContainerAddPrototypes) Run(ctx *types.Context) error { } } - if err := bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()); err != nil { + if err := bldr.SaveSketchItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()); err != nil { return i18n.WrapError(err) } diff --git a/legacy/builder/container_merge_copy_sketch_files.go b/legacy/builder/container_merge_copy_sketch_files.go index 30ac0dc9e8f..b7466906a4c 100644 --- a/legacy/builder/container_merge_copy_sketch_files.go +++ b/legacy/builder/container_merge_copy_sketch_files.go @@ -31,6 +31,7 @@ package builder import ( bldr "github.com/arduino/arduino-cli/arduino/builder" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" ) @@ -42,7 +43,7 @@ func (s *ContainerMergeCopySketchFiles) Run(ctx *types.Context) error { return i18n.WrapError(err) } - if err := bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()); err != nil { + if err := bldr.SaveSketchItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()); err != nil { return i18n.WrapError(err) } diff --git a/legacy/builder/preprocess_sketch.go b/legacy/builder/preprocess_sketch.go index 1f961a2637a..22051dd6888 100644 --- a/legacy/builder/preprocess_sketch.go +++ b/legacy/builder/preprocess_sketch.go @@ -38,6 +38,7 @@ import ( "strings" bldr "github.com/arduino/arduino-cli/arduino/builder" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/legacy/builder/constants" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" @@ -81,7 +82,7 @@ func (s *PreprocessSketchArduino) Run(ctx *types.Context) error { if ctx.CodeCompleteAt != "" { err = new(OutputCodeCompletions).Run(ctx) } else { - err = bldr.SaveSketch(ctx.Sketch.MainFile.Name.Base(), ctx.Source, ctx.SketchBuildPath.String()) + err = bldr.SaveSketchItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()) } return err From 8c18ef54c98685b1a0398cd2f90a06d8122b44ac Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 5 Jul 2019 16:34:03 +0200 Subject: [PATCH 04/15] restored LoadSketch tests --- arduino/builder/sketch_test.go | 37 ++++ .../TestLoadSketchFolder/.#sketch.ino | 2 + .../TestLoadSketchFolder.ino | 7 + .../testdata/TestLoadSketchFolder/doc.txt | 0 .../testdata/TestLoadSketchFolder/header.h | 1 + .../TestLoadSketchFolder/merged_sketch.txt | 16 ++ .../testdata/TestLoadSketchFolder/old.pde | 0 .../testdata/TestLoadSketchFolder/other.ino | 3 + .../testdata/TestLoadSketchFolder/s_file.S | 0 .../TestLoadSketchFolder/src/dont_load_me.ino | 2 + .../TestLoadSketchFolder/src/helper.h | 0 .../TestLoadSketchFolderWrongMain/main.ino | 0 legacy/builder/test/sketch_loader_test.go | 178 ------------------ 13 files changed, 68 insertions(+), 178 deletions(-) create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/.#sketch.ino create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/TestLoadSketchFolder.ino create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/doc.txt create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/header.h create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/old.pde create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/other.ino create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/s_file.S create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/src/dont_load_me.ino create mode 100644 arduino/builder/testdata/TestLoadSketchFolder/src/helper.h create mode 100644 arduino/builder/testdata/TestLoadSketchFolderWrongMain/main.ino delete mode 100644 legacy/builder/test/sketch_loader_test.go diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index 1623ea4b245..5098b908620 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -46,3 +46,40 @@ func TestSaveSketch(t *testing.T) { assert.Equal(t, source, out) } + +func TestLoadSketchFolder(t *testing.T) { + // pass the path to the sketch folder + sketchPath := filepath.Join("testdata", t.Name()) + mainFilePath := filepath.Join(sketchPath, t.Name()+".ino") + s, err := builder.LoadSketch(sketchPath, "") + assert.Nil(t, err) + assert.NotNil(t, s) + assert.Equal(t, mainFilePath, s.MainFile.Path) + assert.Len(t, s.OtherSketchFiles, 2) // [old.pde, other.ino] + assert.Len(t, s.AdditionalFiles, 3) // [header.h, s_file.S, src/helper.h] + + // pass the path to the main file + sketchPath = mainFilePath + s, err = builder.LoadSketch(sketchPath, "") + assert.Nil(t, err) + assert.NotNil(t, s) + assert.Equal(t, mainFilePath, s.MainFile.Path) + assert.Len(t, s.OtherSketchFiles, 2) + assert.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path)) + assert.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path)) + assert.Len(t, s.AdditionalFiles, 3) + assert.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path)) + assert.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path)) + assert.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path)) +} + +func TestLoadSketchFolderWrongMain(t *testing.T) { + sketchPath := filepath.Join("testdata", t.Name()) + _, err := builder.LoadSketch(sketchPath, "") + assert.Error(t, err) + assert.Contains(t, err.Error(), "unable to find the main sketch file") + + _, err = builder.LoadSketch("does/not/exist", "") + assert.Error(t, err) + assert.Contains(t, err.Error(), "no such file or directory") +} diff --git a/arduino/builder/testdata/TestLoadSketchFolder/.#sketch.ino b/arduino/builder/testdata/TestLoadSketchFolder/.#sketch.ino new file mode 100644 index 00000000000..71048175432 --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/.#sketch.ino @@ -0,0 +1,2 @@ +void setup() +void loop) } \ No newline at end of file diff --git a/arduino/builder/testdata/TestLoadSketchFolder/TestLoadSketchFolder.ino b/arduino/builder/testdata/TestLoadSketchFolder/TestLoadSketchFolder.ino new file mode 100644 index 00000000000..0d5e0f5ceb9 --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/TestLoadSketchFolder.ino @@ -0,0 +1,7 @@ +void setup() { + +} + +void loop() { + +} \ No newline at end of file diff --git a/arduino/builder/testdata/TestLoadSketchFolder/doc.txt b/arduino/builder/testdata/TestLoadSketchFolder/doc.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/arduino/builder/testdata/TestLoadSketchFolder/header.h b/arduino/builder/testdata/TestLoadSketchFolder/header.h new file mode 100644 index 00000000000..2e24536f9fb --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/header.h @@ -0,0 +1 @@ +#define TRUE FALSE \ No newline at end of file diff --git a/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt b/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt new file mode 100644 index 00000000000..4654de3236c --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt @@ -0,0 +1,16 @@ +#include +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +void setup() { + +} + +void loop() { + +} +#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 0).Name}} + +#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 1).Name}} +String hello() { + return "world"; +} diff --git a/arduino/builder/testdata/TestLoadSketchFolder/old.pde b/arduino/builder/testdata/TestLoadSketchFolder/old.pde new file mode 100644 index 00000000000..e69de29bb2d diff --git a/arduino/builder/testdata/TestLoadSketchFolder/other.ino b/arduino/builder/testdata/TestLoadSketchFolder/other.ino new file mode 100644 index 00000000000..c426196c017 --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/other.ino @@ -0,0 +1,3 @@ +String hello() { + return "world"; +} \ No newline at end of file diff --git a/arduino/builder/testdata/TestLoadSketchFolder/s_file.S b/arduino/builder/testdata/TestLoadSketchFolder/s_file.S new file mode 100644 index 00000000000..e69de29bb2d diff --git a/arduino/builder/testdata/TestLoadSketchFolder/src/dont_load_me.ino b/arduino/builder/testdata/TestLoadSketchFolder/src/dont_load_me.ino new file mode 100644 index 00000000000..46b07018d09 --- /dev/null +++ b/arduino/builder/testdata/TestLoadSketchFolder/src/dont_load_me.ino @@ -0,0 +1,2 @@ +#include +#error "Whattya looking at?" diff --git a/arduino/builder/testdata/TestLoadSketchFolder/src/helper.h b/arduino/builder/testdata/TestLoadSketchFolder/src/helper.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/arduino/builder/testdata/TestLoadSketchFolderWrongMain/main.ino b/arduino/builder/testdata/TestLoadSketchFolderWrongMain/main.ino new file mode 100644 index 00000000000..e69de29bb2d diff --git a/legacy/builder/test/sketch_loader_test.go b/legacy/builder/test/sketch_loader_test.go deleted file mode 100644 index dad4f7e01f2..00000000000 --- a/legacy/builder/test/sketch_loader_test.go +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is part of Arduino Builder. - * - * Arduino Builder is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - * - * Copyright 2015 Arduino LLC (http://www.arduino.cc/) - */ - -package test - -import ( - "path/filepath" - "testing" - - "github.com/arduino/arduino-cli/legacy/builder" - "github.com/arduino/arduino-cli/legacy/builder/types" - paths "github.com/arduino/go-paths-helper" - "github.com/stretchr/testify/require" -) - -func TestLoadSketchWithFolder(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch1"), - } - - loader := builder.SketchLoader{} - err := loader.Run(ctx) - - require.Error(t, err) - require.Nil(t, ctx.Sketch) -} - -func TestLoadSketchNonExistentPath(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("asdasd78128123981723981273asdasd"), - } - - loader := builder.SketchLoader{} - err := loader.Run(ctx) - - require.Error(t, err) - require.Nil(t, ctx.Sketch) -} - -func TestLoadSketch(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch1", "sketch.ino"), - } - - commands := []types.Command{ - &builder.SketchLoader{}, - } - - for _, command := range commands { - err := command.Run(ctx) - NoError(t, err) - } - - sketch := ctx.Sketch - require.NotNil(t, sketch) - - require.Contains(t, sketch.MainFile.Name.String(), "sketch.ino") - - require.Equal(t, 2, len(sketch.OtherSketchFiles)) - require.Contains(t, sketch.OtherSketchFiles[0].Name.String(), "old.pde") - require.Contains(t, sketch.OtherSketchFiles[1].Name.String(), "other.ino") - - require.Equal(t, 3, len(sketch.AdditionalFiles)) - require.Contains(t, sketch.AdditionalFiles[0].Name.String(), "header.h") - require.Contains(t, sketch.AdditionalFiles[1].Name.String(), "s_file.S") - require.Contains(t, sketch.AdditionalFiles[2].Name.String(), "helper.h") -} - -func TestFailToLoadSketchFromFolder(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("./sketch1"), - } - - loader := builder.SketchLoader{} - err := loader.Run(ctx) - require.Error(t, err) - require.Nil(t, ctx.Sketch) -} - -func TestLoadSketchFromFolder(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch_with_subfolders"), - } - - commands := []types.Command{ - &builder.SketchLoader{}, - } - - for _, command := range commands { - err := command.Run(ctx) - NoError(t, err) - } - - sketch := ctx.Sketch - require.NotNil(t, sketch) - - require.Contains(t, sketch.MainFile.Name.String(), "sketch_with_subfolders.ino") - - require.Equal(t, 0, len(sketch.OtherSketchFiles)) - - require.Equal(t, 4, len(sketch.AdditionalFiles)) - require.Contains(t, filepath.ToSlash(sketch.AdditionalFiles[0].Name.String()), "sketch_with_subfolders/src/subfolder/other.cpp") - require.Contains(t, filepath.ToSlash(sketch.AdditionalFiles[1].Name.String()), "sketch_with_subfolders/src/subfolder/other.h") - require.Contains(t, filepath.ToSlash(sketch.AdditionalFiles[2].Name.String()), "sketch_with_subfolders/subfolder/dont_load_me.cpp") - require.Contains(t, filepath.ToSlash(sketch.AdditionalFiles[3].Name.String()), "sketch_with_subfolders/subfolder/other.h") -} - -func TestLoadSketchWithBackup(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch_with_backup_files", "sketch.ino"), - } - - commands := []types.Command{ - &builder.SketchLoader{}, - } - - for _, command := range commands { - err := command.Run(ctx) - NoError(t, err) - } - - sketch := ctx.Sketch - require.NotNil(t, sketch) - - require.Contains(t, sketch.MainFile.Name.String(), "sketch.ino") - - require.Equal(t, 0, len(sketch.AdditionalFiles)) - require.Equal(t, 0, len(sketch.OtherSketchFiles)) -} - -func TestLoadSketchWithMacOSXGarbage(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch_with_macosx_garbage", "sketch.ino"), - } - - commands := []types.Command{ - &builder.SketchLoader{}, - } - - for _, command := range commands { - err := command.Run(ctx) - NoError(t, err) - } - - sketch := ctx.Sketch - require.NotNil(t, sketch) - - require.Contains(t, sketch.MainFile.Name.String(), "sketch.ino") - - require.Equal(t, 0, len(sketch.AdditionalFiles)) - require.Equal(t, 0, len(sketch.OtherSketchFiles)) -} From a32e90a695ce49077b4d2e873771ccbb056c4a89 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 5 Jul 2019 16:53:13 +0200 Subject: [PATCH 05/15] forgot to check both cases --- arduino/builder/sketch_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index 5098b908620..5742171fe5a 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -55,8 +55,13 @@ func TestLoadSketchFolder(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, s) assert.Equal(t, mainFilePath, s.MainFile.Path) - assert.Len(t, s.OtherSketchFiles, 2) // [old.pde, other.ino] - assert.Len(t, s.AdditionalFiles, 3) // [header.h, s_file.S, src/helper.h] + assert.Len(t, s.OtherSketchFiles, 2) + assert.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path)) + assert.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path)) + assert.Len(t, s.AdditionalFiles, 3) + assert.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path)) + assert.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path)) + assert.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path)) // pass the path to the main file sketchPath = mainFilePath From 34474dc56a0f2bb81767facfc46b44d06fa397f1 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 5 Jul 2019 16:54:09 +0200 Subject: [PATCH 06/15] stop using SketchLoader command in container setup --- legacy/builder/container_setup.go | 31 ++++++++++++++++++++++++++++++- legacy/builder/types/types.go | 25 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/legacy/builder/container_setup.go b/legacy/builder/container_setup.go index 4b0ad5bf190..03f0af139cd 100644 --- a/legacy/builder/container_setup.go +++ b/legacy/builder/container_setup.go @@ -30,9 +30,11 @@ package builder import ( + bldr "github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/legacy/builder/builder_utils" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" + "github.com/arduino/go-paths-helper" ) type ContainerSetupHardwareToolsLibsSketchAndProps struct{} @@ -48,7 +50,34 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(ctx *types.Context) &ToolsLoader{}, &AddBuildBoardPropertyIfMissing{}, &LibrariesLoader{}, - &SketchLoader{}, + } + + ctx.Progress.Steps = ctx.Progress.Steps / float64(len(commands)) + + for _, command := range commands { + builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx) + PrintRingNameIfDebug(ctx, command) + err := command.Run(ctx) + if err != nil { + return i18n.WrapError(err) + } + } + + // get abs path to sketch + sketchLocation, err := ctx.SketchLocation.Abs() + if err != nil { + return i18n.WrapError(err) + } + + // load sketch + sketch, err := bldr.LoadSketch(sketchLocation.String(), ctx.BuildPath.String()) + if err != nil { + return i18n.WrapError(err) + } + ctx.SketchLocation = paths.New(sketch.MainFile.Path) + ctx.Sketch = types.SketchToLegacy(sketch) + + commands = []types.Command{ &SetupBuildProperties{}, &LoadVIDPIDSpecificProperties{}, &SetCustomBuildProperties{}, diff --git a/legacy/builder/types/types.go b/legacy/builder/types/types.go index 14c95bc07bc..1e00a37e10f 100644 --- a/legacy/builder/types/types.go +++ b/legacy/builder/types/types.go @@ -34,6 +34,7 @@ import ( "strconv" "github.com/arduino/arduino-cli/arduino/libraries" + "github.com/arduino/arduino-cli/arduino/sketch" paths "github.com/arduino/go-paths-helper" ) @@ -123,6 +124,30 @@ type Sketch struct { AdditionalFiles []SketchFile } +func SketchToLegacy(sketch *sketch.Sketch) *Sketch { + s := &Sketch{} + s.MainFile = SketchFile{ + paths.New(sketch.MainFile.Path), + string(sketch.MainFile.Source), + } + + for _, item := range sketch.OtherSketchFiles { + s.OtherSketchFiles = append(s.OtherSketchFiles, SketchFile{ + paths.New(item.Path), + string(item.Source), + }) + } + + for _, item := range sketch.AdditionalFiles { + s.AdditionalFiles = append(s.AdditionalFiles, SketchFile{ + paths.New(item.Path), + string(item.Source), + }) + } + + return s +} + type PlatforKeysRewrite struct { Rewrites []PlatforKeyRewrite } From 9c740866a876202ea723e331d21edd061fbccdc3 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 10:18:33 +0200 Subject: [PATCH 07/15] store sketch location in the sketch struct --- arduino/builder/sketch_test.go | 1 + arduino/sketch/sketch.go | 2 ++ arduino/sketch/sketch_test.go | 1 + 3 files changed, 4 insertions(+) diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index 5742171fe5a..bb4aa5fbfb9 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -55,6 +55,7 @@ func TestLoadSketchFolder(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, s) assert.Equal(t, mainFilePath, s.MainFile.Path) + assert.Equal(t, sketchPath, s.LocationPath) assert.Len(t, s.OtherSketchFiles, 2) assert.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path)) assert.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path)) diff --git a/arduino/sketch/sketch.go b/arduino/sketch/sketch.go index 1b90916f34e..c76fd435622 100644 --- a/arduino/sketch/sketch.go +++ b/arduino/sketch/sketch.go @@ -54,6 +54,7 @@ func (ibn ItemByPath) Less(i, j int) bool { return ibn[i].Path < ibn[j].Path } // Sketch holds all the files composing a sketch type Sketch struct { MainFile *Item + LocationPath string OtherSketchFiles []*Item AdditionalFiles []*Item } @@ -108,6 +109,7 @@ func New(sketchFolderPath, mainFilePath, buildPath string, allFilesPaths []strin return &Sketch{ MainFile: mainFile, + LocationPath: sketchFolderPath, OtherSketchFiles: otherSketchFiles, AdditionalFiles: additionalFiles, }, nil diff --git a/arduino/sketch/sketch_test.go b/arduino/sketch/sketch_test.go index 833c384e747..283c8362954 100644 --- a/arduino/sketch/sketch_test.go +++ b/arduino/sketch/sketch_test.go @@ -62,6 +62,7 @@ func TestNew(t *testing.T) { sketch, err := sketch.New(sketchFolderPath, mainFilePath, "", allFilesPaths) assert.Nil(t, err) assert.Equal(t, mainFilePath, sketch.MainFile.Path) + assert.Equal(t, sketchFolderPath, sketch.LocationPath) assert.Len(t, sketch.OtherSketchFiles, 0) assert.Len(t, sketch.AdditionalFiles, 1) } From 8feeb6a6184deed0f1707269c8c381371cd2f520 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 11:50:19 +0200 Subject: [PATCH 08/15] add convenience method to get the source in string format --- arduino/sketch/sketch.go | 5 +++++ arduino/sketch/sketch_test.go | 1 + 2 files changed, 6 insertions(+) diff --git a/arduino/sketch/sketch.go b/arduino/sketch/sketch.go index c76fd435622..6e062c14623 100644 --- a/arduino/sketch/sketch.go +++ b/arduino/sketch/sketch.go @@ -43,6 +43,11 @@ func NewItem(itemPath string) (*Item, error) { return &Item{itemPath, source}, nil } +// GetSourceStr returns the Source contents in string format +func (i *Item) GetSourceStr() string { + return string(i.Source) +} + // ItemByPath implements sort.Interface for []Item based on // lexicographic order of the path string. type ItemByPath []*Item diff --git a/arduino/sketch/sketch_test.go b/arduino/sketch/sketch_test.go index 283c8362954..f0d8760ef47 100644 --- a/arduino/sketch/sketch_test.go +++ b/arduino/sketch/sketch_test.go @@ -30,6 +30,7 @@ func TestNewItem(t *testing.T) { assert.Nil(t, err) assert.Equal(t, sketchItem, item.Path) assert.Equal(t, []byte(`#include `), item.Source) + assert.Equal(t, "#include ", item.GetSourceStr()) item, err = sketch.NewItem("doesnt/exist") assert.Nil(t, item) From 4a23cd073fc5d33591016aa382cfe43b6a7816d2 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 13:17:56 +0200 Subject: [PATCH 09/15] added MergeSketchSources + tests --- arduino/builder/sketch.go | 35 +++++++++++++++++++ arduino/builder/sketch_test.go | 18 ++++++++++ .../TestLoadSketchFolder/merged_sketch.txt | 16 --------- .../testdata/TestMergeSketchSources.txt | 15 ++++++++ 4 files changed, 68 insertions(+), 16 deletions(-) delete mode 100644 arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt create mode 100644 arduino/builder/testdata/TestMergeSketchSources.txt diff --git a/arduino/builder/sketch.go b/arduino/builder/sketch.go index 46c61e5fa62..b1c1f1ec3e4 100644 --- a/arduino/builder/sketch.go +++ b/arduino/builder/sketch.go @@ -19,6 +19,7 @@ import ( "io/ioutil" "os" "path/filepath" + "regexp" "strings" "github.com/arduino/arduino-cli/arduino/globals" @@ -27,6 +28,17 @@ import ( "github.com/pkg/errors" ) +var includesArduinoH = regexp.MustCompile(`^\s*#\s*include\s*[<\"]Arduino\.h[>\"]`) + +// QuoteCppString returns the given string as a quoted string for use with the C +// preprocessor. This adds double quotes around it and escapes any +// double quotes and backslashes in the string. +func QuoteCppString(str string) string { + str = strings.Replace(str, "\\", "\\\\", -1) + str = strings.Replace(str, "\"", "\\\"", -1) + return "\"" + str + "\"" +} + // SaveSketchItemCpp saves a preprocessed .cpp sketch file on disk func SaveSketchItemCpp(item *sketch.Item, buildPath string) error { @@ -120,3 +132,26 @@ func LoadSketch(sketchPath, buildPath string) (*sketch.Sketch, error) { return sketch.New(sketchFolder, mainSketchFile, buildPath, files) } + +// MergeSketchSources merges all the source files included in a sketch +func MergeSketchSources(sketch *sketch.Sketch) (int, string) { + lineOffset := 0 + mergedSource := "" + + // add Arduino.h inclusion directive if missing + if !includesArduinoH.MatchString(sketch.MainFile.GetSourceStr()) { + mergedSource += "#include \n" + lineOffset++ + } + + mergedSource += "#line 1 " + QuoteCppString(sketch.MainFile.Path) + "\n" + mergedSource += sketch.MainFile.GetSourceStr() + "\n" + lineOffset++ + + for _, item := range sketch.OtherSketchFiles { + mergedSource += "#line 1 " + QuoteCppString(item.Path) + "\n" + mergedSource += item.GetSourceStr() + "\n" + } + + return lineOffset, mergedSource +} diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index bb4aa5fbfb9..6fd099f6a8c 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -89,3 +89,21 @@ func TestLoadSketchFolderWrongMain(t *testing.T) { assert.Error(t, err) assert.Contains(t, err.Error(), "no such file or directory") } + +func TestMergeSketchSources(t *testing.T) { + // borrow the sketch from TestLoadSketchFolder to avoid boilerplate + s, err := builder.LoadSketch(filepath.Join("testdata", "TestLoadSketchFolder"), "") + assert.Nil(t, err) + assert.NotNil(t, s) + + // load expected result + mergedPath := filepath.Join("testdata", t.Name()+".txt") + mergedBytes, err := ioutil.ReadFile(mergedPath) + if err != nil { + t.Fatalf("unable to read golden file %s: %v", mergedPath, err) + } + + offset, source := builder.MergeSketchSources(s) + assert.Equal(t, 2, offset) + assert.Equal(t, string(mergedBytes), source) +} diff --git a/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt b/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt deleted file mode 100644 index 4654de3236c..00000000000 --- a/arduino/builder/testdata/TestLoadSketchFolder/merged_sketch.txt +++ /dev/null @@ -1,16 +0,0 @@ -#include -#line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} -void setup() { - -} - -void loop() { - -} -#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 0).Name}} - -#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 1).Name}} -String hello() { - return "world"; -} diff --git a/arduino/builder/testdata/TestMergeSketchSources.txt b/arduino/builder/testdata/TestMergeSketchSources.txt new file mode 100644 index 00000000000..57f68974397 --- /dev/null +++ b/arduino/builder/testdata/TestMergeSketchSources.txt @@ -0,0 +1,15 @@ +#include +#line 1 "testdata/TestLoadSketchFolder/TestLoadSketchFolder.ino" +void setup() { + +} + +void loop() { + +} +#line 1 "testdata/TestLoadSketchFolder/old.pde" + +#line 1 "testdata/TestLoadSketchFolder/other.ino" +String hello() { + return "world"; +} From 1e045281fcfbdaf708ca3daa06cc3d86b25268f4 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 13:18:12 +0200 Subject: [PATCH 10/15] use MergeSketchSources instead of the command --- .../container_merge_copy_sketch_files.go | 4 ++ .../builder/test/sketch_source_merger_test.go | 63 ------------------- legacy/builder/types/types.go | 26 ++++++++ 3 files changed, 30 insertions(+), 63 deletions(-) delete mode 100644 legacy/builder/test/sketch_source_merger_test.go diff --git a/legacy/builder/container_merge_copy_sketch_files.go b/legacy/builder/container_merge_copy_sketch_files.go index b7466906a4c..d8124a9239d 100644 --- a/legacy/builder/container_merge_copy_sketch_files.go +++ b/legacy/builder/container_merge_copy_sketch_files.go @@ -39,6 +39,10 @@ import ( type ContainerMergeCopySketchFiles struct{} func (s *ContainerMergeCopySketchFiles) Run(ctx *types.Context) error { + offset, source := bldr.MergeSketchSources(types.SketchFromLegacy(ctx.Sketch)) + ctx.LineOffset = offset + ctx.Source = source + if err := new(SketchSourceMerger).Run(ctx); err != nil { return i18n.WrapError(err) } diff --git a/legacy/builder/test/sketch_source_merger_test.go b/legacy/builder/test/sketch_source_merger_test.go deleted file mode 100644 index 29b6a657d40..00000000000 --- a/legacy/builder/test/sketch_source_merger_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Arduino Builder. - * - * Arduino Builder is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - * - * Copyright 2015 Arduino LLC (http://www.arduino.cc/) - * Copyright 2015 Matthijs Kooijman - */ - -package test - -import ( - "path/filepath" - "strings" - "testing" - - "github.com/arduino/arduino-cli/legacy/builder" - "github.com/arduino/arduino-cli/legacy/builder/types" - "github.com/arduino/go-paths-helper" - "github.com/stretchr/testify/require" -) - -func TestMergeSketch(t *testing.T) { - ctx := &types.Context{ - SketchLocation: paths.New("sketch1", "sketch.ino"), - } - - commands := []types.Command{ - &builder.SketchLoader{}, - &builder.SketchSourceMerger{}, - } - - for _, command := range commands { - err := command.Run(ctx) - NoError(t, err) - } - - source := ctx.Source - - expected_source := LoadAndInterpolate(t, filepath.Join("sketch1", "merged_sketch.txt"), ctx) - require.Equal(t, expected_source, strings.Replace(source, "\r\n", "\n", -1)) -} diff --git a/legacy/builder/types/types.go b/legacy/builder/types/types.go index 1e00a37e10f..58fb6ed0a92 100644 --- a/legacy/builder/types/types.go +++ b/legacy/builder/types/types.go @@ -148,6 +148,32 @@ func SketchToLegacy(sketch *sketch.Sketch) *Sketch { return s } +func SketchFromLegacy(s *Sketch) *sketch.Sketch { + others := []*sketch.Item{} + for _, f := range s.OtherSketchFiles { + if i, err := sketch.NewItem(f.Name.String()); err == nil { + others = append(others, i) + } + } + + additional := []*sketch.Item{} + for _, f := range s.AdditionalFiles { + if i, err := sketch.NewItem(f.Name.String()); err == nil { + additional = append(additional, i) + } + } + + return &sketch.Sketch{ + MainFile: &sketch.Item{ + Path: s.MainFile.Name.String(), + Source: []byte(s.MainFile.Source), + }, + LocationPath: s.MainFile.Name.Parent().String(), + OtherSketchFiles: others, + AdditionalFiles: additional, + } +} + type PlatforKeysRewrite struct { Rewrites []PlatforKeyRewrite } From 40b8d53df98071f2d7831c8ed952d59c9184fdef Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 14:40:37 +0200 Subject: [PATCH 11/15] removed SketchSourceMerger --- .../container_merge_copy_sketch_files.go | 10 +-- legacy/builder/sketch_source_merger.go | 82 ------------------- 2 files changed, 5 insertions(+), 87 deletions(-) delete mode 100644 legacy/builder/sketch_source_merger.go diff --git a/legacy/builder/container_merge_copy_sketch_files.go b/legacy/builder/container_merge_copy_sketch_files.go index d8124a9239d..b6222fd4cd4 100644 --- a/legacy/builder/container_merge_copy_sketch_files.go +++ b/legacy/builder/container_merge_copy_sketch_files.go @@ -39,14 +39,14 @@ import ( type ContainerMergeCopySketchFiles struct{} func (s *ContainerMergeCopySketchFiles) Run(ctx *types.Context) error { - offset, source := bldr.MergeSketchSources(types.SketchFromLegacy(ctx.Sketch)) + sk := types.SketchFromLegacy(ctx.Sketch) + if sk == nil { + return i18n.WrapError("unable to convert legacy sketch to the new type") + } + offset, source := bldr.MergeSketchSources(sk) ctx.LineOffset = offset ctx.Source = source - if err := new(SketchSourceMerger).Run(ctx); err != nil { - return i18n.WrapError(err) - } - if err := bldr.SaveSketchItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()); err != nil { return i18n.WrapError(err) } diff --git a/legacy/builder/sketch_source_merger.go b/legacy/builder/sketch_source_merger.go deleted file mode 100644 index 771d3584b0a..00000000000 --- a/legacy/builder/sketch_source_merger.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of Arduino Builder. - * - * Arduino Builder is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - * - * Copyright 2015 Arduino LLC (http://www.arduino.cc/) - * Copyright 2015 Matthijs Kooijman - */ - -package builder - -import ( - "regexp" - - "github.com/arduino/arduino-cli/legacy/builder/types" - "github.com/arduino/arduino-cli/legacy/builder/utils" -) - -type SketchSourceMerger struct{} - -func (s *SketchSourceMerger) Run(ctx *types.Context) error { - sketch := ctx.Sketch - - lineOffset := 0 - includeSection := "" - if !sketchIncludesArduinoH(&sketch.MainFile) { - includeSection += "#include \n" - lineOffset++ - } - includeSection += "#line 1 " + utils.QuoteCppString(sketch.MainFile.Name.String()) + "\n" - lineOffset++ - ctx.IncludeSection = includeSection - - source := includeSection - source += addSourceWrappedWithLineDirective(&sketch.MainFile) - lineOffset += 1 - for _, file := range sketch.OtherSketchFiles { - source += addSourceWrappedWithLineDirective(&file) - } - - ctx.LineOffset = lineOffset - ctx.Source = source - - return nil -} - -func sketchIncludesArduinoH(sketch *types.SketchFile) bool { - if matched, err := regexp.MatchString("(?m)^\\s*#\\s*include\\s*[<\"]Arduino\\.h[>\"]", sketch.Source); err != nil { - panic(err) - } else { - return matched - } -} - -func addSourceWrappedWithLineDirective(sketch *types.SketchFile) string { - source := "#line 1 " + utils.QuoteCppString(sketch.Name.String()) + "\n" - source += sketch.Source - source += "\n" - - return source -} From 3d95ff4aa9d57beafc209f1387507c0ae3f61d90 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 14:43:54 +0200 Subject: [PATCH 12/15] fix error creation --- legacy/builder/container_merge_copy_sketch_files.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/legacy/builder/container_merge_copy_sketch_files.go b/legacy/builder/container_merge_copy_sketch_files.go index b6222fd4cd4..74d2eb11151 100644 --- a/legacy/builder/container_merge_copy_sketch_files.go +++ b/legacy/builder/container_merge_copy_sketch_files.go @@ -34,6 +34,7 @@ import ( "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" + "github.com/go-errors/errors" ) type ContainerMergeCopySketchFiles struct{} @@ -41,7 +42,7 @@ type ContainerMergeCopySketchFiles struct{} func (s *ContainerMergeCopySketchFiles) Run(ctx *types.Context) error { sk := types.SketchFromLegacy(ctx.Sketch) if sk == nil { - return i18n.WrapError("unable to convert legacy sketch to the new type") + return i18n.WrapError(errors.New("unable to convert legacy sketch to the new type")) } offset, source := bldr.MergeSketchSources(sk) ctx.LineOffset = offset From ae3881b517e84dc0fc6d02af1790dfc8699fa6bb Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 16:00:02 +0200 Subject: [PATCH 13/15] fix golden files accordingly to changes to the sketch merger --- legacy/builder/test/prototypes_adder_test.go | 24 +++++++++---------- legacy/builder/test/sketch1/merged_sketch.txt | 1 - .../sketch2/SketchWithIfDef.preprocessed.txt | 1 - .../SketchWithIfDef.resolved.directives.txt | 1 - .../test/sketch3/Baladuino.preprocessed.txt | 1 - ...harWithEscapedDoubleQuote.preprocessed.txt | 1 - ...deBetweenMultilineComment.preprocessed.txt | 1 - .../LineContinuations.preprocessed.txt | 1 - .../StringWithComment.preprocessed.txt | 1 - .../sketch8/SketchWithStruct.preprocessed.txt | 1 - .../sketch_with_config.preprocessed.txt | 1 - .../sketch.preprocessed.SAM.txt | 1 - .../sketch_with_ifdef/sketch.preprocessed.txt | 1 - legacy/builder/types/context.go | 1 - 14 files changed, 12 insertions(+), 25 deletions(-) diff --git a/legacy/builder/test/prototypes_adder_test.go b/legacy/builder/test/prototypes_adder_test.go index b75655102b6..814f00935a0 100644 --- a/legacy/builder/test/prototypes_adder_test.go +++ b/legacy/builder/test/prototypes_adder_test.go @@ -83,7 +83,7 @@ func TestPrototypesAdderBridgeExample(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 33 "+quotedSketchLocation+"\nvoid setup();\n#line 46 "+quotedSketchLocation+"\nvoid loop();\n#line 62 "+quotedSketchLocation+"\nvoid process(BridgeClient client);\n#line 82 "+quotedSketchLocation+"\nvoid digitalCommand(BridgeClient client);\n#line 109 "+quotedSketchLocation+"\nvoid analogCommand(BridgeClient client);\n#line 149 "+quotedSketchLocation+"\nvoid modeCommand(BridgeClient client);\n#line 33 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } @@ -411,7 +411,7 @@ func TestPrototypesAdderSketchWithConfig(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 13 "+quotedSketchLocation+"\nvoid setup();\n#line 17 "+quotedSketchLocation+"\nvoid loop();\n#line 13 "+quotedSketchLocation+"\n", ctx.PrototypesSection) preprocessed := LoadAndInterpolate(t, filepath.Join("sketch_with_config", "sketch_with_config.preprocessed.txt"), ctx) @@ -457,7 +457,7 @@ func TestPrototypesAdderSketchNoFunctionsTwoFiles(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "", ctx.PrototypesSection) } @@ -500,7 +500,7 @@ func TestPrototypesAdderSketchNoFunctions(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "", ctx.PrototypesSection) } @@ -543,7 +543,7 @@ func TestPrototypesAdderSketchWithDefaultArgs(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 4 "+quotedSketchLocation+"\nvoid setup();\n#line 7 "+quotedSketchLocation+"\nvoid loop();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } @@ -586,7 +586,7 @@ func TestPrototypesAdderSketchWithInlineFunction(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") expected := "#line 1 " + quotedSketchLocation + "\nvoid setup();\n#line 2 " + quotedSketchLocation + "\nvoid loop();\n#line 4 " + quotedSketchLocation + "\nshort unsigned int testInt();\n#line 8 " + quotedSketchLocation + "\nstatic int8_t testInline();\n#line 12 " + quotedSketchLocation + "\n__attribute__((always_inline)) uint8_t testAttribute();\n#line 1 " + quotedSketchLocation + "\n" obtained := ctx.PrototypesSection @@ -640,7 +640,7 @@ func TestPrototypesAdderSketchWithFunctionSignatureInsideIFDEF(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 1 "+quotedSketchLocation+"\nvoid setup();\n#line 3 "+quotedSketchLocation+"\nvoid loop();\n#line 15 "+quotedSketchLocation+"\nint8_t adalight();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } @@ -683,7 +683,7 @@ func TestPrototypesAdderSketchWithUSBCON(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 5 "+quotedSketchLocation+"\nvoid ciao();\n#line 10 "+quotedSketchLocation+"\nvoid setup();\n#line 15 "+quotedSketchLocation+"\nvoid loop();\n#line 5 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } @@ -725,7 +725,7 @@ func TestPrototypesAdderSketchWithTypename(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") expected := "#line 6 " + quotedSketchLocation + "\nvoid setup();\n#line 10 " + quotedSketchLocation + "\nvoid loop();\n#line 12 " + quotedSketchLocation + "\ntypename Foo::Bar func();\n#line 6 " + quotedSketchLocation + "\n" obtained := ctx.PrototypesSection // ctags based preprocessing ignores line with typename @@ -774,7 +774,7 @@ func TestPrototypesAdderSketchWithIfDef2(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 5 "+quotedSketchLocation+"\nvoid elseBranch();\n#line 9 "+quotedSketchLocation+"\nvoid f1();\n#line 10 "+quotedSketchLocation+"\nvoid f2();\n#line 12 "+quotedSketchLocation+"\nvoid setup();\n#line 14 "+quotedSketchLocation+"\nvoid loop();\n#line 5 "+quotedSketchLocation+"\n", ctx.PrototypesSection) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.txt"), ctx) @@ -820,7 +820,7 @@ func TestPrototypesAdderSketchWithIfDef2SAM(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 2 "+quotedSketchLocation+"\nvoid ifBranch();\n#line 9 "+quotedSketchLocation+"\nvoid f1();\n#line 10 "+quotedSketchLocation+"\nvoid f2();\n#line 12 "+quotedSketchLocation+"\nvoid setup();\n#line 14 "+quotedSketchLocation+"\nvoid loop();\n#line 2 "+quotedSketchLocation+"\n", ctx.PrototypesSection) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.SAM.txt"), ctx) @@ -866,7 +866,7 @@ func TestPrototypesAdderSketchWithConst(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Contains(t, ctx.Source, "#include \n#line 1 "+quotedSketchLocation+"\n") require.Equal(t, "#line 1 "+quotedSketchLocation+"\nvoid setup();\n#line 2 "+quotedSketchLocation+"\nvoid loop();\n#line 4 "+quotedSketchLocation+"\nconst __FlashStringHelper* test();\n#line 6 "+quotedSketchLocation+"\nconst int test3();\n#line 8 "+quotedSketchLocation+"\nvolatile __FlashStringHelper* test2();\n#line 10 "+quotedSketchLocation+"\nvolatile int test4();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } diff --git a/legacy/builder/test/sketch1/merged_sketch.txt b/legacy/builder/test/sketch1/merged_sketch.txt index 4654de3236c..6f21615ced6 100644 --- a/legacy/builder/test/sketch1/merged_sketch.txt +++ b/legacy/builder/test/sketch1/merged_sketch.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} void setup() { } diff --git a/legacy/builder/test/sketch2/SketchWithIfDef.preprocessed.txt b/legacy/builder/test/sketch2/SketchWithIfDef.preprocessed.txt index e0380e1725e..9d943396d6c 100644 --- a/legacy/builder/test/sketch2/SketchWithIfDef.preprocessed.txt +++ b/legacy/builder/test/sketch2/SketchWithIfDef.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #define DEBUG 1 #define DISABLED 0 diff --git a/legacy/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt b/legacy/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt index c01a6fe35d2..bf79b2f49c8 100644 --- a/legacy/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt +++ b/legacy/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #define DEBUG 1 #define DISABLED 0 diff --git a/legacy/builder/test/sketch3/Baladuino.preprocessed.txt b/legacy/builder/test/sketch3/Baladuino.preprocessed.txt index 989b6b9b4c0..238739eb902 100644 --- a/legacy/builder/test/sketch3/Baladuino.preprocessed.txt +++ b/legacy/builder/test/sketch3/Baladuino.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} /* * The code is released under the GNU General Public License. * Developed by Kristian Lauszus, TKJ Electronics 2013 diff --git a/legacy/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt b/legacy/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt index 62fa1ac6031..1f9e69a613b 100644 --- a/legacy/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt +++ b/legacy/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include // required to send and receive AT commands from the GPRS Shield #include // required for I2C communication with the RTC diff --git a/legacy/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt b/legacy/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt index a19528dcbda..076ff1b3b28 100644 --- a/legacy/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt +++ b/legacy/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include /* #include diff --git a/legacy/builder/test/sketch6/LineContinuations.preprocessed.txt b/legacy/builder/test/sketch6/LineContinuations.preprocessed.txt index 1d5845833dd..227bf26d32a 100644 --- a/legacy/builder/test/sketch6/LineContinuations.preprocessed.txt +++ b/legacy/builder/test/sketch6/LineContinuations.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} const char *foo = "\ hello \ world\n"; diff --git a/legacy/builder/test/sketch7/StringWithComment.preprocessed.txt b/legacy/builder/test/sketch7/StringWithComment.preprocessed.txt index f4432fcdcf0..2fcb13c5ea4 100644 --- a/legacy/builder/test/sketch7/StringWithComment.preprocessed.txt +++ b/legacy/builder/test/sketch7/StringWithComment.preprocessed.txt @@ -1,7 +1,6 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} void setup(); #line 10 {{QuoteCppString .sketch.MainFile.Name}} void loop(); diff --git a/legacy/builder/test/sketch8/SketchWithStruct.preprocessed.txt b/legacy/builder/test/sketch8/SketchWithStruct.preprocessed.txt index 35302e16791..4f15168af15 100644 --- a/legacy/builder/test/sketch8/SketchWithStruct.preprocessed.txt +++ b/legacy/builder/test/sketch8/SketchWithStruct.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} /* START CODE */ struct A_NEW_TYPE { diff --git a/legacy/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt b/legacy/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt index 2d56efd332c..9604504bc00 100644 --- a/legacy/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt +++ b/legacy/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include "config.h" #ifdef DEBUG diff --git a/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt b/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt index 2eb36912649..76e39303fa2 100644 --- a/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt +++ b/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #if __SAM3X8E__ #line 2 {{QuoteCppString .sketch.MainFile.Name}} void ifBranch(); diff --git a/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.txt b/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.txt index 31c86758e5f..85f2068e48c 100644 --- a/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.txt +++ b/legacy/builder/test/sketch_with_ifdef/sketch.preprocessed.txt @@ -1,6 +1,5 @@ #include #line 1 {{QuoteCppString .sketch.MainFile.Name}} -#line 1 {{QuoteCppString .sketch.MainFile.Name}} #if __SAM3X8E__ void ifBranch() { } diff --git a/legacy/builder/types/context.go b/legacy/builder/types/context.go index 5208ce92640..c1cfadfbb31 100644 --- a/legacy/builder/types/context.go +++ b/legacy/builder/types/context.go @@ -86,7 +86,6 @@ type Context struct { CTagsOutput string CTagsTargetFile *paths.Path CTagsOfPreprocessedSource []*CTag - IncludeSection string LineOffset int PrototypesSection string PrototypesLineWhereToInsert int From 3656f477be25e7fc62e1e9ea736d8ca1af7a8b53 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 8 Jul 2019 16:51:32 +0200 Subject: [PATCH 14/15] fix regex and add test --- arduino/builder/sketch.go | 2 +- arduino/builder/sketch_test.go | 11 +++++++++++ .../TestMergeSketchSourcesArduinoIncluded.ino | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 arduino/builder/testdata/TestMergeSketchSourcesArduinoIncluded/TestMergeSketchSourcesArduinoIncluded.ino diff --git a/arduino/builder/sketch.go b/arduino/builder/sketch.go index b1c1f1ec3e4..cccffcf5608 100644 --- a/arduino/builder/sketch.go +++ b/arduino/builder/sketch.go @@ -28,7 +28,7 @@ import ( "github.com/pkg/errors" ) -var includesArduinoH = regexp.MustCompile(`^\s*#\s*include\s*[<\"]Arduino\.h[>\"]`) +var includesArduinoH = regexp.MustCompile(`(?m)^\s*#\s*include\s*[<\"]Arduino\.h[>\"]`) // QuoteCppString returns the given string as a quoted string for use with the C // preprocessor. This adds double quotes around it and escapes any diff --git a/arduino/builder/sketch_test.go b/arduino/builder/sketch_test.go index 6fd099f6a8c..356c34435f2 100644 --- a/arduino/builder/sketch_test.go +++ b/arduino/builder/sketch_test.go @@ -19,6 +19,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "github.com/arduino/arduino-cli/arduino/builder" @@ -107,3 +108,13 @@ func TestMergeSketchSources(t *testing.T) { assert.Equal(t, 2, offset) assert.Equal(t, string(mergedBytes), source) } + +func TestMergeSketchSourcesArduinoIncluded(t *testing.T) { + s, err := builder.LoadSketch(filepath.Join("testdata", t.Name()), "") + assert.Nil(t, err) + assert.NotNil(t, s) + + // ensure not to include Arduino.h when it's already there + _, source := builder.MergeSketchSources(s) + assert.Equal(t, 1, strings.Count(source, "")) +} diff --git a/arduino/builder/testdata/TestMergeSketchSourcesArduinoIncluded/TestMergeSketchSourcesArduinoIncluded.ino b/arduino/builder/testdata/TestMergeSketchSourcesArduinoIncluded/TestMergeSketchSourcesArduinoIncluded.ino new file mode 100644 index 00000000000..d913e6cd174 --- /dev/null +++ b/arduino/builder/testdata/TestMergeSketchSourcesArduinoIncluded/TestMergeSketchSourcesArduinoIncluded.ino @@ -0,0 +1,9 @@ +// a comment + + # include + +void setup() { +} + +void loop() { +} From 5f5823a123052c729c9a15af5ec5ff8f6b372301 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Tue, 9 Jul 2019 16:38:34 +0200 Subject: [PATCH 15/15] remove misleading define --- arduino/builder/testdata/TestLoadSketchFolder/header.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino/builder/testdata/TestLoadSketchFolder/header.h b/arduino/builder/testdata/TestLoadSketchFolder/header.h index 2e24536f9fb..0e7d3b1a6a9 100644 --- a/arduino/builder/testdata/TestLoadSketchFolder/header.h +++ b/arduino/builder/testdata/TestLoadSketchFolder/header.h @@ -1 +1 @@ -#define TRUE FALSE \ No newline at end of file +#define FOO "BAR" \ No newline at end of file