From 43d412aadc51d50943e4d2d036d0561590154854 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 4 May 2016 11:33:41 +0200 Subject: [PATCH] Fix duplicate-skipping in prototype generation While generating prototypes, a scan is made for any function definitions which would result in identical prototypes, and all but the first are skipped. However, when doing so, this did not take into account function definitions which were already marked to be skipped, which could cause *all* definitions to be skipped. This behaviour caused a particular problem when a method definition existed with the same signature as a function definition. All method definitions are skipped through `tagIsUnhandled`, but could still make `skipDuplicates` skip the corresponding function definition. This commit fixes this. It is not entirely clear to me if this duplicate removal is actually needed at all. If code contains multiple function definitions with the same signature, you would expect the compiler to throw an error anyway. If duplicate removal would be removed, only one testcase (TestCTagsToPrototypesShouldDealFunctionWithDifferentSignatures) fails, but that testcase uses a predefined ctags output that contains a duplicate function definition. It is not quite clear what source files this output was generated from (it seems to stem from CharWithEscapedDoubleQuote.ino, which originated at https://github.com/arduino/Arduino/issues/1245, but those only contain one version of the function definition, not two). Still, since the ctags parsing will hopefully be replaced in the near future, this just fixes the duplicate removal instead of removing it and risking a regression on some corner case. This fixes #140. Signed-off-by: Martino Facchin Signed-off-by: Matthijs Kooijman --- src/arduino.cc/builder/ctags/ctags_parser.go | 2 +- .../builder/test/ctags_to_prototypes_test.go | 52 +++++++++++++++++++ .../sketch_class_function.ino | 8 +++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/arduino.cc/builder/test/sketch_class_function/sketch_class_function.ino 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/test/ctags_to_prototypes_test.go b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go index ca1a2a6b..c83f8afc 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_class_function", "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_class_function/sketch_class_function.ino b/src/arduino.cc/builder/test/sketch_class_function/sketch_class_function.ino new file mode 100644 index 00000000..45250090 --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_class_function/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