blob: fb0ec1a0e884ba56c4cdb354a73fa7b56052e1c2 [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 (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os/exec"
"fidl-lsp/state"
)
// Read in the JSON IR at absolute filepath `jsonPath`.
func (a *Analyzer) importLibrary(jsonPath string) error {
data, err := ioutil.ReadFile(jsonPath)
if err != nil {
return err
}
var lib FidlLibrary
if err := json.Unmarshal(data, &lib); err != nil {
return err
}
// TODO: import more things? files + deps?
if _, ok := a.libs[LibraryName(lib.Name)]; !ok {
a.libs[LibraryName(lib.Name)] = &Library{
json: jsonPath,
}
}
a.libs[LibraryName(lib.Name)].ir = &lib
// TODO: construct symbol map from JSON IR for the file's library
return nil
}
type compileResult struct {
lib LibraryName
diags map[state.EditorFile][]Diagnostic
}
// Compile the FIDL library that includes the file at `path`.
// Returns either a compileResult containing the name of the library along with
// any diagnostics returned by fidlc and fidl-lint, or an error if compilation
// fails.
func (a *Analyzer) compile(fs *state.FileSystem, path state.EditorFile) (compileResult, error) {
var jsonPath string
file, err := fs.File(path)
if err != nil {
return compileResult{}, fmt.Errorf("could not find file `%s`", path)
}
libraryName, err := state.LibraryOfFile(file)
if err != nil {
return compileResult{}, fmt.Errorf("could not find library name of file `%s`", path)
}
jsonPath = a.pathToJSON(LibraryName(libraryName))
args := append([]string{"--format=json"}, "--json", jsonPath)
files, err := a.FindDeps(fs, path)
if err != nil {
return compileResult{}, fmt.Errorf("could not find dependencies of file `%s`: %s", path, err)
}
args = append(args, files...)
cmd := exec.Command(fidlcPath, args...)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err == nil {
// If fidlc compiled successfully, update a.libs with the compiled JSON IR
if err := a.importLibrary(jsonPath); err != nil {
return compileResult{}, fmt.Errorf("error on adding compiled JSON: %s", err)
}
}
diags := make(map[state.EditorFile][]Diagnostic)
for fileName := range a.libs[LibraryName(libraryName)].files {
editorFile, err := a.inputFileToEditorFile(fileName)
if err == nil {
diags[editorFile] = []Diagnostic{}
}
}
if errorsAndWarnings, err := a.fidlcDiagsFromStderr(stderr.Bytes()); err == nil {
for editorFile, fileDiags := range errorsAndWarnings {
if _, ok := diags[editorFile]; !ok {
diags[editorFile] = []Diagnostic{}
}
diags[editorFile] = append(diags[editorFile], fileDiags...)
}
}
if lints, err := a.runFidlLint(a.inputFilesFIDL[path]); err == nil {
for editorFile, fileDiags := range lints {
if _, ok := diags[editorFile]; !ok {
diags[editorFile] = []Diagnostic{}
}
diags[editorFile] = append(diags[editorFile], fileDiags...)
}
}
return compileResult{
lib: LibraryName(libraryName),
diags: diags,
}, nil
}