blob: 9dec18c927fa26b8c85971f5c56ca1c5968c2046 [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 langserver
import (
"context"
"fmt"
"path/filepath"
"github.com/sourcegraph/go-lsp"
"github.com/sourcegraph/jsonrpc2"
"fidl-lsp/analysis"
)
// clientConfig are the configuration settings from the LSP client. These are
// relevant to the Analyzer. If they are left unset, the Analyzer uses its
// defaults.
type clientConfig struct {
FidlProject string `json:"fidlProject,omitempty"`
BuildRoot string `json:"projectRoot,omitempty"`
Tools toolsConfig `json:"tools,omitempty"`
}
type toolsConfig struct {
Compiler string `json:"compiler,omitempty"`
Linter string `json:"linter,omitempty"`
Formatter string `json:"formatter,omitempty"`
}
func (h *LangHandler) requestConfiguration(ctx context.Context, conn *jsonrpc2.Conn) {
go func() {
var cfg []clientConfig
conn.Call(
ctx,
"workspace/configuration",
lsp.ConfigurationParams{
Items: []lsp.ConfigurationItem{{Section: "fidl"}},
},
&cfg,
)
if len(cfg) < 1 {
h.log.Printf("received invalid configuration settings. unable to update\n")
return
}
h.updateConfig(ctx, conn, cfg[0])
}()
}
func (h *LangHandler) handleDidChangeConfiguration(ctx context.Context, conn *jsonrpc2.Conn, params lsp.DidChangeConfigurationParams) {
h.log.Printf("updating with new config settings: %#v", params.Settings)
cfg, ok := params.Settings.([]clientConfig)
if !ok {
h.log.Printf("received invalid configuration settings. unable to update\n")
return
}
if len(cfg) < 1 {
h.log.Printf("received invalid configuration settings. unable to update\n")
return
}
h.updateConfig(ctx, conn, cfg[0])
}
func (h *LangHandler) updateConfig(ctx context.Context, conn *jsonrpc2.Conn, cfg clientConfig) {
if cfg.FidlProject != "" {
h.LoadFidlProject(ctx, conn, cfg.FidlProject)
// If the BuildRoot is unset, set it to the directory containing
// `FidlProject`
if cfg.BuildRoot == "" {
cfg.BuildRoot = filepath.Dir(cfg.FidlProject)
}
}
h.analyzer.SetConfig(analysis.Config{
BuildRootDir: cfg.BuildRoot,
FidlcPath: cfg.Tools.Compiler,
FidlLintPath: cfg.Tools.Linter,
FidlFormatPath: cfg.Tools.Formatter,
})
}
// LoadFidlProject attempts to read in the fidl_project.json file at
// `fidlProjectPath`, and if it can't, it displays an error dialog in the client
// so the user can try to regenerate the file.
func (h *LangHandler) LoadFidlProject(ctx context.Context, conn *jsonrpc2.Conn, fidlProjectPath string) {
fidlProject, err := analysis.LoadFidlProject(fidlProjectPath)
if err != nil {
h.log.Printf("failed to parse fidl_project.json at `%s`: %s\n", fidlProjectPath, err)
h.Notify(ctx, conn, "window/showMessage", lsp.ShowMessageParams{
Type: lsp.MTError,
Message: fmt.Sprintf(
"Failed to load fidl_project.json at '%s'.\n"+
"To generate this file, run "+
"`fx gen && fx build build/fidl:validate_fidl_project_json`. "+
"Alternatively, custom path can be specified in settings.",
fidlProjectPath,
),
})
}
h.analyzer.ImportCompiledLibraries(fidlProject)
}