{"id":25976794,"url":"https://github.com/cheekyghost-labs/indexstore","last_synced_at":"2025-03-05T04:24:33.152Z","repository":{"id":159128423,"uuid":"630001167","full_name":"CheekyGhost-Labs/IndexStore","owner":"CheekyGhost-Labs","description":"Swift library providing a query-based approach for searching for and working with Apple's indexstore-db library","archived":false,"fork":false,"pushed_at":"2025-01-23T06:50:31.000Z","size":823,"stargazers_count":37,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-02-25T12:07:22.530Z","etag":null,"topics":["apple","ios","macos","swift","xcode"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CheekyGhost-Labs.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-04-19T13:12:55.000Z","updated_at":"2025-02-11T21:37:59.000Z","dependencies_parsed_at":"2024-01-01T09:08:23.151Z","dependency_job_id":"eb637160-ae47-4a99-a40f-b37153c6a0a3","html_url":"https://github.com/CheekyGhost-Labs/IndexStore","commit_stats":{"total_commits":35,"total_committers":3,"mean_commits":"11.666666666666666","dds":0.4,"last_synced_commit":"431850480262b65a96065e15cb322b607249ad47"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CheekyGhost-Labs%2FIndexStore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CheekyGhost-Labs%2FIndexStore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CheekyGhost-Labs%2FIndexStore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CheekyGhost-Labs%2FIndexStore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CheekyGhost-Labs","download_url":"https://codeload.github.com/CheekyGhost-Labs/IndexStore/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241962701,"owners_count":20049667,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple","ios","macos","swift","xcode"],"created_at":"2025-03-05T04:24:32.603Z","updated_at":"2025-03-05T04:24:33.140Z","avatar_url":"https://github.com/CheekyGhost-Labs.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IndexStore\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FCheekyGhost-Labs%2FIndexStore%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/CheekyGhost-Labs/IndexStore) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FCheekyGhost-Labs%2FIndexStore%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/CheekyGhost-Labs/IndexStore)\n\nIndexStore is a library providing that provides a query-based approach for searching for and working with source symbols within an indexed code base. It is built on top of the [Apple IndexStoreDB Library](https://github.com/swiftlang/indexstore-db), which provides access to the index data produced by the swift compiler.\n\nWith this library, you can easily search for and analyze symbols in your code, making it a powerful tool for building developer tools, static analyzers, and code refactoring utilities.\n\n## Note:\n\nThe [Apple IndexStoreDB Library](https://github.com/apple/indexstore-db) is not considered stable yet as it has no resolvable semvar tags. This project points at a release branch found on the repo and is actively maintained.\n\n## Features:\n\n- Query symbols and occurrences in your Swift source code\n- Find the occurrences and references of symbols\n- Access detailed information about symbols, such as their USR, source file location, parent, inheritance, and more\n- Access detailed information about symbols (location, kind, parent, etc.)\n- Filter and customize queries with various options, such as restricting to the project directory or specific source files\n- Supports both Swift and Objective-C code\n- Retrieve symbols conforming to a specific protocol\n- Retrieve symbols subclassing a specific class\n- Find invocations of a specific symbol\n- Check if a symbol is invoked by a test case\n- Identify empty extensions\n\n### High Level Topics:\n\n`IndexStore` is a layer of abstraction over the `indexstore-db`, aimed at simplifying queries and making codebase exploration more intuitive. Here are the key concepts that drive its functionality:\n\n##### SourceSymbol: \nAt its core, every distinct named entity in your code, such as functions, classes, or variables, is represented as a symbol. When you query for symbols in `IndexStore`, you're seeking its primary definition and associated metadata.\n\n##### USR (Unified Symbol Resolution:\nThink of USR as the unique fingerprint of a symbol. It's a consistent identifier that ensures even if a symbol appears in various places or across projects, we know it's the same entity.\n\n##### Occurrence: \n`SourceSymbol` instances aren't just static entities; they live and breathe throughout your code. When you query for occurrences of a symbol, it aims to capture every specific instance or reference of a symbol in your project, revealing the footprint of that symbol in your codebase.\n\n##### Related Occurrences: \nBeyond just finding where a symbol exists or occurs, it's often vital to understand its broader context and relationships. Related Occurrences do just that, fetching symbols and instances that share a defined relationship with the queried symbol. This can encompass overrides, implementations, associations, and more, providing a richer tapestry of how a particular symbol interplays with others in your project.\n\n\n### Getting Started:\n\nTo use `IndexStore` in your project, you'll need to instantiate an index with a valid `Configuration` instance.\n\nThe `Configuration` holds, among other things, paths to the project directory, libIndexStore, and IndexStoreDB database. The only required value to get started is the `projectDirectory` location, which is the working directory of the project you are assessing.\n\nBy default the configuration will automatically resolve the required `indexStorePath` and `libIndexStorePath` based on the running process. This will use `xcode-select` and `ProcessInfo().environment` to derive the index store details for the project within the `projectDirectory`.\n\nYou can also override this by providing your own values.\n\n#### Instantiating:\n\nOnce you have your configuration ready, you can create an `IndexStore` instance:\n\n```swift\n// Manual Configuration\nlet configuration = Configuration(projectDirectory: \"path/to/project/root\")\ninstanceUnderTest = IndexStore(configuration: configuration)\n```\n\nThe `Configuration` is also `Decodable` and can be built from a JSON file:\n\n```swift\nlet configuration = try Configuration.fromJson(at: configPath)\ninstanceUnderTest = IndexStore(configuration: configuration)\n```\n\n#### Basic Usage\n\nOnce you have a configured `IndexStore` instance, you can begin querying for symbols:\n\n\n1. Import `IndexStore`:\n\n```swift\nimport IndexStore\n```\n\n2. Use the `IndexStore` instance to query for symbols, occurrences, or other information:\n\n```swift\n// Query for functions by name\nlet results = indexStore.querySymbols(.functions(\"someFunctionName\"))\n\n// Find all class symbols\nlet classSymbols = indexStore.querySymbols(.kinds([.class]))\n\n// Find all extensions of a type\nlet results = indexStore.querySymbols(.extensions(ofType: \"MyClass\"))\n\n// Find all extensions of a class within specific source files\nlet results = indexStore.querySymbols(.extensions(in: [\"path\", \"path\"], matching: \"XCTest\"))\n\n// Find all invocations of a function symbol\nlet function = indexStore.querySymbols(.functions(\"someFunctionName\"))[0]\nlet results = indexStore.invocationsOfSymbol(function)\n\n// Find all symbols declared in a specific file\nlet symbols = indexStore.querySymbols(\n    .withSourceFiles([\"/path/to/your/project/SourceFile.swift\"])\n    .withKinds(SourceKind.allCases)\n    .withRoles(.all)\n)\n```\n\n#### Occurrence Lookups\n\nOnce you have a symbol, whether by general querying or by plucking things from other results, you can also look up occurrences by a symbol (or usr). You can additionally provide a valid query to further filter results.\n\n```swift\n// Find UIColor declaration\nlet colorSymbol indexStore.querySymbols(\n    .withQuery(\"UIColor\")\n    .withAnchorStart(true)\n    .withAnchorEnd(true)\n    .withRestrictingToProjectDirectory(false)\n    .withKinds([.class])\n    .first!\n\n// Look up any occurrences of the UIColor symbol\nlet occurrences = indexStore.queryOccurrences(ofSymbol: colorSymbol, query: .empty)\n```\n\n#### Relation Lookups\n\nOnce you have a symbol, whether by general querying or by plucking things from other results, you can also look up related occurrences by a symbol (or usr). You can additionally provide a valid query to further filter results.\n\n```swift\n// Find UIColor declaration\nlet colorSymbol indexStore.querySymbols(\n    .withQuery(\"UIColor\")\n    .withAnchorStart(true)\n    .withAnchorEnd(true)\n    .withRestrictingToProjectDirectory(false)\n    .withKinds([.class])\n    .first!\n\n// Look up any occurrences of the UIColor symbol\nlet occurrences = indexStore.queryRelatedOccurences(ofSymbol: colorSymbol, query: .empty)\n```\n\n#### Convenience Methods\n\nIndexStore provides convenience methods for common static analysis tasks:\n\n- Find symbols conforming to a specific protocol:\n\n```swift\nlet conformingSymbols = indexStore.sourceSymbols(conformingToProtocol: \"SomeProtocol\")\n```\n\n- Find symbols subclassing a specific class:\n\n```swift\nlet subclassingSymbols = indexStore.sourceSymbols(subclassing: \"SomeClass\")\n```\n\n- Find invocations of a specific symbol:\n\n```swift\nlet invocations = indexStore.invocationsOfSymbol(someSymbol)\n```\n\n- Check if a symbol is invoked by a test case:\n\n```swift\nlet isInvokedByTestCase = indexStore.isSymbolInvokedByTestCase(someSymbol)\n```\n\n- Identify empty extensions:\n\n```swift\nlet emptyExtensions = indexStore.sourceSymbols(forEmptyExtensionsMatching: \"SomeType\")\n```\n\n## Installation\n\n### Swift Package Manager\n\nAdd the following to your `Package.swift` file:\n\n```swift\nlet package = Package(\n    // name, platforms, products, etc.\n    dependencies: [\n        // other dependencies\n        .package(url: \"https://github.com/CheekyGhost-Labs/IndexStore.git\", branch: \"release/3.0\"),\n    ],\n    targets: [\n        .executableTarget(name: \"\u003ccommand-line-tool\u003e\", dependencies: [\n            // other dependencies\n            .product(name: \"IndexStore\", package: \"IndexStore\")\n        ]),\n        // other targets\n    ]\n)\n```\n\n## License\n\nIndexStore is available under the MIT license. See the [LICENSE](LICENSE) file for more info.\n\n## Contribution\n\n### Submitting a Bug Report\n\nSwift Markdown tracks all bug reports with [GitHub Issues](https://github.com/CheekyGhost-Labs/IndexStore/issues).\nYou can use the \"IndexStore\" component for issues and feature requests specific to IndexStore.\nWhen you submit a bug report we ask that you are descriptive and include as much information as possible to document or re-create the issue.\n\n### Submitting a Feature Request\n\nFor feature requests, please feel free to file a [GitHub issue](https://github.com/CheekyGhost-Labs/IndexStore/issues/new)\n\nDon't hesitate to submit a feature request if you see a way IndexStore can be improved to better meet your needs.\n\n### Contributing to IndexStore\n\nDue to [Apple IndexStoreDB Library](https://github.com/apple/indexstore-db) repo using branches for releases rather than tagging stable versions, the IndexStore repo can't follow the traditional semvar and [Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) approach.\n\nThe approach IndexStore takes for releases is:\n- main: contains the latest stable release\n- develop: contains the latest stable changes pending release\n- release/\u003cmajor\u003e.minor: contains released code\n\nA release branch will have a semantic version without accounting for patch updates. For example\n\n```shell\nrelease/1.0\nrelease/1.1\n```\n\n- any `patch` changes (bug fixes and improvements that don't change the public interface) will be pulled into the appropriate release branch as needed.\n\n- any `minor` updates (publicly visible changes that are backwards compatible) will get their own release branch.\n\n- any `major` updates (publicly visible changes that are **not** backwards compatible) will get their own release branch.\n\nReleases will still be tagged for when the [Apple IndexStoreDB Library](https://github.com/apple/indexstore-db) becomes stable. This will also allow us to manage patch releases easier too.\n\nFor the most part, pull requests should be made against the `develop` branch to coordinate releases with multiple features and fixes. This also provides a means to test from the `develop` branch in the wild to further test pending releases. Once a release is ready it will be merged into `main` and release branches created/updated from the `main` branch.\n\nIf a fix for an older version is being made, the pull request can be made against the intended release branch, and the change can be worked into the other branches with the help of maintainers as needed.\n\nTo get started:\n\n1. **Fork the repository**: Start by creating a fork of the project to your own GitHub account.\n\n2. **Clone the forked repository**: After forking, clone your forked repository to your local machine so you can make changes.\n\n```shell\ngit clone https://github.com/CheekyGhost-Labs/IndexStore.git\n```\n\n3. **Create a new branch**: Before making changes, create a new branch for your feature or bug fix. Use a descriptive name that reflects the purpose of your changes.\n\n```shell\ngit switch -c your-feature-branch\n```\n\n4. **Follow the Swift Language Guide**: Ensure that your code adheres to the [Swift Language Guide](https://swift.org/documentation/api-design-guidelines/) for styling and syntax conventions.\n\n5. **Make your changes**: Implement your feature or bug fix, following the project's code style and best practices. Don't forget to add tests and update documentation as needed.\n\n6. **Commit your changes**: Commit your changes with a descriptive and concise commit message. Use the imperative mood, and explain what your commit does, rather than what you did.\n\n```shell\n\n# Feature\ngit commit -m \"Feature: Adding convenience method for resolving awesomeness\"\n\n\n# Bug\ngit commit -m \"Bug: Fixing issue where awesome query was not including awesome\"\n```\n\n7. **Pull the latest changes from the upstream**: Before submitting your changes, make sure to pull the latest changes from the upstream repository and merge them into your branch. This helps to avoid any potential merge conflicts.\n\n```shell\ngit pull origin develop\n```\n\n8. **Push your changes**: Push your changes to your forked repository on GitHub.\n\n```shell\ngit push origin your-feature-branch\n```\n\n9. **Submit a pull request**: Finally, create a pull request from your forked repository to the original repository, targeting the `develop` branch. Fill in the pull request template with the necessary details, and wait for the project maintainers to review your contribution.\n\n### Unit Testing\n\nPlease ensure you add unit tests for any changes. The aim is not `100%` coverage, but rather meaningful test coverage that ensures your changes are behaving as expected without negatively effecting existing behaviour.\n\nPlease note that the project maintainers may ask you to make changes to your contribution or provide additional information. Be open to feedback and willing to make adjustments as needed. Once your pull request is approved and merged, your changes will become part of the project!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheekyghost-labs%2Findexstore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcheekyghost-labs%2Findexstore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheekyghost-labs%2Findexstore/lists"}