diff --git a/src/arduino.cc/builder/ctags/ctags_parser.go b/src/arduino.cc/builder/ctags/ctags_parser.go index 55497155..318c679b 100644 --- a/src/arduino.cc/builder/ctags/ctags_parser.go +++ b/src/arduino.cc/builder/ctags/ctags_parser.go @@ -130,7 +130,7 @@ func removeDuplicate(tags []*types.CTag) { definedPrototypes := make(map[string]bool) for _, tag := range tags { - if !definedPrototypes[tag.Prototype] { + if !definedPrototypes[tag.Prototype] && tag.SkipMe == false { definedPrototypes[tag.Prototype] = true } else { tag.SkipMe = true diff --git a/src/arduino.cc/builder/ctags_target_file_saver.go b/src/arduino.cc/builder/ctags_target_file_saver.go index 0f3277ca..5df0d40d 100644 --- a/src/arduino.cc/builder/ctags_target_file_saver.go +++ b/src/arduino.cc/builder/ctags_target_file_saver.go @@ -34,6 +34,8 @@ import ( "arduino.cc/builder/types" "arduino.cc/builder/utils" "path/filepath" + "strconv" + "strings" ) type CTagsTargetFileSaver struct { @@ -50,6 +52,12 @@ func (s *CTagsTargetFileSaver) Run(ctx *types.Context) error { return i18n.WrapError(err) } + // drop every line which is not part of user sketch or a define/ifdef/endif/etc + var searchSlice []string + searchSlice = append(searchSlice, filepath.Dir(ctx.SketchLocation)) + searchSlice = append(searchSlice, filepath.Dir(ctx.BuildPath)) + source = saveLinesContainingDirectivesAndSketch(source, searchSlice) + ctagsTargetFilePath := filepath.Join(preprocPath, s.TargetFileName) err = utils.WriteFile(ctagsTargetFilePath, source) if err != nil { @@ -60,3 +68,52 @@ func (s *CTagsTargetFileSaver) Run(ctx *types.Context) error { return nil } + +func saveLinesContainingDirectivesAndSketch(src string, tofind []string) string { + lines := strings.Split(src, "\n") + + saveLine := false + minimizedString := "" + + for _, line := range lines { + if saveLine || startsWithHashtag(line) { + minimizedString += line + "\n" + } + if containsAny(line, tofind) && isLineMarker(line) { + saveLine = true + } + if saveLine && !containsAny(line, tofind) && isLineMarker(line) { + saveLine = false + } + } + return minimizedString +} + +func containsAny(src string, tofind []string) bool { + for _, str := range tofind { + if strings.Contains(src, str) { + return true + } + } + return false +} + +func startsWithHashtag(src string) bool { + trimmedStr := strings.TrimSpace(src) + if len(trimmedStr) > 0 && trimmedStr[0] == '#' { + return true + } + return false +} + +func isLineMarker(src string) bool { + trimmedStr := strings.TrimSpace(src) + splittedStr := strings.Split(trimmedStr, " ") + if len(splittedStr) > 2 && splittedStr[0][0] == '#' { + _, err := strconv.Atoi(splittedStr[1]) + if err == nil { + return true + } + } + return false +} diff --git a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go index ca1a2a6b..55dd7abe 100644 --- a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go +++ b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go @@ -30,10 +30,13 @@ package test import ( + "arduino.cc/builder" + "arduino.cc/builder/constants" "arduino.cc/builder/ctags" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "io/ioutil" + "os" "path/filepath" "testing" ) @@ -459,3 +462,52 @@ func TestCTagsToPrototypesFunctionPointers(t *testing.T) { require.Equal(t, 2, ctx.PrototypesLineWhereToInsert) } + +func TestCTagsRunnerSketchWithClassFunction(t *testing.T) { + DownloadCoresAndToolsAndLibraries(t) + + sketchLocation := Abs(t, filepath.Join("sketch_with_class", "sketch_class_function.ino")) + + ctx := &types.Context{ + HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, + ToolsFolders: []string{"downloaded_tools"}, + BuiltInLibrariesFolders: []string{"downloaded_libraries"}, + OtherLibrariesFolders: []string{"libraries"}, + SketchLocation: sketchLocation, + FQBN: "arduino:avr:leonardo", + ArduinoAPIVersion: "10600", + Verbose: true, + } + + buildPath := SetupBuildPath(t, ctx) + defer os.RemoveAll(buildPath) + + commands := []types.Command{ + + &builder.ContainerSetupHardwareToolsLibsSketchAndProps{}, + + &builder.ContainerMergeCopySketchFiles{}, + + &builder.ContainerFindIncludes{}, + + &builder.PrintUsedLibrariesIfVerbose{}, + &builder.WarnAboutArchIncompatibleLibraries{}, + &builder.CTagsTargetFileSaver{Source: &ctx.Source, TargetFileName: constants.FILE_CTAGS_TARGET}, + &ctags.CTagsRunner{}, + &ctags.CTagsParser{}, + &CollectCtagsFromPreprocSource{}, + &ctags.CTagsToPrototypes{}, + } + + for _, command := range commands { + err := command.Run(ctx) + NoError(t, err) + } + + prototypes := ctx.Prototypes + + require.Equal(t, 3, len(prototypes)) + require.Equal(t, "void setup();", prototypes[0].Prototype) + require.Equal(t, "void loop();", prototypes[1].Prototype) + require.Equal(t, "void asdf();", prototypes[2].Prototype) +} diff --git a/src/arduino.cc/builder/test/sketch_with_class/sketch_class_function.ino b/src/arduino.cc/builder/test/sketch_with_class/sketch_class_function.ino new file mode 100644 index 00000000..45250090 --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_class/sketch_class_function.ino @@ -0,0 +1,8 @@ +class test { + void asdf() {} +}; +void setup() { + asdf(); +} +void loop() {} +void asdf() {} \ No newline at end of file