{"id":18484796,"url":"https://github.com/butr/butr.harmony.analyzer","last_synced_at":"2025-04-08T19:31:36.798Z","repository":{"id":37021324,"uuid":"434619584","full_name":"BUTR/BUTR.Harmony.Analyzer","owner":"BUTR","description":"Roslyn analyzer for Harmony.","archived":false,"fork":false,"pushed_at":"2023-07-07T11:33:15.000Z","size":226,"stargazers_count":8,"open_issues_count":5,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-02T04:05:44.532Z","etag":null,"topics":["harmony","roslyn-analyzer"],"latest_commit_sha":null,"homepage":"","language":"C#","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/BUTR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-03T14:12:14.000Z","updated_at":"2024-09-02T15:46:29.000Z","dependencies_parsed_at":"2023-02-11T23:01:40.251Z","dependency_job_id":null,"html_url":"https://github.com/BUTR/BUTR.Harmony.Analyzer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BUTR%2FBUTR.Harmony.Analyzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BUTR%2FBUTR.Harmony.Analyzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BUTR%2FBUTR.Harmony.Analyzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BUTR%2FBUTR.Harmony.Analyzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BUTR","download_url":"https://codeload.github.com/BUTR/BUTR.Harmony.Analyzer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223342148,"owners_count":17129781,"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":["harmony","roslyn-analyzer"],"created_at":"2024-11-06T12:42:59.620Z","updated_at":"2024-11-06T12:43:00.338Z","avatar_url":"https://github.com/BUTR.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BUTR.Harmony.Analyzer\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/BUTR/BUTR.Harmony.Analyzer\" alt=\"Lines Of Code\"\u003e\n    \u003cimg src=\"https://tokei.rs/b1/github/BUTR/BUTR.Harmony.Analyzer?category=code\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.codefactor.io/repository/github/butr/butr.harmony.analyzer\"\u003e\n    \u003cimg src=\"https://www.codefactor.io/repository/github/butr/butr.harmony.analyzer/badge\" alt=\"CodeFactor\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codeclimate.com/github/BUTR/BUTR.Harmony.Analyzer/maintainability\"\u003e\n    \u003cimg alt=\"Code Climate maintainability\" src=\"https://img.shields.io/codeclimate/maintainability-percentage/BUTR/BUTR.Harmony.Analyzer\"\u003e\n  \u003c/a\u003e\n  \u003c!--\n  \u003ca href=\"https://butr.github.io/BUTR.Harmony.Analyzer\" alt=\"Documentation\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Documentation-%F0%9F%94%8D-blue?style=flat\" /\u003e\n  \u003c/a\u003e\n  --\u003e\n  \u003c/br\u003e\n  \u003ca href=\"https://github.com/BUTR/BUTR.Harmony.Analyzer/actions/workflows/test.yml?query=branch%3Amaster\"\u003e\n    \u003cimg alt=\"GitHub Workflow Status (event)\" src=\"https://img.shields.io/github/workflow/status/BUTR/BUTR.Harmony.Analyzer/Test?branch=master\u0026label=Tests\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/BUTR/BUTR.Harmony.Analyzer\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/BUTR/BUTR.Harmony.Analyzer/branch/master/graph/badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003c/br\u003e\n  \u003ca href=\"https://www.nuget.org/packages/BUTR.Harmony.Analyzer\" alt=\"NuGet BUTR.Harmony.Analyzer\"\u003e\n    \u003cimg src=\"https://img.shields.io/nuget/v/BUTR.Harmony.Analyzer.svg?label=NuGet%20BUTR.Harmony.Analyzer\u0026colorB=blue\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nA Roslyn analyzer for [`Harmony`](https://github.com/pardeike/Harmony) which adds the ability to do dynamic type checking and ensures that there are no typos when using the AccessTools* methods.\n\nFor example, if the user wants to access `_privateField` from some class/struct, but typed instead `_privateFld`, the analyzer will highlight that. It leverages the [`System.Reflection.Metadata`](https://www.nuget.org/packages/System.Reflection.Metadata/) package for fast analysys or public and non-public members of types, since Roslyn can't access non public members.\n\nThis drastically reduces runtime errors when using Harmony.\n\nAlso, when speaking in long-term maintenance of mods, if the game's internal API changes and a type member will be renamed or it will be changed to another type (e.g. field to a property), the analyzer will highlight that.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn.discordapp.com/attachments/422092475163869201/987282699347714078/unknown.png\" width=\"800\" /\u003e\n\u003c/p\u003e\n\n```csharp\n// The analyzer works only when full data is provided for the method in compile-time\n// so the following methods will work:\nAccessTools.Method(typeof(Class), \"MemberName\");\nAccessTools.Method(\"System.Class:MemberName\");\n\n// But this won't be supported, because the information will be available only at runtime\nType type = ExternalMethod();\nAccessTools.Method(type, \"MemberName\");\n```\n\n\n## Rules\n\nYou'll find the rules in the documentation: [the rules and their explanation](https://github.com/BUTR/BUTR.Harmony.Analyzer/tree/master/docs)\n\n## Installation\n\n- NuGet package (recommended): \u003chttps://www.nuget.org/packages/BUTR/BUTR.Harmony.Analyzer/\u003e\n\n## Supported API\nSupports `AccessTools` classes from [`Harmony`](https://github.com/pardeike/Harmony), [`HarmonyX`](https://github.com/BepInEx/HarmonyX) and [`Harmony.Extensions`](https://github.com/BUTR/Harmony.Extensions).  \nAs long as the class starts with `AccessTools`, it will be supported.  \nThe following API's are supported:\n* Constructor/DeclaredConstructor\n* Field/DeclaredField\n* Property/DeclaredProperty\n* Method/DeclaredMethod\n* PropertyGetter/DeclaredPropertyGetter\n* PropertySetter/DeclaredPropertySetter\n* Delegate/DeclaredDelegate\n* FieldRefAccess\n* StaticFieldRefAccess\n* StructFieldRefAccess\n\n## Additional Analyzers\nWe provide conversions from static typed check from AccessTools and SymbolExtensions to dynamic string based, marked by default as suggestions.\n\nWe believe that static typed member check (via `typeof(Type)`) adds more problems than it solves, because we are bound to the public ABI of the library that is patched.  \nInstead, we suggest to use dynamic typed member check (via a string containing the full name of the type).  \nCommon sense would suggest that this is a bad idea, since you can't check whether the member you want to get exists, but the sole purpose of `BUTR.Harmony.Analyzer` is to solve this exact problem by creating warnings at compile time if the type was not found.\n\nOne of the most common problems that is solved is type namespace moving, since it breaks the public ABI.  \nUsually, the modder won't notice that a type was moved if both old and new namespaces are referenced and the full name of the type is not used. It will compile, but won't be binary compatible.  \nThe dynamic typed check requires the full name of the type, so a namespace change will create a warning that the type does not exists.  \nThere is a edge case that is not covered by the analyzer - moving a type within different assemblies with keeping the exact namespace.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbutr%2Fbutr.harmony.analyzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbutr%2Fbutr.harmony.analyzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbutr%2Fbutr.harmony.analyzer/lists"}