{"id":28403339,"url":"https://github.com/workiva/over_react_codemod","last_synced_at":"2025-07-02T09:05:34.480Z","repository":{"id":37502699,"uuid":"143073092","full_name":"Workiva/over_react_codemod","owner":"Workiva","description":"Codemods to help consumers of over_react automate the migration of UI component code.","archived":false,"fork":false,"pushed_at":"2025-06-10T00:07:03.000Z","size":2941,"stargazers_count":2,"open_issues_count":12,"forks_count":7,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-06-10T01:21:36.032Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Workiva.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-07-31T21:41:41.000Z","updated_at":"2025-01-25T16:51:38.000Z","dependencies_parsed_at":"2023-10-12T16:42:56.738Z","dependency_job_id":"d4bd61e8-7a2d-4a34-b45e-7e29984dc98b","html_url":"https://github.com/Workiva/over_react_codemod","commit_stats":null,"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/Workiva/over_react_codemod","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workiva%2Fover_react_codemod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workiva%2Fover_react_codemod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workiva%2Fover_react_codemod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workiva%2Fover_react_codemod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Workiva","download_url":"https://codeload.github.com/Workiva/over_react_codemod/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workiva%2Fover_react_codemod/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262151662,"owners_count":23266919,"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":[],"created_at":"2025-06-01T17:36:28.832Z","updated_at":"2025-07-02T09:05:34.471Z","avatar_url":"https://github.com/Workiva.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Over React Codemods\n\n[![Pub](https://img.shields.io/pub/v/over_react_codemod.svg)](https://pub.dartlang.org/packages/over_react_codemod)\n[![Build Status](https://github.com/Workiva/over_react_codemod/workflows/Dart%20CI/badge.svg?branch=master)](https://github.com/Workiva/over_react_codemod/actions?query=workflow%3A%22Dart+CI%22+branch%3Amaster)\n\n\u003e **Built with [dart_codemod][dart_codemod].**\n\nCodemods to help consumers of [over_react][over_react] automate the migration of\nUI component code. \n\n## Installation\n\n\u003e Note: this package requires Dart SDK version 2.1.0 to run, but the codemods\n\u003e themselves are designed to run on code that is written for Dart 1.x or 2.x.\n\n```bash\ndart pub global activate over_react_codemod\n```\n\nOnce you've activated this package, you should be able to run whichever codemods\nyou need via `pub global run`.\n\n\n## Internationalization Codemod\n\nThis package provides a `intl_message_migration` codemod that will modify existing UI component code to make them available for internationalization.\n\nFor more information, please see the [INTL Message Codemod Readme](docs/intl_message.md)\n\n## Dart 1 to Dart 2 Codemod\n\nThe `dart2_upgrade` codemod that used to be provided by this package is no longer available.\n\nTo use it, you'll need over_react_codemod 1.1.0 instead of the latest, which also must be used with Dart 2.1.0:\n```sh\nasdf install dart 2.1.0\nasdf shell dart 2.1.0\npub global activate over_react_codemod 1.1.0\n```\nOnce that's set up, see the `dart2_upgrade` documentation here: https://github.com/Workiva/over_react_codemod/tree/1.1.0#dart-1-to-dart-2-codemod\n\n## Checking for Regressions\n\nEspecially in the case where a forwards- and backwards-compatible version of\nyour code is necessary, it can be helpful to be able to check automatically for\nregressions after having initially migrated your code. Doing so will help\nprevent accidentally merging code that doesn't meet your compatability\nexpectations.\n\nEach of these codemods can be run in a `--fail-on-changes` mode that will count\nthe number of changes that _would_ have been suggested and exit with a non-zero\nexit code if that number is greater than 0.\n\nAs an example, adding the following command to your CI process or pre-merge\nchecklist will prevent merging code that is not in the form that is compatible\nwith both Dart 1 and Dart 2:\n\n```bash\ndart pub global run over_react_codemod:dart2_upgrade --fail-on-changes\n```\n\n## Ignoring Codemod Suggestions\n\nSome of the changes provided by the codemods in this package are based on\nimperfect heuristics (e.g. looking for a specific naming convention) and\nconsequently may be susceptible to false positives. If you hit such a case in\nyour codebase, you can tell the codemod to ignore a certain line by attaching an\nignore comment either on the same line or the immediately preceding line.\n\nFor example, consider a mixin usage that happens to match the naming convention\nof ending with `StateMixin`, but isn't actually an over_react state mixin:\n\n```dart\nclass Foo extends Object with BarStateMixin {}\n```\n\nAs is, the `dart2_upgrade --backwards-compat` codemod would find this code and\nattempt to change it to:\n\n```dart\nclass Foo extends Object\n    with\n        BarStateMixin,\n        // ignore: mixin_of_non_class, undefined_class\n        $BarStateMixin {}\n```\n\nBut if `BarStateMixin` isn't actually an over_react state mixin, then this\nupdated code will fail. To avoid this problem, simply add an `// orcm_ignore`\ncomment to the mixin type that should be ignored:\n\n```dart\nclass Foo extends Object\n    with\n        // orcm_ignore\n        BarStateMixin {}\n```\n\nThis ignore mechanism works with any of the changes that the codemods in this\npackage will try to suggest.\n\n\n## Authoring codemods\n\n### Resources\n\n- Analyzer package\n    - [AST documentation](https://github.com/dart-lang/sdk/blob/master/pkg/analyzer/doc/tutorial/ast.md)\n    - [Element model documentation](https://github.com/dart-lang/sdk/blob/master/pkg/analyzer/doc/tutorial/element.md)\n      - (the element model is only accessible from \"resolved AST\")\n    - In general, the various `AstNode` and `Element` subclasses are well-documented, and are very helpful in describing the relationships between different types of nodes/elements and pointing to other classes. Reading those and clicking through the references is a good way to learn about specific structures, and help get your bearings.\n- [codemod][dart_codemod] package\n\n### Best practices\n\n- Code defensively for edge-cases, and avoid assumptions about the AST or Element model.\n\n    Some codemods process a lot of code, especially when identifying code that should be operated on, and some of that code may have structures you don't expect.\n\n    That doesn't necessarily mean your codemod should handle every single edge-case, but generally it shouldn't break with uncaught exceptions when it encounters certain code.\n\n    Things to avoid assumptions about:\n\n    - The types or nullability of child/parent nodes\n        - Prefer type checks over casts\n          - `tryCast()` and `ancestorOfType()` can be handy in certain cases.\n        - Prefer null-checks over `!`\n    - The number of child nodes or other items in collections\n        - When using `.first`/`.last`/`.single` on iterables, either check the length of the iterable first, or switch to something more conditional like `.firstWhere()` or `.firstOrNull`\n\n- Avoid using `childEntities`\n\n    Most AST node classes have getters for their different child nodes. Using these helps make code easier to read, and also provide typing (and nullability) which helps with static analysis and autocomplete.\n\n    If you're manually traversing the AST trying to find a certain descendant, consider whether a visitor-based implementation would be better.\n\n- Avoid using `AstNode.toSource()` (or `.toString()`) outside of tests\n\n    - To identify relevant code. There may be different syntax variations (either current or in future Dart versions) of code that unintentionally wouldn't be a match.\n\n        For example, if we were doing `expression.toSource() == 'foo.bar()'`, we would miss the following cases:\n        ```dart\n        foo..bar();\n        foo?.bar();\n        namespaced_import.foo.bar();\n        foo.bar(optionalArgAddedInSubclass: true);\n        ```\n\n        Instead, we could check for the method name via:\n        ```dart\n        expression is MethodInvocation \u0026\u0026 expression.methodName.name == 'bar'\n        ```\n        and change the foo check to something else, depending on the use-case:\n        ```dart\n        // Check whether the target is a \"foo\" identifier\n        // (though this doesn't handle prefixed cases)\n        expression.realTarget?.tryCast\u003cIdentifier\u003e()?.name == 'foo'\n        // Check whether it statically points to a `foo` variable\n        expression.realTarget?.tryCast\u003cIdentifier\u003e()?.staticElement?.name == 'foo');\n        // Or, Check whether it's a `Foo` object:\n        isFooType(expression.realTarget?.staticType);\n        // (Or, something else)\n        ```\n\n        For cases where the syntax seems simple enough where variations shouldn't be a problem, there are usually APIs that provide the value you're looking for.\n\n        ```dart\n        final identifier = parseIdentifier('foo');\n        identifier.name; // 'foo'\n\n        final boolean = parseBooleanLiteral('false');\n        boolean.value; // false\n\n        final import = parseImportDirective('import \"package:foo/foo.dart\";');\n        import.uriContent; // 'package:foo/foo.dart'\n        ```\n\n    - For building patch strings (such as when moving code from one place to another).\n\n        `toSource()` provides an approximation of the source, and may be missing comments or have different whitespace. If needed, use the `context.sourceFile` to get the original source for a given node.\n\n- Don't make assumptions about existing whitespace and line breaks.\n\n    There are different ways code can be formatted with dartfmt, and some code may not be formatted at all, so it's unsafe to make assumptions.\n\n    For instance, if you'd like to yield a patch that deletes a newline with some code, either check for its existence first by getting the source or line number of that offset in `context.sourceFile`. Or, instead of deleting from `node.offset`, delete from the end of the previous token (`node.prevToken?.end ?? node.offset`) to take any whitespace between those nodes with it.\n\n[dart_codemod]: https://github.com/Workiva/dart_codemod\n[over_react]: https://github.com/Workiva/over_react\n[over_react_dart2]: https://github.com/Workiva/over_react/blob/master/doc/dart2_migration.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkiva%2Fover_react_codemod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkiva%2Fover_react_codemod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkiva%2Fover_react_codemod/lists"}