fx ide-queryThis document describes the design for collecting and managing workspace-level metadata in the ide-query tool.
The ide-query tool needs to understand the structure of the Fuchsia checkout it is running in to resolve file paths, find build artifacts, and interact with other build tools (like GN and Ninja). This state is encapsulated in a WorkspaceContext.
WorkspaceContext StructureThe context is a central data structure passed to query handlers:
type FileStatus string const ( StatusFound FileStatus = "found" StatusNotFound FileStatus = "not_found" ) type AnalysisStatus string const ( AnalysisStatusOk AnalysisStatus = "OK" AnalysisStatusNotFound AnalysisStatus = "NOT_FOUND" AnalysisStatusBuildFailed AnalysisStatus = "BUILD_FAILED" AnalysisStatusUnknown AnalysisStatus = "UNKNOWN" ) type AnalysisResult struct { Status AnalysisStatus `json:"status"` Message string `json:"message,omitempty"` } type FileEntry struct { // AbsPath is the absolute, canonicalized path to the file. AbsPath string `json:"abs_path"` // OriginalPath is the path as provided by the user (relative or absolute). OriginalPath string `json:"original_path"` // Status indicates if the file exists on disk. Status FileStatus `json:"status"` // IsDirectory is true if the path points to a directory. IsDirectory bool `json:"is_directory"` // BuildTargets is a list of GN labels that need to be built for this file. BuildTargets []string `json:"build_targets,omitempty"` // AnalysisError is a human-readable string populated if the query fails. AnalysisError string `json:"analysis_error,omitempty"` // AnalysisResult captures the build state of the file. AnalysisResult *AnalysisResult `json:"analysis_result,omitempty"` } type WorkspaceContext struct { // FuchsiaDir is the absolute path to the root of the Fuchsia checkout. FuchsiaDir string `json:"fuchsia_dir"` // BuildDir is the absolute path to the current build output directory. // This may be empty if not provided and .fx-build-dir is missing. BuildDir string `json:"build_dir"` // Files is a list of file entries provided via the --file flag or --file-list flag. Files []FileEntry `json:"files"` } type ErrorResponse struct { // Error is a human-readable error message. Error string `json:"error"` }
FuchsiaDir)The root directory must be provided via the --fuchsia-dir command-line flag. The Go tool does not perform auto-discovery and will only trust this flag.
If this flag is not provided, the tool will report an error and exit. This ensures that the tool always has a consistent view of the workspace regardless of how it is invoked.
The shell wrapper (//tools/devshell/ide-query) is responsible for reading the FUCHSIA_DIR environment variable and passing it as the --fuchsia-dir flag to the underlying binary.
Once the --fuchsia-dir is provided, it is immediately canonicalized (e.g., via filepath.EvalSymlinks) to its physical location. This canonical root is used for all subsequent relative path resolutions.
All flag arguments (like --build-dir and --file-list) are initially resolved relative to the command's current working directory (CWD) before being canonicalized.
BuildDir)The build directory is determined in the following order of precedence:
--build-dir command-line flag.${FuchsiaDir}/.fx-build-dir.out/default).BuildDir is resolved as filepath.Join(FuchsiaDir, line).If neither is provided, BuildDir will be empty. Queries that require a build directory (e.g., to find generated headers) will report an error during the execution phase.
Files)Users can specify files to query using either the --file flag or the --file-list flag. Both flags are repeatable.
--file: Specifies a single file path.--file-list: Specifies a path to a file containing a newline-separated list of file paths.Example: fx ide-query --file path/to/a.cc --file-list my_files.txt
If a file path provided to --file-list cannot be read, the tool will report an error and exit immediately.
When reading from a --file-list:
# are treated as comments and ignored.--file or inside a --file-list are always resolved relative to FuchsiaDir.--file scripts/main.go becomes ${FuchsiaDir}/scripts/main.go.${FuchsiaDir} are accepted and included in the Files list with their absolute paths.--file or inside a --file-list does not exist on disk, it is included in the Files list with a status of "not_found" and IsDirectory set to false.AbsPath, the tool will resolve symlinks for all existing parent directories and then append the missing filename to the canonicalized parent path.Files list with status "found" and IsDirectory set to true.OriginalPath field in FileEntry must contain the path as it was received from the flag or file list (before any prepending or canonicalization). If an empty string is provided as a path via --file, the tool will report an error and exit.FuchsiaDir and BuildDir) are converted to absolute paths and have symbolic links evaluated (e.g., via filepath.EvalSymlinks).OriginalPath of the last occurrence (based on the order they appear inside flags or across different flags on the command line) and discard the earlier ones.--file or --file-list, the tool will still succeed and return a WorkspaceContext with an empty Files list. It is not an error to query zero files.The tool uses the github.com/spf13/pflag package to support POSIX-style flags, consistent with other Fuchsia Go tools. This is provided via the GN dependency //third_party/golibs:github.com/spf13/pflag.
| Flag | Type | Description |
|---|---|---|
--fuchsia-dir | string | Overrides the Fuchsia root directory. |
--build-dir | string | Overrides the build output directory. |
--file | stringSlice | A path to a file to be queried. Can be repeated. |
--file-list | stringSlice | A path to a file containing a list of files to be queried. Can be repeated. |
Validation:
FuchsiaDir is provided and is an existing directory.BuildDir is non-empty, the tool verifies it is an existing directory.--file-list cannot be read.Output Format:
WorkspaceContext as a single JSON object to stdout with 2-space indentation.ErrorResponse as a single JSON object to stdout with 2-space indentation. The tool will exit with status 1 for all errors.Structure:
func NewWorkspaceContext(args []string) (*WorkspaceContext, error).main package.Immutability: Once initialized, the WorkspaceContext is treated as immutable. Query handlers should not modify the context.
NewWorkspaceContext will be tested using Go's t.TempDir() to create a temporary filesystem layout, ensuring correct resolution of .fx-build-dir and --file paths.