blob: c8f7e4a76a8f9a7c9a5e77e657cb1c1f7ef33057 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package analysis
import (
"encoding/json"
"fmt"
"os/exec"
fidlcommon "fidl-lsp/third_party/common"
"fidl-lsp/state"
)
// DiagnosticsOnLibrary retrieves the cached diagnostics for the library with
// name `libName` including the file `path`.
func (a *Analyzer) DiagnosticsOnLibrary(libName fidlcommon.LibraryName, path state.FileID) (map[state.FileID][]Diagnostic, error) {
lib, ok := a.getLibraryWithFile(libName, path)
if !ok {
return nil, fmt.Errorf("could not find library `%s`", libName)
}
return lib.diags, nil
}
type fidlLintSuggestion struct {
Description string
}
type FidlcTool string
const (
Fidlc FidlcTool = "fidlc"
FidlLint = "fidl-lint"
)
// Diagnostic represents an {error, warning, lint} deserialized from the JSON
// output of fidlc or fidl-lint.
type Diagnostic struct {
Source FidlcTool
Category string
Message string
Path string
StartLine int `json:"start_line"`
StartChar int `json:"start_char"`
EndLine int `json:"end_line"`
EndChar int `json:"end_char"`
Suggestions []fidlLintSuggestion
}
func (a *Analyzer) fidlcDiagsFromStderr(stderr []byte) (map[state.FileID][]Diagnostic, error) {
// Deserialize stderr into []Diagnostic
var diags []Diagnostic
if err := json.Unmarshal(stderr, &diags); err != nil {
return nil, fmt.Errorf("could not deserialize fidlc diagnostics: `%s`", err)
}
fileToDiags := make(map[state.FileID][]Diagnostic)
for i := range diags {
fileID, err := a.inputFileToFileID(diags[i].Path)
if err != nil {
continue
}
if _, ok := fileToDiags[fileID]; !ok {
fileToDiags[fileID] = []Diagnostic{}
}
diags[i].Source = Fidlc
fileToDiags[fileID] = append(fileToDiags[fileID], diags[i])
}
return fileToDiags, nil
}
func (a *Analyzer) runFidlLint(path string) (map[state.FileID][]Diagnostic, error) {
// TODO: return early with an error if we got status code != 0 or 1?
// Otherwise, ignore err: we expect this to fail with status code 1 if there
// are any lints from fidl-lint.
out, _ := exec.Command(a.cfg.FidlLintPath, "--format=json", path).Output()
// Deserialize stdout into []fidlLint
var diags []Diagnostic
if err := json.Unmarshal(out, &diags); err != nil {
return nil, fmt.Errorf("error deserializing fidl-lint output: %s", err)
}
fileToDiags := make(map[state.FileID][]Diagnostic)
for i := range diags {
fileID, err := a.inputFileToFileID(diags[i].Path)
if err != nil {
continue
}
if _, ok := fileToDiags[fileID]; !ok {
fileToDiags[fileID] = []Diagnostic{}
}
diags[i].Source = FidlLint
fileToDiags[fileID] = append(fileToDiags[fileID], diags[i])
}
return fileToDiags, nil
}