Validating Indexes (scip lint)
Relevant source files
The following files were used as context for generating this wiki page:
The scip lint command is a specialized diagnostic tool within the SCIP CLI designed to identify correctness, well-formedness, and redundancy issues in a SCIP index file. It is primarily intended for developers building SCIP indexers to ensure their output adheres to the protocol's requirements and best practices.
Sources: Development.md:61-64, CHANGELOG.md:188-189, cmd/scip/lint.go:14-17
Architecture and Data Flow
The linting process involves loading a SCIP index, constructing an internal symbol table to track relationships and occurrences, and performing multiple passes over the data to detect inconsistencies.
Validation Flow
The lintMainPure function orchestrates the validation by iterating through different components of the index:
- External Symbols: Validates that external symbols are not empty and are not duplicated.
- Documents: Checks for empty relative paths and duplicate document entries.
- Symbol Pass: populates the symbol table with local symbols and verifies their uniqueness within files.
- Relationship Pass: Checks that all symbol relationships link to valid symbols (either external or local) and have proper flags (e.g.,
is_definition,is_reference). - Occurrence Pass: Verifies that every occurrence in a document has a corresponding
SymbolInformationentry and that symbol names are canonical.
Sources: cmd/scip/lint.go:37-96
The following diagram illustrates the data flow from the SCIP index into the diagnostic error set:
Informational notes are provided for certain issues, such as skipping empty documents to continue diagnostics on other parts of the index.
Sources: cmd/scip/lint.go:57-61
Core Components
Internal Data Structures
The linter uses several private structures to maintain state during the validation process:
| Structure | Description |
|---|---|
symbolTable | Tracks extSyms, localSymsMap, and relsMap to detect cross-references and duplicates. |
errorSet | A collection of errors and warnings encountered during the linting process. |
occurrenceKey | A composite key of scip.Range and roles used to detect duplicate occurrences at the same location. |
fileOccurrenceMap | Maps document paths to a map of occurrences to track where symbols appear. |
Sources: cmd/scip/lint.go:105-125
Key Functions
lintSymbolString: Validates that a symbol string is non-empty, can be parsed byscip.ParseSymbol, and is in its canonical (formatted) form.
Sources: cmd/scip/lint.go:217-234addRelationship: Ensures that relationships have at least one valid role flag and that the destination symbol exists.
Sources: cmd/scip/lint.go:174-192addOccurrence: Checks that an occurrence's symbol is defined in the index and flags conflicts, such as a forward declaration being marked as a full definition.
Sources: cmd/scip/lint.go:194-213
Diagnostic Categories
The linter generates specific error and warning types based on the violation discovered:
Symbol and Document Integrity
- duplicateDocumentWarning: Triggered when multiple documents in the index share the same relative path. Sources: cmd/scip/lint.go:261-267
- bothLocalAndExternalSymbolError: Triggered if a symbol is defined both as an external symbol and within a local document. Sources: cmd/scip/lint.go:269-276
- nonCanonicalSymbolError: Triggered when a symbol string does not match its canonical formatting (e.g., unnecessary backticks). Sources: cmd/scip/lint.go:252-259
Relationship and Occurrence Logic
- missingRelationshipFlagError: Occurs when a relationship is defined without setting any of
is_definition,is_reference,is_type_definition, oris_implementation. Sources: cmd/scip/lint.go:278-286 - missingSymbolForOccurrenceError: Occurs when an occurrence references a symbol that has no corresponding
SymbolInformationin the index. Sources: cmd/scip/lint.go:303-311 - forwardDefIsDefinitionError: Triggered when a range is marked as both a
Definitionand aForwardDefinition. Sources: cmd/scip/lint.go:313-321
Usage and Implementation
The command is registered in the main SCIP application via lintCommand().
func lintCommand() cli.Command {
snapshot := cli.Command{
Name: "lint",
Usage: "Flag potential issues with a SCIP index",
Description: "Example usage:\n\n scip lint /path/to/index.scip\n\n" +
"You may want to filter the output using `grep -v <pattern>`\n" +
"to narrow down on certain classes of errors.",
Action: func(c *cli.Context) error {
indexPath := c.Args().Get(0)
if indexPath == "" {
return stderrors.New("missing argument for path to SCIP index")
}
return lintMain(indexPath)
},
}
return snapshot
}
Sources: cmd/scip/lint.go:14-31
Summary
scip lint serves as a critical quality assurance tool for SCIP indexers. By performing deep inspections of symbol canonicalization, relationship integrity, and occurrence placement, it helps prevent "blast radius" issues where indexer bugs (such as duplicate documents or missing symbol definitions) could degrade the code navigation experience.
Sources: DESIGN.md:33-35, cmd/scip/lint.go:37-40