diff --git a/.prettierignore b/.prettierignore index 3b34afa1ed6..6aabe7366cb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,6 +4,7 @@ .vs/ .ionide/ +testdata /arduino/libraries/librariesindex/testdata/invalid.json /arduino/security/testdata/ /.licenses/ diff --git a/arduino/builder/builder.go b/arduino/builder/builder.go index 51646bdcf48..c24bac47011 100644 --- a/arduino/builder/builder.go +++ b/arduino/builder/builder.go @@ -25,6 +25,7 @@ import ( "github.com/arduino/arduino-cli/arduino/builder/internal/compilation" "github.com/arduino/arduino-cli/arduino/builder/internal/detector" + "github.com/arduino/arduino-cli/arduino/builder/internal/diagnostics" "github.com/arduino/arduino-cli/arduino/builder/internal/logger" "github.com/arduino/arduino-cli/arduino/builder/internal/progress" "github.com/arduino/arduino-cli/arduino/builder/internal/utils" @@ -36,6 +37,7 @@ import ( rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/go-paths-helper" "github.com/arduino/go-properties-orderedmap" + "github.com/sirupsen/logrus" ) // ErrSketchCannotBeLocatedInBuildPath fixdoc @@ -90,6 +92,12 @@ type Builder struct { buildOptions *buildOptions libsDetector *detector.SketchLibrariesDetector + + // This is a function used to parse the output of the compiler + // It is used to extract errors and warnings + compilerOutputParser diagnostics.CompilerOutputParserCB + // and here are the diagnostics parsed from the compiler + compilerDiagnostics diagnostics.Diagnostics } // buildArtifacts contains the result of various build @@ -189,7 +197,7 @@ func NewBuilder( logger.Warn(string(verboseOut)) } - return &Builder{ + b := &Builder{ sketch: sk, buildProperties: buildProperties, buildPath: buildPath, @@ -226,7 +234,26 @@ func NewBuilder( buildProperties.GetPath("runtime.platform.path"), buildProperties.GetPath("build.core.path"), // TODO can we buildCorePath ? ), - }, nil + } + + b.compilerOutputParser = func(cmdline []string, out []byte) { + compiler := diagnostics.DetectCompilerFromCommandLine( + cmdline, + false, // at the moment compiler-probing is not required + ) + if compiler == nil { + logrus.Warnf("Could not detect compiler from: %s", cmdline) + return + } + diags, err := diagnostics.ParseCompilerOutput(compiler, out) + if err != nil { + logrus.Warnf("Error parsing compiler output: %s", err) + return + } + b.compilerDiagnostics = append(b.compilerDiagnostics, diags...) + } + + return b, nil } // GetBuildProperties returns the build properties for running this build @@ -249,6 +276,11 @@ func (b *Builder) ImportedLibraries() libraries.List { return b.libsDetector.ImportedLibraries() } +// CompilerDiagnostics returns the parsed compiler diagnostics +func (b *Builder) CompilerDiagnostics() diagnostics.Diagnostics { + return b.compilerDiagnostics +} + // Preprocess fixdoc func (b *Builder) Preprocess() ([]byte, error) { b.Progress.AddSubSteps(6) diff --git a/arduino/builder/compilation.go b/arduino/builder/compilation.go index e3c70900bf6..0d91f622579 100644 --- a/arduino/builder/compilation.go +++ b/arduino/builder/compilation.go @@ -166,6 +166,12 @@ func (b *Builder) compileFileWithRecipe( } b.logger.WriteStderr(commandStderr.Bytes()) + // Parse the output of the compiler to gather errors and warnings... + if b.compilerOutputParser != nil { + b.compilerOutputParser(command.GetArgs(), commandStdout.Bytes()) + b.compilerOutputParser(command.GetArgs(), commandStderr.Bytes()) + } + // ...and then return the error if err != nil { return nil, errors.WithStack(err) diff --git a/arduino/builder/internal/diagnostics/compiler_detection.go b/arduino/builder/internal/diagnostics/compiler_detection.go new file mode 100644 index 00000000000..53b83a52bc1 --- /dev/null +++ b/arduino/builder/internal/diagnostics/compiler_detection.go @@ -0,0 +1,85 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 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 diagnostics + +import ( + "bytes" + "path/filepath" + "strings" + + "github.com/arduino/arduino-cli/executils" + semver "go.bug.st/relaxed-semver" +) + +// DetectedCompiler represents a compiler detected from a given command line +type DetectedCompiler struct { + Name string + Family string + Version *semver.Version + DetailedVersion []string +} + +// This function is overridden for mocking unit tests +var runProcess = func(args ...string) []string { + if cmd, err := executils.NewProcess(nil, args...); err == nil { + out := &bytes.Buffer{} + cmd.RedirectStdoutTo(out) + cmd.Run() + return splitLines(out.Bytes()) + } + return nil +} + +// DetectCompilerFromCommandLine tries to detect a compiler from a given command line. +// If probeCompiler is true, the compiler may be executed with different flags to +// infer the version or capabilities. +func DetectCompilerFromCommandLine(args []string, probeCompiler bool) *DetectedCompiler { + if len(args) == 0 { + return nil + } + basename := filepath.Base(args[0]) + family := "" + if strings.Contains(basename, "g++") || strings.Contains(basename, "gcc") { + family = "gcc" + } + res := &DetectedCompiler{ + Name: basename, + Family: family, + } + + if family == "gcc" && probeCompiler { + // Run "gcc --version" to obtain more info + res.DetailedVersion = runProcess(args[0], "--version") + + // Usually on the first line we get the compiler architecture and + // version (as last field), followed by the compiler license, for + // example: + // + // g++ (Ubuntu 12.2.0-3ubuntu1) 12.2.0 + // Copyright (C) 2022 Free Software Foundation, Inc. + // This is free software; see the source for copying conditions. There is NO + // warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + // + if len(res.DetailedVersion) > 0 { + split := strings.Split(res.DetailedVersion[0], " ") + if len(split) >= 3 { + res.Name = split[0] + res.Version, _ = semver.Parse(split[len(split)-1]) + } + } + } + return res +} diff --git a/arduino/builder/internal/diagnostics/compiler_detection_test.go b/arduino/builder/internal/diagnostics/compiler_detection_test.go new file mode 100644 index 00000000000..024c66868ed --- /dev/null +++ b/arduino/builder/internal/diagnostics/compiler_detection_test.go @@ -0,0 +1,79 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 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 diagnostics + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func init() { + runProcess = mockedRunProcessToGetCompilerVersion +} + +func mockedRunProcessToGetCompilerVersion(args ...string) []string { + if strings.HasSuffix(args[0], "7.3.0-atmel3.6.1-arduino7/bin/avr-g++") && args[1] == "--version" { + return []string{ + "avr-g++ (GCC) 7.3.0", + "Copyright (C) 2017 Free Software Foundation, Inc.", + "This is free software; see the source for copying conditions. There is NO", + "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.", + "", + } + } + if strings.HasSuffix(args[0], "7.3.0-atmel3.6.1-arduino7/bin/avr-gcc") && args[1] == "--version" { + return []string{ + "avr-gcc (GCC) 7.3.0", + "Copyright (C) 2017 Free Software Foundation, Inc.", + "This is free software; see the source for copying conditions. There is NO", + "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.", + "", + } + } + if strings.HasSuffix(args[0], "xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/xtensa-esp32-elf-g++") && args[1] == "--version" { + return []string{ + "xtensa-esp32-elf-g++ (crosstool-NG esp-2021r2-patch3) 8.4.0", + "Copyright (C) 2018 Free Software Foundation, Inc.", + "This is free software; see the source for copying conditions. There is NO", + "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.", + "", + } + } + + panic("missing mock for command line: " + strings.Join(args, " ")) +} + +func TestCompilerDetection(t *testing.T) { + comp := DetectCompilerFromCommandLine([]string{"~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++"}, true) + require.NotNil(t, comp) + require.Equal(t, "gcc", comp.Family) + require.Equal(t, "avr-g++", comp.Name) + require.Equal(t, "7.3.0", comp.Version.String()) + + comp = DetectCompilerFromCommandLine([]string{"~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc"}, true) + require.NotNil(t, comp) + require.Equal(t, "gcc", comp.Family) + require.Equal(t, "avr-gcc", comp.Name) + require.Equal(t, "7.3.0", comp.Version.String()) + + comp = DetectCompilerFromCommandLine([]string{"/home/megabug/.arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/xtensa-esp32-elf-g++"}, true) + require.NotNil(t, comp) + require.Equal(t, "gcc", comp.Family) + require.Equal(t, "xtensa-esp32-elf-g++", comp.Name) + require.Equal(t, "8.4.0", comp.Version.String()) +} diff --git a/arduino/builder/internal/diagnostics/parser.go b/arduino/builder/internal/diagnostics/parser.go new file mode 100644 index 00000000000..5aafaa5072d --- /dev/null +++ b/arduino/builder/internal/diagnostics/parser.go @@ -0,0 +1,173 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 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 diagnostics + +import ( + "fmt" + "strings" + + rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" +) + +// CompilerOutputParserCB is a callback function that is called to feed a parser +// with the plain-text compiler output. +type CompilerOutputParserCB func(cmdline []string, out []byte) + +// Diagnostics represents a list of diagnostics +type Diagnostics []*Diagnostic + +// Diagnostic represents a diagnostic (a compiler error, warning, note, etc.) +type Diagnostic struct { + Severity Severity `json:"severity,omitempty"` + Message string `json:"message"` + File string `json:"file,omitempty"` + Line int `json:"line,omitempty"` + Column int `json:"col,omitempty"` + Context FullContext `json:"context,omitempty"` + Suggestions Notes `json:"suggestions,omitempty"` +} + +// Severity is a diagnostic severity +type Severity string + +const ( + // SeverityUnspecified is the undefined severity + SeverityUnspecified Severity = "" + // SeverityWarning is a warning + SeverityWarning = "WARNING" + // SeverityError is an error + SeverityError = "ERROR" + // SeverityFatal is a fatal error + SeverityFatal = "FATAL" +) + +// Notes represents a list of Note +type Notes []*Note + +// Note represents a compiler annotation or suggestion +type Note struct { + Message string `json:"message"` + File string `json:"file,omitempty"` + Line int `json:"line,omitempty"` + Column int `json:"col,omitempty"` +} + +// FullContext represents a list of Context +type FullContext []*Context + +// Context represents a context, i.e. a reference to a file, line and column +// or a part of the code that a Diagnostic refers to. +type Context struct { + Message string `json:"message"` + File string `json:"file,omitempty"` + Line int `json:"line,omitempty"` + Column int `json:"col,omitempty"` +} + +// ParseCompilerOutput parses the output of a compiler and returns a list of +// diagnostics. +func ParseCompilerOutput(compiler *DetectedCompiler, out []byte) ([]*Diagnostic, error) { + lines := splitLines(out) + switch compiler.Family { + case "gcc": + return parseGccOutput(lines) + default: + return nil, fmt.Errorf("unsupported compiler: %s", compiler) + } +} + +func splitLines(in []byte) []string { + res := strings.Split(string(in), "\n") + for i, line := range res { + res[i] = strings.TrimSuffix(line, "\r") + } + if l := len(res) - 1; res[l] == "" { + res = res[:l] + } + return res +} + +// ToRPC converts a Diagnostics to a slice of rpc.CompileDiagnostic +func (d Diagnostics) ToRPC() []*rpc.CompileDiagnostic { + if len(d) == 0 { + return nil + } + var res []*rpc.CompileDiagnostic + for _, diag := range d { + res = append(res, diag.ToRPC()) + } + return res +} + +// ToRPC converts a Diagnostic to a rpc.CompileDiagnostic +func (d *Diagnostic) ToRPC() *rpc.CompileDiagnostic { + if d == nil { + return nil + } + return &rpc.CompileDiagnostic{ + Severity: string(d.Severity), + Message: d.Message, + File: d.File, + Line: int64(d.Line), + Column: int64(d.Column), + Context: d.Context.ToRPC(), + Notes: d.Suggestions.ToRPC(), + } +} + +// ToRPC converts a Notes to a slice of rpc.CompileDiagnosticNote +func (s Notes) ToRPC() []*rpc.CompileDiagnosticNote { + var res []*rpc.CompileDiagnosticNote + for _, suggestion := range s { + res = append(res, suggestion.ToRPC()) + } + return res +} + +// ToRPC converts a Note to a rpc.CompileDiagnosticNote +func (s *Note) ToRPC() *rpc.CompileDiagnosticNote { + if s == nil { + return nil + } + return &rpc.CompileDiagnosticNote{ + File: s.File, + Line: int64(s.Line), + Column: int64(s.Column), + Message: s.Message, + } +} + +// ToRPC converts a FullContext to a slice of rpc.CompileDiagnosticContext +func (t FullContext) ToRPC() []*rpc.CompileDiagnosticContext { + var res []*rpc.CompileDiagnosticContext + for _, trace := range t { + res = append(res, trace.ToRPC()) + } + return res +} + +// ToRPC converts a Context to a rpc.CompileDiagnosticContext +func (d *Context) ToRPC() *rpc.CompileDiagnosticContext { + if d == nil { + return nil + } + return &rpc.CompileDiagnosticContext{ + File: d.File, + Line: int64(d.Line), + Column: int64(d.Column), + Message: d.Message, + } +} diff --git a/arduino/builder/internal/diagnostics/parser_gcc.go b/arduino/builder/internal/diagnostics/parser_gcc.go new file mode 100644 index 00000000000..afc9ef40c41 --- /dev/null +++ b/arduino/builder/internal/diagnostics/parser_gcc.go @@ -0,0 +1,193 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 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 diagnostics + +import ( + "strconv" + "strings" +) + +// Parse output from gcc compiler and extract diagnostics +func parseGccOutput(output []string) ([]*Diagnostic, error) { + // Output from gcc is a mix of diagnostics and other information. + // + // 1. include trace lines: + // + // In file included from /home/megabug/Arduino/libraries/Audio/src/Audio.h:16:0, + // ·················from /home/megabug/Arduino/Blink/Blink.ino:1: + // + // 2. in-file context lines: + // + // /home/megabug/Arduino/libraries/Audio/src/DAC.h: In member function 'void DACClass::enableInterrupts()': + // + // 3. actual diagnostic lines: + // + // /home/megabug/Arduino/libraries/Audio/src/DAC.h:31:44: fatal error: 'isrId' was not declared in this scope + // + // /home/megabug/Arduino/libraries/Audio/src/DAC.h:31:44: error: 'isrId' was not declared in this scope + // + // /home/megabug/Arduino/libraries/Audio/src/DAC.h:31:44: warning: 'isrId' was not declared in this scope + // + // 4. annotations or suggestions: + // + // /home/megabug/Arduino/Blink/Blink.ino:4:1: note: suggested alternative: 'rand' + // + // 5. extra context lines with an extract of the code that errors refers to: + // + // ·asd; + // ·^~~ + // ·rand + // + // ·void enableInterrupts() { NVIC_EnableIRQ(isrId); }; + // ···········································^~~~~ + + var fullContext FullContext + var fullContextRefersTo string + var inFileContext *Context + var currentDiagnostic *Diagnostic + var currentMessage *string + var res []*Diagnostic + + for _, in := range output { + isTrace := false + if strings.HasPrefix(in, "In file included from ") { + in = strings.TrimPrefix(in, "In file included from ") + // 1. include trace + isTrace = true + inFileContext = nil + fullContext = nil + fullContextRefersTo = "" + } else if strings.HasPrefix(in, " from ") { + in = strings.TrimPrefix(in, " from ") + // 1. include trace continuation + isTrace = true + } + if isTrace { + in = strings.TrimSuffix(in, ",") + file, line, col := extractFileLineAndColumn(in) + context := &Context{ + File: file, + Line: line, + Column: col, + Message: "included from here", + } + currentMessage = &context.Message + fullContext = append(fullContext, context) + continue + } + + if split := strings.SplitN(in, ": ", 2); len(split) == 2 { + file, line, column := extractFileLineAndColumn(split[0]) + msg := split[1] + + if line == 0 && column == 0 { + // 2. in-file context + inFileContext = &Context{ + Message: msg, + File: file, + } + currentMessage = &inFileContext.Message + continue + } + + if strings.HasPrefix(msg, "note: ") { + msg = strings.TrimPrefix(msg, "note: ") + // 4. annotations or suggestions + if currentDiagnostic != nil { + suggestion := &Note{ + Message: msg, + File: file, + Line: line, + Column: column, + } + currentDiagnostic.Suggestions = append(currentDiagnostic.Suggestions, suggestion) + currentMessage = &suggestion.Message + } + continue + } + + severity := SeverityUnspecified + if strings.HasPrefix(msg, "error: ") { + msg = strings.TrimPrefix(msg, "error: ") + severity = SeverityError + } else if strings.HasPrefix(msg, "warning: ") { + msg = strings.TrimPrefix(msg, "warning: ") + severity = SeverityWarning + } else if strings.HasPrefix(msg, "fatal error: ") { + msg = strings.TrimPrefix(msg, "fatal error: ") + severity = SeverityFatal + } + if severity != SeverityUnspecified { + // 3. actual diagnostic lines + currentDiagnostic = &Diagnostic{ + Severity: severity, + Message: msg, + File: file, + Line: line, + Column: column, + } + currentMessage = ¤tDiagnostic.Message + + if len(fullContext) > 0 { + if fullContextRefersTo == "" || fullContextRefersTo == file { + fullContextRefersTo = file + currentDiagnostic.Context = append(currentDiagnostic.Context, fullContext...) + } + } + if inFileContext != nil && inFileContext.File == file { + currentDiagnostic.Context = append(currentDiagnostic.Context, inFileContext) + } + + res = append(res, currentDiagnostic) + continue + } + } + + // 5. extra context lines + if strings.HasPrefix(in, " ") { + if currentMessage != nil { + *currentMessage += "\n" + in + } + continue + } + } + return res, nil +} + +func extractFileLineAndColumn(file string) (string, int, int) { + split := strings.Split(file, ":") + file = split[0] + if len(split) == 1 { + return file, 0, 0 + } + + // Special case: handle Windows drive letter `C:\...` + if len(split) > 1 && len(file) == 1 && strings.HasPrefix(split[1], `\`) { + file += ":" + split[1] + split = split[1:] + + if len(split) == 1 { + return file, 0, 0 + } + } + + line, err := strconv.Atoi(split[1]) + if err != nil || len(split) == 2 { + return file, line, 0 + } + column, _ := strconv.Atoi(split[2]) + return file, line, column +} diff --git a/arduino/builder/internal/diagnostics/parser_test.go b/arduino/builder/internal/diagnostics/parser_test.go new file mode 100644 index 00000000000..fe2b6cbed53 --- /dev/null +++ b/arduino/builder/internal/diagnostics/parser_test.go @@ -0,0 +1,57 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 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 diagnostics + +import ( + "bytes" + "encoding/json" + "strings" + "testing" + + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" +) + +func TestParser(t *testing.T) { + t.Run("Generic001", func(t *testing.T) { runParserTest(t, "test001.txt") }) + t.Run("Generic002", func(t *testing.T) { runParserTest(t, "test002.txt") }) + t.Run("Generic003", func(t *testing.T) { runParserTest(t, "test003.txt") }) + t.Run("Generic004", func(t *testing.T) { runParserTest(t, "test004.txt") }) +} + +func runParserTest(t *testing.T, testFile string) { + testData, err := paths.New("testdata", "compiler_outputs", testFile).ReadFile() + require.NoError(t, err) + // The first line contains the compiler arguments + idx := bytes.Index(testData, []byte("\n")) + require.NotEqual(t, -1, idx) + args := strings.Split(string(testData[0:idx]), " ") + // The remainder of the file is the compiler output + data := testData[idx:] + + // Run compiler detection and parse compiler output + detectedCompiler := DetectCompilerFromCommandLine(args, true) + require.NotNil(t, detectedCompiler) + diags, err := ParseCompilerOutput(detectedCompiler, data) + require.NoError(t, err) + + // Check if the parsed data match the expected output + output, err := json.MarshalIndent(diags, "", " ") + require.NoError(t, err) + golden, err := paths.New("testdata", "compiler_outputs", testFile+".json").ReadFile() + require.NoError(t, err) + require.Equal(t, string(golden), string(output)) +} diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt new file mode 100644 index 00000000000..a04874cd03c --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt @@ -0,0 +1,12 @@ +/home/megabug/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_LEONARDO -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x8036 "-DUSB_MANUFACTURER=\"Unknown\"" "-DUSB_PRODUCT=\"Arduino Leonardo\"" -I/home/megabug/.arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/home/megabug/.arduino15/packages/arduino/hardware/avr/1.8.6/variants/leonardo /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp -o /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp.o +/home/megabug/Arduino/Blink/Blink.ino:1:14: error: expected initializer before 'asd' + void setup() asd { + ^~~ +/home/megabug/Arduino/Blink/Blink.ino: In function 'void loop()': +/home/megabug/Arduino/Blink/Blink.ino:6:1: error: 'asd' was not declared in this scope + asd + ^~~ +/home/megabug/Arduino/Blink/Blink.ino:6:1: note: suggested alternative: 'rand' + asd + ^~~ + rand \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt.json b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt.json new file mode 100644 index 00000000000..e1fd65d270d --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test001.txt.json @@ -0,0 +1,30 @@ +[ + { + "severity": "ERROR", + "message": "expected initializer before 'asd'\n void setup() asd {\n ^~~", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1, + "col": 14 + }, + { + "severity": "ERROR", + "message": "'asd' was not declared in this scope\n asd\n ^~~", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 6, + "col": 1, + "context": [ + { + "message": "In function 'void loop()':", + "file": "/home/megabug/Arduino/Blink/Blink.ino" + } + ], + "suggestions": [ + { + "message": "suggested alternative: 'rand'\n asd\n ^~~\n rand", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 6, + "col": 1 + } + ] + } +] \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt new file mode 100644 index 00000000000..c0add91431e --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt @@ -0,0 +1,34 @@ +/home/megabug/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -I/home/megabug/.arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/home/megabug/.arduino15/packages/arduino/hardware/avr/1.8.6/variants/standard -I/home/megabug/Arduino/libraries/Audio/src /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp -o /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp.o +In file included from /home/megabug/Arduino/libraries/Audio/src/Audio.h:16:0, + from /home/megabug/Arduino/Blink/Blink.ino:1: +/home/megabug/Arduino/libraries/Audio/src/DAC.h:21:16: error: expected ')' before '*' token + DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) : + ^ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:35:2: error: 'Dacc' does not name a type + Dacc *dac; + ^~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:37:2: error: 'IRQn_Type' does not name a type + IRQn_Type isrId; + ^~~~~~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h: In member function 'void DACClass::enableInterrupts()': +/home/megabug/Arduino/libraries/Audio/src/DAC.h:31:44: error: 'isrId' was not declared in this scope + void enableInterrupts() { NVIC_EnableIRQ(isrId); }; + ^~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:31:29: error: 'NVIC_EnableIRQ' was not declared in this scope + void enableInterrupts() { NVIC_EnableIRQ(isrId); }; + ^~~~~~~~~~~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h: In member function 'void DACClass::disableInterrupts()': +/home/megabug/Arduino/libraries/Audio/src/DAC.h:32:45: error: 'isrId' was not declared in this scope + void disableInterrupts() { NVIC_DisableIRQ(isrId); }; + ^~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:32:29: error: 'NVIC_DisableIRQ' was not declared in this scope + void disableInterrupts() { NVIC_DisableIRQ(isrId); }; + ^~~~~~~~~~~~~~~ +/home/megabug/Arduino/Blink/Blink.ino: In function 'void setup()': +/home/megabug/Arduino/Blink/Blink.ino:4:1: error: 'asd' was not declared in this scope + asd; + ^~~ +/home/megabug/Arduino/Blink/Blink.ino:4:1: note: suggested alternative: 'rand' + asd; + ^~~ + rand \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt.json b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt.json new file mode 100644 index 00000000000..cd1a4c402a5 --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test002.txt.json @@ -0,0 +1,172 @@ +[ + { + "severity": "ERROR", + "message": "expected ')' before '*' token\n DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) :\n ^", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 21, + "col": 16, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'Dacc' does not name a type\n Dacc *dac;\n ^~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 35, + "col": 2, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'IRQn_Type' does not name a type\n IRQn_Type isrId;\n ^~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 37, + "col": 2, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'isrId' was not declared in this scope\n void enableInterrupts() { NVIC_EnableIRQ(isrId); };\n ^~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 31, + "col": 44, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::enableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'NVIC_EnableIRQ' was not declared in this scope\n void enableInterrupts() { NVIC_EnableIRQ(isrId); };\n ^~~~~~~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 31, + "col": 29, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::enableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'isrId' was not declared in this scope\n void disableInterrupts() { NVIC_DisableIRQ(isrId); };\n ^~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 32, + "col": 45, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::disableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'NVIC_DisableIRQ' was not declared in this scope\n void disableInterrupts() { NVIC_DisableIRQ(isrId); };\n ^~~~~~~~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 32, + "col": 29, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::disableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'asd' was not declared in this scope\n asd;\n ^~~", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 4, + "col": 1, + "context": [ + { + "message": "In function 'void setup()':", + "file": "/home/megabug/Arduino/Blink/Blink.ino" + } + ], + "suggestions": [ + { + "message": "suggested alternative: 'rand'\n asd;\n ^~~\n rand", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 4, + "col": 1 + } + ] + } +] \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt new file mode 100644 index 00000000000..1b8af0f22d6 --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt @@ -0,0 +1,40 @@ +/home/megabug/.arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/xtensa-esp32-elf-g++ -DHAVE_CONFIG_H "-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\"" -DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX -D_GNU_SOURCE "-DIDF_VER=\"v4.4.1-1-gb8050b365e\"" -DESP_PLATFORM -D_POSIX_READER_WRITER_LOCKS -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/config -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/newlib/platform_include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/freertos/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/freertos/include/esp_additions/freertos -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/freertos/port/xtensa/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/freertos/include/esp_additions -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hw_support/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hw_support/include/soc -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hw_support/include/soc/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hw_support/port/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hw_support/port/esp32/private_include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/heap/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/log/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/lwip/include/apps -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/lwip/include/apps/sntp -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/lwip/lwip/src/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/lwip/port/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/lwip/port/esp32/include/arch -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/soc/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/soc/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/soc/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/hal/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/hal/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/hal/platform_port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_rom/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_rom/include/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_rom/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_common/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_system/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_system/port/soc -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_system/port/public_compat -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/xtensa/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/xtensa/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/driver/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/driver/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_pm/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_ringbuf/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/efuse/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/efuse/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/vfs/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_wifi/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_event/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_netif/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_eth/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/tcpip_adapter/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_phy/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_phy/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_ipc/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/app_trace/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_timer/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/mbedtls/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/mbedtls/mbedtls/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/mbedtls/esp_crt_bundle/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/app_update/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/spi_flash/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bootloader_support/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/nvs_flash/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/pthread/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_gdbstub/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_gdbstub/xtensa -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_gdbstub/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/espcoredump/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/espcoredump/include/port/xtensa -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/wpa_supplicant/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/wpa_supplicant/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/wpa_supplicant/esp_supplicant/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/ieee802154/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/console -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/asio/asio/asio/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/asio/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/common/osi/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/include/esp32/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/common/api/include/api -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/common/btc/profile/esp/blufi/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/common/btc/profile/esp/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/bt/host/bluedroid/api/include/api -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/cbor/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/unity/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/unity/unity/src -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/cmock/CMock/src -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/coap/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/coap/libcoap/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/nghttp/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/nghttp/nghttp2/lib/includes -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-tls -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-tls/esp-tls-crypto -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_adc_cal/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_hid/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/tcp_transport/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_http_client/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_http_server/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_https_ota/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_lcd/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_lcd/interface -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/protobuf-c/protobuf-c -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/protocomm/include/common -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/protocomm/include/security -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/protocomm/include/transports -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/mdns/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_local_ctrl/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/sdmmc/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_serial_slave_link/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_websocket_client/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/expat/expat/expat/lib -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/expat/port/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/wear_levelling/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/fatfs/diskio -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/fatfs/vfs -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/fatfs/src -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/freemodbus/common/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/idf_test/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/idf_test/include/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/jsmn/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/json/cJSON -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/libsodium/libsodium/src/libsodium/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/libsodium/port_include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/mqtt/esp-mqtt/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/openssl/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/perfmon/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/spiffs/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/ulp/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/wifi_provisioning/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/button/button/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/rmaker_common/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/json_parser/upstream/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/json_parser/upstream -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/json_generator/upstream -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_schedule/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_rainmaker/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/qrcode/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/ws2812_led -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/dotprod/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/support/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/hann/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_harris/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_nuttall/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/nuttall/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/windows/flat_top/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/iir/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/fir/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/add/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/sub/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/mul/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/addc/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/mulc/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/math/sqrt/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/matrix/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/fft/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/dct/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/conv/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/common/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf_imu13states/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_littlefs/src -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp_littlefs/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/tool -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/typedef -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/image -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/math -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/nn -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/layer -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/detect -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-dl/include/model_zoo -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-sr/esp-tts/esp_tts_chinese/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp-sr/include/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp32-camera/driver/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/esp32-camera/conversions/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/include/fb_gfx/include -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/tools/sdk/esp32/qspi_qspi/include -mlongcalls -Wno-frame-address -ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Os -freorder-blocks -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -std=gnu++11 -fexceptions -fno-rtti -MMD -c -DF_CPU=240000000L -DARDUINO=10607 -DARDUINO_ESPino32 -DARDUINO_ARCH_ESP32 "-DARDUINO_BOARD=\"ESPino32\"" "-DARDUINO_VARIANT=\"espino32\"" -DARDUINO_PARTITION_default -DESP32 -DCORE_DEBUG_LEVEL=0 -DARDUINO_USB_CDC_ON_BOOT=0 @/tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/build_opt.h -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/cores/esp32 -I/home/megabug/.arduino15/packages/esp32/hardware/esp32/2.0.3/variants/espino32 -I/home/megabug/Arduino/libraries/Audio/src /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp -o /tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/sketch/Blink.ino.cpp.o +In file included from /home/megabug/Arduino/libraries/Audio/src/Audio.h:16, + from /home/megabug/Arduino/Blink/Blink.ino:1: +/home/megabug/Arduino/libraries/Audio/src/DAC.h:21:15: error: expected ')' before '*' token + DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) : + ~ ^~ + ) +/home/megabug/Arduino/libraries/Audio/src/DAC.h:35:2: error: 'Dacc' does not name a type + Dacc *dac; + ^~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:37:2: error: 'IRQn_Type' does not name a type + IRQn_Type isrId; + ^~~~~~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h: In member function 'void DACClass::enableInterrupts()': +/home/megabug/Arduino/libraries/Audio/src/DAC.h:31:43: error: 'isrId' was not declared in this scope + void enableInterrupts() { NVIC_EnableIRQ(isrId); }; + ^~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:31:28: error: 'NVIC_EnableIRQ' was not declared in this scope + void enableInterrupts() { NVIC_EnableIRQ(isrId); }; + ^~~~~~~~~~~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h: In member function 'void DACClass::disableInterrupts()': +/home/megabug/Arduino/libraries/Audio/src/DAC.h:32:44: error: 'isrId' was not declared in this scope + void disableInterrupts() { NVIC_DisableIRQ(isrId); }; + ^~~~~ +/home/megabug/Arduino/libraries/Audio/src/DAC.h:32:28: error: 'NVIC_DisableIRQ' was not declared in this scope + void disableInterrupts() { NVIC_DisableIRQ(isrId); }; + ^~~~~~~~~~~~~~~ +In file included from /home/megabug/Arduino/Blink/Blink.ino:1: +/home/megabug/Arduino/libraries/Audio/src/Audio.h: In member function 'virtual size_t AudioClass::write(uint8_t)': +/home/megabug/Arduino/libraries/Audio/src/Audio.h:25:82: warning: no return statement in function returning non-void [-Wreturn-type] + virtual size_t write(uint8_t c) { /* not implemented */ }; + ^ +/home/megabug/Arduino/Blink/Blink.ino: In function 'void setup()': +/home/megabug/Arduino/Blink/Blink.ino:4:1: error: 'asd' was not declared in this scope + asd; + ^~~ +/home/megabug/Arduino/Blink/Blink.ino:4:1: note: suggested alternative: 'rand' + asd; + ^~~ + rand \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt.json b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt.json new file mode 100644 index 00000000000..5f9b36e4309 --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test003.txt.json @@ -0,0 +1,190 @@ +[ + { + "severity": "ERROR", + "message": "expected ')' before '*' token\n DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) :\n ~ ^~\n )", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 21, + "col": 15, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'Dacc' does not name a type\n Dacc *dac;\n ^~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 35, + "col": 2, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'IRQn_Type' does not name a type\n IRQn_Type isrId;\n ^~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 37, + "col": 2, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + } + ] + }, + { + "severity": "ERROR", + "message": "'isrId' was not declared in this scope\n void enableInterrupts() { NVIC_EnableIRQ(isrId); };\n ^~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 31, + "col": 43, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::enableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'NVIC_EnableIRQ' was not declared in this scope\n void enableInterrupts() { NVIC_EnableIRQ(isrId); };\n ^~~~~~~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 31, + "col": 28, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::enableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'isrId' was not declared in this scope\n void disableInterrupts() { NVIC_DisableIRQ(isrId); };\n ^~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 32, + "col": 44, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::disableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'NVIC_DisableIRQ' was not declared in this scope\n void disableInterrupts() { NVIC_DisableIRQ(isrId); };\n ^~~~~~~~~~~~~~~", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h", + "line": 32, + "col": 28, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 16 + }, + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'void DACClass::disableInterrupts()':", + "file": "/home/megabug/Arduino/libraries/Audio/src/DAC.h" + } + ] + }, + { + "severity": "WARNING", + "message": "no return statement in function returning non-void [-Wreturn-type]\n virtual size_t write(uint8_t c) { /* not implemented */ };\n ^", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h", + "line": 25, + "col": 82, + "context": [ + { + "message": "included from here", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 1 + }, + { + "message": "In member function 'virtual size_t AudioClass::write(uint8_t)':", + "file": "/home/megabug/Arduino/libraries/Audio/src/Audio.h" + } + ] + }, + { + "severity": "ERROR", + "message": "'asd' was not declared in this scope\n asd;\n ^~~", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 4, + "col": 1, + "context": [ + { + "message": "In function 'void setup()':", + "file": "/home/megabug/Arduino/Blink/Blink.ino" + } + ], + "suggestions": [ + { + "message": "suggested alternative: 'rand'\n asd;\n ^~~\n rand", + "file": "/home/megabug/Arduino/Blink/Blink.ino", + "line": 4, + "col": 1 + } + ] + } +] \ No newline at end of file diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt new file mode 100644 index 00000000000..958800f68f5 --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt @@ -0,0 +1,5 @@ +C:\Users\runneradmin\AppData\Local\Temp\cli2123776893\A\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Users\runneradmin\AppData\Local\Temp\cli2123776893\A\packages\arduino\hardware\avr\1.8.5\cores\arduino -IC:\Users\runneradmin\AppData\Local\Temp\cli2123776893\A\packages\arduino\hardware\avr\1.8.5\variants\standard C:\Users\runneradmin\AppData\Local\Temp\arduino\sketches\BD9E9425D0ACEC4A9F5E44E2417C33A5\sketch\wrong.cpp -o C:\Users\runneradmin\AppData\Local\Temp\arduino\sketches\BD9E9425D0ACEC4A9F5E44E2417C33A5\sketch\wrong.cpp.o +D:\a\arduino-cli\arduino-cli\internal\integrationtest\compile_3\testdata\blink_with_wrong_cpp\wrong.cpp: In function 'void wrong()': +D:\a\arduino-cli\arduino-cli\internal\integrationtest\compile_3\testdata\blink_with_wrong_cpp\wrong.cpp:1:14: error: expected '}' at end of input + void wrong() { + ^ diff --git a/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt.json b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt.json new file mode 100644 index 00000000000..e436025aee2 --- /dev/null +++ b/arduino/builder/internal/diagnostics/testdata/compiler_outputs/test004.txt.json @@ -0,0 +1,15 @@ +[ + { + "severity": "ERROR", + "message": "expected '}' at end of input\n void wrong() {\n ^", + "file": "D:\\a\\arduino-cli\\arduino-cli\\internal\\integrationtest\\compile_3\\testdata\\blink_with_wrong_cpp\\wrong.cpp", + "line": 1, + "col": 14, + "context": [ + { + "message": "In function 'void wrong()':", + "file": "D:\\a\\arduino-cli\\arduino-cli\\internal\\integrationtest\\compile_3\\testdata\\blink_with_wrong_cpp\\wrong.cpp" + } + ] + } +] \ No newline at end of file diff --git a/commands/compile/compile.go b/commands/compile/compile.go index 604a7acb215..c168f27998a 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -177,6 +177,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream if pme.GetProfile() != nil { libsManager = lm } + sketchBuilder, err := builder.NewBuilder( sk, boardBuildProperties, @@ -218,6 +219,10 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream } }() + defer func() { + r.Diagnostics = sketchBuilder.CompilerDiagnostics().ToRPC() + }() + defer func() { buildProperties := sketchBuilder.GetBuildProperties() if buildProperties == nil { diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 8f371d5b060..1204b529f17 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -348,6 +348,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { UpdatedUploadPort: result.NewPort(uploadRes.GetUpdatedUploadPort()), }, ProfileOut: profileOut, + Diagnostics: result.NewCompileDiagnostics(compileRes.GetDiagnostics()), Success: compileError == nil, showPropertiesMode: showProperties, hideStats: preprocess, @@ -392,14 +393,14 @@ type updatedUploadPortResult struct { } type compileResult struct { - CompilerOut string `json:"compiler_out"` - CompilerErr string `json:"compiler_err"` - BuilderResult *result.CompileResponse `json:"builder_result"` - UploadResult updatedUploadPortResult `json:"upload_result"` - Success bool `json:"success"` - ProfileOut string `json:"profile_out,omitempty"` - Error string `json:"error,omitempty"` - + CompilerOut string `json:"compiler_out"` + CompilerErr string `json:"compiler_err"` + BuilderResult *result.CompileResponse `json:"builder_result"` + UploadResult updatedUploadPortResult `json:"upload_result"` + Success bool `json:"success"` + ProfileOut string `json:"profile_out,omitempty"` + Error string `json:"error,omitempty"` + Diagnostics []*result.CompileDiagnostic `json:"diagnostics,omitempty"` showPropertiesMode arguments.ShowPropertiesMode hideStats bool } diff --git a/internal/cli/feedback/result/rpc.go b/internal/cli/feedback/result/rpc.go index 6b19c138a6d..a632af7737c 100644 --- a/internal/cli/feedback/result/rpc.go +++ b/internal/cli/feedback/result/rpc.go @@ -18,6 +18,7 @@ package result import ( "cmp" + f "github.com/arduino/arduino-cli/internal/algorithms" "github.com/arduino/arduino-cli/internal/orderedmap" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" semver "go.bug.st/relaxed-semver" @@ -880,6 +881,7 @@ type CompileResponse struct { BoardPlatform *InstalledPlatformReference `json:"board_platform,omitempty"` BuildPlatform *InstalledPlatformReference `json:"build_platform,omitempty"` BuildProperties []string `json:"build_properties,omitempty"` + Diagnostics []*CompileDiagnostic `json:"diagnostics,omitempty"` } func NewCompileResponse(c *rpc.CompileResponse) *CompileResponse { @@ -904,6 +906,7 @@ func NewCompileResponse(c *rpc.CompileResponse) *CompileResponse { BoardPlatform: NewInstalledPlatformReference(c.GetBoardPlatform()), BuildPlatform: NewInstalledPlatformReference(c.GetBuildPlatform()), BuildProperties: c.GetBuildProperties(), + Diagnostics: NewCompileDiagnostics(c.GetDiagnostics()), } } @@ -959,3 +962,61 @@ func NewBoardListWatchResponse(r *rpc.BoardListWatchResponse) *BoardListWatchRes Error: r.Error, } } + +type CompileDiagnostic struct { + Severity string `json:"severity,omitempty"` + Message string `json:"message,omitempty"` + File string `json:"file,omitempty"` + Line int64 `json:"line,omitempty"` + Column int64 `json:"column,omitempty"` + Context []*CompileDiagnosticContext `json:"context,omitempty"` + Notes []*CompileDiagnosticNote `json:"notes,omitempty"` +} + +func NewCompileDiagnostics(cd []*rpc.CompileDiagnostic) []*CompileDiagnostic { + return f.Map(cd, NewCompileDiagnostic) +} + +func NewCompileDiagnostic(cd *rpc.CompileDiagnostic) *CompileDiagnostic { + return &CompileDiagnostic{ + Severity: cd.GetSeverity(), + Message: cd.GetMessage(), + File: cd.GetFile(), + Line: cd.GetLine(), + Column: cd.GetColumn(), + Context: f.Map(cd.GetContext(), NewCompileDiagnosticContext), + Notes: f.Map(cd.GetNotes(), NewCompileDiagnosticNote), + } +} + +type CompileDiagnosticContext struct { + Message string `json:"message,omitempty"` + File string `json:"file,omitempty"` + Line int64 `json:"line,omitempty"` + Column int64 `json:"column,omitempty"` +} + +func NewCompileDiagnosticContext(cdc *rpc.CompileDiagnosticContext) *CompileDiagnosticContext { + return &CompileDiagnosticContext{ + Message: cdc.GetMessage(), + File: cdc.GetFile(), + Line: cdc.GetLine(), + Column: cdc.GetColumn(), + } +} + +type CompileDiagnosticNote struct { + Message string `json:"message,omitempty"` + File string `json:"file,omitempty"` + Line int64 `json:"line,omitempty"` + Column int64 `json:"column,omitempty"` +} + +func NewCompileDiagnosticNote(cdn *rpc.CompileDiagnosticNote) *CompileDiagnosticNote { + return &CompileDiagnosticNote{ + Message: cdn.GetMessage(), + File: cdn.GetFile(), + Line: cdn.GetLine(), + Column: cdn.GetColumn(), + } +} diff --git a/internal/cli/feedback/result/rpc_test.go b/internal/cli/feedback/result/rpc_test.go index 46adbcd8acc..af5259d128e 100644 --- a/internal/cli/feedback/result/rpc_test.go +++ b/internal/cli/feedback/result/rpc_test.go @@ -205,6 +205,18 @@ func TestAllFieldAreMapped(t *testing.T) { boardListWatchResponseRpc := &rpc.BoardListWatchResponse{} boardListWatchResponseResult := result.NewBoardListWatchResponse(boardListWatchResponseRpc) mustContainsAllPropertyOfRpcStruct(t, boardListWatchResponseRpc, boardListWatchResponseResult) + + compileDiagnosticRpc := &rpc.CompileDiagnostic{} + compileDiagnosticResult := result.NewCompileDiagnostic(compileDiagnosticRpc) + mustContainsAllPropertyOfRpcStruct(t, compileDiagnosticRpc, compileDiagnosticResult) + + compileDiagnosticContextRpc := &rpc.CompileDiagnosticContext{} + compileDiagnosticContextResult := result.NewCompileDiagnosticContext(compileDiagnosticContextRpc) + mustContainsAllPropertyOfRpcStruct(t, compileDiagnosticContextRpc, compileDiagnosticContextResult) + + compileDiagnosticNoteRpc := &rpc.CompileDiagnosticNote{} + compileDiagnosticNoteResult := result.NewCompileDiagnosticNote(compileDiagnosticNoteRpc) + mustContainsAllPropertyOfRpcStruct(t, compileDiagnosticNoteRpc, compileDiagnosticNoteResult) } func TestEnumsMapsEveryRpcCounterpart(t *testing.T) { diff --git a/internal/integrationtest/compile_3/compile_test.go b/internal/integrationtest/compile_3/compile_test.go index 2df3d59f40d..2f9ba8e5306 100644 --- a/internal/integrationtest/compile_3/compile_test.go +++ b/internal/integrationtest/compile_3/compile_test.go @@ -113,10 +113,19 @@ func TestCompilerErrOutput(t *testing.T) { require.NoError(t, err) // Run compile and catch err stream - out, _, err := cli.Run("compile", "-b", "arduino:avr:uno", "--format", "json", sketch.String()) + out, _, err := cli.Run("compile", "-b", "arduino:avr:uno", "-v", "--format", "json", sketch.String()) require.Error(t, err) - compilerErr := requirejson.Parse(t, out).Query(".compiler_err") - compilerErr.MustContain(`"error"`) + outJson := requirejson.Parse(t, out) + outJson.Query(`.compiler_err`).MustContain(`"error"`) + outJson.Query(`.diagnostics`).MustContain(` + [ + { + "severity": "ERROR", + "line": 1, + "column": 14, + "context": [ { "message": "In function 'void wrong()':" } ] + } + ]`) } // Check that library discover do not generate false errors @@ -132,6 +141,7 @@ func TestCompilerErrOutput(t *testing.T) { jsonOut := requirejson.Parse(t, out) jsonOut.Query(".compiler_out").MustNotContain(`"fatal error"`) jsonOut.Query(".compiler_err").MustNotContain(`"fatal error"`) + jsonOut.MustNotContain(`{ "diagnostics" : [] }`) } } diff --git a/rpc/cc/arduino/cli/commands/v1/compile.pb.go b/rpc/cc/arduino/cli/commands/v1/compile.pb.go index 7f3a8c6801c..d5564454b25 100644 --- a/rpc/cc/arduino/cli/commands/v1/compile.pb.go +++ b/rpc/cc/arduino/cli/commands/v1/compile.pb.go @@ -343,6 +343,8 @@ type CompileResponse struct { Progress *TaskProgress `protobuf:"bytes,8,opt,name=progress,proto3" json:"progress,omitempty"` // Build properties used for compiling BuildProperties []string `protobuf:"bytes,9,rep,name=build_properties,json=buildProperties,proto3" json:"build_properties,omitempty"` + // Compiler errors and warnings + Diagnostics []*CompileDiagnostic `protobuf:"bytes,10,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` } func (x *CompileResponse) Reset() { @@ -440,6 +442,13 @@ func (x *CompileResponse) GetBuildProperties() []string { return nil } +func (x *CompileResponse) GetDiagnostics() []*CompileDiagnostic { + if x != nil { + return x.Diagnostics + } + return nil +} + type ExecutableSectionSize struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -503,6 +512,260 @@ func (x *ExecutableSectionSize) GetMaxSize() int64 { return 0 } +type CompileDiagnostic struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Severity of the diagnostic + Severity string `protobuf:"bytes,1,opt,name=severity,proto3" json:"severity,omitempty"` + // The explanation of the diagnostic (it may be multiple preformatted lines) + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + // The file containing the diagnostic + File string `protobuf:"bytes,3,opt,name=file,proto3" json:"file,omitempty"` + // The line of the diagnostic if available (starts from 1) + Line int64 `protobuf:"varint,4,opt,name=line,proto3" json:"line,omitempty"` + // The column of the diagnostic if available (starts from 1) + Column int64 `protobuf:"varint,5,opt,name=column,proto3" json:"column,omitempty"` + // The context where this diagnostic is found (it may be multiple files that + // represents a chain of includes, or a text describing where the diagnostic + // is found) + Context []*CompileDiagnosticContext `protobuf:"bytes,6,rep,name=context,proto3" json:"context,omitempty"` + // Annotations or suggestions to the diagnostic made by the compiler + Notes []*CompileDiagnosticNote `protobuf:"bytes,7,rep,name=notes,proto3" json:"notes,omitempty"` +} + +func (x *CompileDiagnostic) Reset() { + *x = CompileDiagnostic{} + if protoimpl.UnsafeEnabled { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CompileDiagnostic) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompileDiagnostic) ProtoMessage() {} + +func (x *CompileDiagnostic) ProtoReflect() protoreflect.Message { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompileDiagnostic.ProtoReflect.Descriptor instead. +func (*CompileDiagnostic) Descriptor() ([]byte, []int) { + return file_cc_arduino_cli_commands_v1_compile_proto_rawDescGZIP(), []int{3} +} + +func (x *CompileDiagnostic) GetSeverity() string { + if x != nil { + return x.Severity + } + return "" +} + +func (x *CompileDiagnostic) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *CompileDiagnostic) GetFile() string { + if x != nil { + return x.File + } + return "" +} + +func (x *CompileDiagnostic) GetLine() int64 { + if x != nil { + return x.Line + } + return 0 +} + +func (x *CompileDiagnostic) GetColumn() int64 { + if x != nil { + return x.Column + } + return 0 +} + +func (x *CompileDiagnostic) GetContext() []*CompileDiagnosticContext { + if x != nil { + return x.Context + } + return nil +} + +func (x *CompileDiagnostic) GetNotes() []*CompileDiagnosticNote { + if x != nil { + return x.Notes + } + return nil +} + +type CompileDiagnosticContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The message describing the context reference + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + // The file of the context reference + File string `protobuf:"bytes,2,opt,name=file,proto3" json:"file,omitempty"` + // The line of the context reference + Line int64 `protobuf:"varint,3,opt,name=line,proto3" json:"line,omitempty"` + // The column of the context reference + Column int64 `protobuf:"varint,4,opt,name=column,proto3" json:"column,omitempty"` +} + +func (x *CompileDiagnosticContext) Reset() { + *x = CompileDiagnosticContext{} + if protoimpl.UnsafeEnabled { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CompileDiagnosticContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompileDiagnosticContext) ProtoMessage() {} + +func (x *CompileDiagnosticContext) ProtoReflect() protoreflect.Message { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompileDiagnosticContext.ProtoReflect.Descriptor instead. +func (*CompileDiagnosticContext) Descriptor() ([]byte, []int) { + return file_cc_arduino_cli_commands_v1_compile_proto_rawDescGZIP(), []int{4} +} + +func (x *CompileDiagnosticContext) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *CompileDiagnosticContext) GetFile() string { + if x != nil { + return x.File + } + return "" +} + +func (x *CompileDiagnosticContext) GetLine() int64 { + if x != nil { + return x.Line + } + return 0 +} + +func (x *CompileDiagnosticContext) GetColumn() int64 { + if x != nil { + return x.Column + } + return 0 +} + +type CompileDiagnosticNote struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The message describing the compiler note + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + // The file of the compiler note + File string `protobuf:"bytes,2,opt,name=file,proto3" json:"file,omitempty"` + // The line of the compiler note + Line int64 `protobuf:"varint,3,opt,name=line,proto3" json:"line,omitempty"` + // The column of the compiler note + Column int64 `protobuf:"varint,4,opt,name=column,proto3" json:"column,omitempty"` +} + +func (x *CompileDiagnosticNote) Reset() { + *x = CompileDiagnosticNote{} + if protoimpl.UnsafeEnabled { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CompileDiagnosticNote) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompileDiagnosticNote) ProtoMessage() {} + +func (x *CompileDiagnosticNote) ProtoReflect() protoreflect.Message { + mi := &file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompileDiagnosticNote.ProtoReflect.Descriptor instead. +func (*CompileDiagnosticNote) Descriptor() ([]byte, []int) { + return file_cc_arduino_cli_commands_v1_compile_proto_rawDescGZIP(), []int{5} +} + +func (x *CompileDiagnosticNote) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *CompileDiagnosticNote) GetFile() string { + if x != nil { + return x.File + } + return "" +} + +func (x *CompileDiagnosticNote) GetLine() int64 { + if x != nil { + return x.Line + } + return 0 +} + +func (x *CompileDiagnosticNote) GetColumn() int64 { + if x != nil { + return x.Column + } + return 0 +} + var File_cc_arduino_cli_commands_v1_compile_proto protoreflect.FileDescriptor var file_cc_arduino_cli_commands_v1_compile_proto_rawDesc = []byte{ @@ -587,7 +850,7 @@ var file_cc_arduino_cli_commands_v1_compile_proto_rawDesc = []byte{ 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xd6, 0x04, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x22, 0xa7, 0x05, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, @@ -624,18 +887,56 @@ var file_cc_arduino_cli_commands_v1_compile_proto_rawDesc = []byte{ 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x5a, 0x0a, 0x15, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, - 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, - 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, - 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, - 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, - 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x4f, 0x0a, 0x0b, 0x64, 0x69, 0x61, + 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, + 0x69, 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0x5a, 0x0a, 0x15, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, + 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, + 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xa2, 0x02, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x69, + 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x12, 0x1a, 0x0a, 0x08, + 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, + 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x12, 0x4e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, + 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, + 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x12, 0x47, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, + 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x4e, 0x6f, 0x74, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x22, 0x74, 0x0a, 0x18, 0x43, + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x22, 0x71, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x61, 0x67, + 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x4e, 0x6f, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, + 0x6c, 0x75, 0x6d, 0x6e, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, + 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, + 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -650,32 +951,38 @@ func file_cc_arduino_cli_commands_v1_compile_proto_rawDescGZIP() []byte { return file_cc_arduino_cli_commands_v1_compile_proto_rawDescData } -var file_cc_arduino_cli_commands_v1_compile_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_cc_arduino_cli_commands_v1_compile_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_cc_arduino_cli_commands_v1_compile_proto_goTypes = []interface{}{ (*CompileRequest)(nil), // 0: cc.arduino.cli.commands.v1.CompileRequest (*CompileResponse)(nil), // 1: cc.arduino.cli.commands.v1.CompileResponse (*ExecutableSectionSize)(nil), // 2: cc.arduino.cli.commands.v1.ExecutableSectionSize - nil, // 3: cc.arduino.cli.commands.v1.CompileRequest.SourceOverrideEntry - (*Instance)(nil), // 4: cc.arduino.cli.commands.v1.Instance - (*wrapperspb.BoolValue)(nil), // 5: google.protobuf.BoolValue - (*Library)(nil), // 6: cc.arduino.cli.commands.v1.Library - (*InstalledPlatformReference)(nil), // 7: cc.arduino.cli.commands.v1.InstalledPlatformReference - (*TaskProgress)(nil), // 8: cc.arduino.cli.commands.v1.TaskProgress + (*CompileDiagnostic)(nil), // 3: cc.arduino.cli.commands.v1.CompileDiagnostic + (*CompileDiagnosticContext)(nil), // 4: cc.arduino.cli.commands.v1.CompileDiagnosticContext + (*CompileDiagnosticNote)(nil), // 5: cc.arduino.cli.commands.v1.CompileDiagnosticNote + nil, // 6: cc.arduino.cli.commands.v1.CompileRequest.SourceOverrideEntry + (*Instance)(nil), // 7: cc.arduino.cli.commands.v1.Instance + (*wrapperspb.BoolValue)(nil), // 8: google.protobuf.BoolValue + (*Library)(nil), // 9: cc.arduino.cli.commands.v1.Library + (*InstalledPlatformReference)(nil), // 10: cc.arduino.cli.commands.v1.InstalledPlatformReference + (*TaskProgress)(nil), // 11: cc.arduino.cli.commands.v1.TaskProgress } var file_cc_arduino_cli_commands_v1_compile_proto_depIdxs = []int32{ - 4, // 0: cc.arduino.cli.commands.v1.CompileRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 3, // 1: cc.arduino.cli.commands.v1.CompileRequest.source_override:type_name -> cc.arduino.cli.commands.v1.CompileRequest.SourceOverrideEntry - 5, // 2: cc.arduino.cli.commands.v1.CompileRequest.export_binaries:type_name -> google.protobuf.BoolValue - 6, // 3: cc.arduino.cli.commands.v1.CompileResponse.used_libraries:type_name -> cc.arduino.cli.commands.v1.Library - 2, // 4: cc.arduino.cli.commands.v1.CompileResponse.executable_sections_size:type_name -> cc.arduino.cli.commands.v1.ExecutableSectionSize - 7, // 5: cc.arduino.cli.commands.v1.CompileResponse.board_platform:type_name -> cc.arduino.cli.commands.v1.InstalledPlatformReference - 7, // 6: cc.arduino.cli.commands.v1.CompileResponse.build_platform:type_name -> cc.arduino.cli.commands.v1.InstalledPlatformReference - 8, // 7: cc.arduino.cli.commands.v1.CompileResponse.progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 7, // 0: cc.arduino.cli.commands.v1.CompileRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 6, // 1: cc.arduino.cli.commands.v1.CompileRequest.source_override:type_name -> cc.arduino.cli.commands.v1.CompileRequest.SourceOverrideEntry + 8, // 2: cc.arduino.cli.commands.v1.CompileRequest.export_binaries:type_name -> google.protobuf.BoolValue + 9, // 3: cc.arduino.cli.commands.v1.CompileResponse.used_libraries:type_name -> cc.arduino.cli.commands.v1.Library + 2, // 4: cc.arduino.cli.commands.v1.CompileResponse.executable_sections_size:type_name -> cc.arduino.cli.commands.v1.ExecutableSectionSize + 10, // 5: cc.arduino.cli.commands.v1.CompileResponse.board_platform:type_name -> cc.arduino.cli.commands.v1.InstalledPlatformReference + 10, // 6: cc.arduino.cli.commands.v1.CompileResponse.build_platform:type_name -> cc.arduino.cli.commands.v1.InstalledPlatformReference + 11, // 7: cc.arduino.cli.commands.v1.CompileResponse.progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress + 3, // 8: cc.arduino.cli.commands.v1.CompileResponse.diagnostics:type_name -> cc.arduino.cli.commands.v1.CompileDiagnostic + 4, // 9: cc.arduino.cli.commands.v1.CompileDiagnostic.context:type_name -> cc.arduino.cli.commands.v1.CompileDiagnosticContext + 5, // 10: cc.arduino.cli.commands.v1.CompileDiagnostic.notes:type_name -> cc.arduino.cli.commands.v1.CompileDiagnosticNote + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_cc_arduino_cli_commands_v1_compile_proto_init() } @@ -722,6 +1029,42 @@ func file_cc_arduino_cli_commands_v1_compile_proto_init() { return nil } } + file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CompileDiagnostic); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CompileDiagnosticContext); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cc_arduino_cli_commands_v1_compile_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CompileDiagnosticNote); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -729,7 +1072,7 @@ func file_cc_arduino_cli_commands_v1_compile_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_cc_arduino_cli_commands_v1_compile_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/rpc/cc/arduino/cli/commands/v1/compile.proto b/rpc/cc/arduino/cli/commands/v1/compile.proto index ff160ba1c01..57c6ca9d23d 100644 --- a/rpc/cc/arduino/cli/commands/v1/compile.proto +++ b/rpc/cc/arduino/cli/commands/v1/compile.proto @@ -115,6 +115,8 @@ message CompileResponse { TaskProgress progress = 8; // Build properties used for compiling repeated string build_properties = 9; + // Compiler errors and warnings + repeated CompileDiagnostic diagnostics = 10; } message ExecutableSectionSize { @@ -122,3 +124,44 @@ message ExecutableSectionSize { int64 size = 2; int64 max_size = 3; } + +message CompileDiagnostic { + // Severity of the diagnostic + string severity = 1; + // The explanation of the diagnostic (it may be multiple preformatted lines) + string message = 2; + // The file containing the diagnostic + string file = 3; + // The line of the diagnostic if available (starts from 1) + int64 line = 4; + // The column of the diagnostic if available (starts from 1) + int64 column = 5; + // The context where this diagnostic is found (it may be multiple files that + // represents a chain of includes, or a text describing where the diagnostic + // is found) + repeated CompileDiagnosticContext context = 6; + // Annotations or suggestions to the diagnostic made by the compiler + repeated CompileDiagnosticNote notes = 7; +} + +message CompileDiagnosticContext { + // The message describing the context reference + string message = 1; + // The file of the context reference + string file = 2; + // The line of the context reference + int64 line = 3; + // The column of the context reference + int64 column = 4; +} + +message CompileDiagnosticNote { + // The message describing the compiler note + string message = 1; + // The file of the compiler note + string file = 2; + // The line of the compiler note + int64 line = 3; + // The column of the compiler note + int64 column = 4; +}