[
  {
    "path": ".gitignore",
    "content": "/node_modules\r\n/.vs\r\n/bin\r\n/dist\r\n/obj\r\n/temp\r\n/temp\r\n*.js.map\r\n*.suo\r\n*.csproj\r\n*.csproj.user\r\n*.sln\r\n/packages/ts-nameof/temp/\r\n/packages/*/dist/\r\n/packages/*/node_modules/\r\n*.tsbuildinfo\r\n# Logs\r\n*.log\r\nnpm-debug.log*\r\nyarn-debug.log*\r\nyarn-error.log*\r\n\r\n# Runtime data\r\n*.pid\r\n*.seed\r\n*.pid.lock\r\n\r\n# Directory for instrumented libs generated by jscoverage/JSCover\r\nlib-cov\r\n\r\n# Coverage directory used by tools like istanbul\r\ncoverage\r\n\r\n# nyc test coverage\r\n.nyc_output\r\n\r\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\r\n.grunt\r\n\r\n# Bower dependency directory (https://bower.io/)\r\nbower_components\r\n\r\n# node-waf configuration\r\n.lock-wscript\r\n\r\n# Compiled binary addons (https://nodejs.org/api/addons.html)\r\nbuild/Release\r\n\r\n# Dependency directories\r\nnode_modules/\r\njspm_packages/\r\n\r\n# Optional npm cache directory\r\n.npm\r\n\r\n# Optional eslint cache\r\n.eslintcache\r\n\r\n# Optional REPL history\r\n.node_repl_history\r\n\r\n# Output of 'npm pack'\r\n*.tgz\r\n\r\n# Yarn Integrity file\r\n.yarn-integrity\r\n\r\n# dotenv environment variables file\r\n.env\r\n\r\n# next.js build output\r\n.next\r\n\r\n# OS X temporary files\r\n.DS_Store\r\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\r\nnode_js:\r\n  - '16'\r\nscript:\r\n  - set -e\r\n\r\n  - yarn install\r\n  - yarn build\r\n  - yarn verify\r\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run transforms-babel tests\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run\", \"--prefix\", \"packages/transforms-babel\", \"test:debug\"],\n      \"port\": 9229,\n      \"stopOnEntry\": false\n    },\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run transforms-common tests\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run\", \"--prefix\", \"packages/transforms-common\", \"test:debug\"],\n      \"port\": 9229,\n      \"stopOnEntry\": false\n    },\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run transforms-ts tests\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run\", \"--prefix\", \"packages/transforms-ts\", \"test:debug\"],\n      \"port\": 9229,\n      \"stopOnEntry\": false\n    },\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run ts-nameof.macro tests\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run\", \"--prefix\", \"packages/ts-nameof.macro\", \"test:debug\"],\n      \"port\": 9229,\n      \"stopOnEntry\": false\n    },\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run ts-nameof tests\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run\", \"--prefix\", \"packages/ts-nameof\", \"test:debug\"],\n      \"port\": 9229,\n      \"stopOnEntry\": false\n    }\n  ]\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n- Using welcoming and inclusive language\n- Being respectful of differing viewpoints and experiences\n- Gracefully accepting constructive criticism\n- Focusing on what is best for the community\n- Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n- Trolling, insulting/derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team on twitter via direct message at\nhttps://twitter.com/DavidSherret (DMs open). All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Logging Bugs\n\n1. Start logging an issue in the [issue tracker](https://github.com/dsherret/ts-nameof/issues).\n2. Clearly identify the problem and submit some reproduction code.\n   - Prune the reproduction to remove needless details.\n3. State the current and expected behaviour.\n4. State the version of ts-nameof (always show a reproduction of the bug on the latest version).\n\n# Contributing Bug Fixes\n\n1. Follow the instructions above about logging a bug. In addition:\n   1. State that you are going to work on the bug.\n   2. Discuss major structural changes in the issue before doing the work to ensure it makes sense and work isn't wasted.\n2. Start working on the fix in a branch and submit a PR when done.\n3. Ensure `yarn verify` passes when run in the root directory.\n\n# Contributing Features\n\n1. Log an issue in the [issue tracker](https://github.com/dsherret/ts-nameof/issues). In the issue:\n   1. Propose the change.\n      - Outline all changes that will be made to the public API.\n      - Discuss any structural changes to the code if necessary.\n   2. Wait for discussion and green light from [@dsherret](https://github.com/dsherret) (who will try to reply as soon as possible, but it might take a few days).\n      - Note: If the change is small and you think it wouldn't take you too much time, then feel free to start working on it and even submit a PR. Just beware that you're taking the risk that it could be denied.\n2. After approval, start working on the change in a branch and submit a PR.\n3. Read [DEVELOPMENT.md](DEVELOPMENT.md) for some useful information.\n4. Ensure `yarn verify` passes when run in the root directory.\n"
  },
  {
    "path": "DEVELOPMENT.md",
    "content": "# Development\n\n## Building\n\nOpen the root directory of the repo and run:\n\n```bash\n# install dependencies\nyarn install\n# build\nyarn build\n```\n\n## Packages\n\n- [packages/babel-plugin-ts-nameof](packages/babel-plugin-ts-nameof) - Transform plugin for Babel.\n- [packages/common](packages/common) - Common code used by almost everything.\n- [packages/scripts-common](packages/scripts-common) - Common scripts used by other packages.\n- [packages/tests-common](packages/tests-common) - Tests used by some packages. Write all your transform tests here.\n- [packages/transforms-babel](packages/transforms-babel) - Transforms from the Babel AST to the Common AST.\n- [packages/transforms-common](packages/transforms-common) - Nameof transforms done in the Common AST.\n- [packages/transforms-ts](packages/transforms-ts) - Transforms from the TypeScript AST to the Common AST.\n- [packages/ts-nameof](packages/ts-nameof) - ts-nameof library for the TypeScript compiler.\n- [packages/ts-nameof.macro](packages/ts-nameof) - ts-nameof.macro library for Babel macros.\n\n## Standard Commands\n\n```bash\n# build (run in root dir)\nyarn build\n# run tests (run in root dir)\nyarn test\n# format the code (download dprint from dprint.dev)\ndprint fmt\n```\n\n### Clean Rebuild\n\n```\nyarn clean && yarn build\n```\n\n## Declaration File\n\n### Global Definitions\n\nThe global definitions are stored in [lib/global.d.ts](lib/global.d.ts). To make changes:\n\n1. Add a failing test in [lib/global.tests.ts](lib/global.tests.ts) (failing test means you get a compile error)\n2. Update [lib/global.d.ts](lib/global.d.ts).\n3. Run `yarn create-declaration-file` in the root directory\n\n### ts-nameof - Updating API\n\n1. Update [packages/ts-nameof/lib/declarationFileTests.ts](packages/ts-nameof/lib/declarationFileTests.ts) with a failing test.\n2. Update the API in [packages/ts-nameof/src/main.ts](packages/ts-nameof/src/main.ts).\n3. Run `yarn create-declaration-file` in the root directory\n\n## After Development\n\nRun the following command in the root directory, which will check that everything is good:\n\n```bash\nyarn verify\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 David Sherret\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# ts-nameof\n\n[![Build Status](https://travis-ci.org/dsherret/ts-nameof.svg)](https://travis-ci.org/dsherret/ts-nameof)\n\n[`nameof`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/nameof) in TypeScript.\n\nMonorepo for ts-nameof projects:\n\n- [ts-nameof](packages/ts-nameof) (TypeScript compiler)\n- [babel-plugin-ts-nameof](packages/babel-plugin-ts-nameof) (Babel compiler)\n- [ts-nameof.macro](packages/ts-nameof.macro) (Babel compiler)\n\n## Recommend: Don't use this package\n\nSee [here](https://github.com/dsherret/ts-nameof/issues/121).\n\n## Setup\n\nts-nameof is a _compile time transform_ so it requires some setup. For setup instructions, see the packages above for the compiler you use.\n\n## nameof transform\n\n### `nameof(...)`\n\n```ts\nnameof(console);\nnameof(console.log);\nnameof(console[\"warn\"]);\n```\n\nTransforms to:\n\n```ts\n\"console\";\n\"log\";\n\"warn\";\n```\n\n### `nameof<T>()`\n\n```ts\nnameof<MyInterface>();\nnameof<Array<MyInterface>>();\nnameof<MyNamespace.MyInnerInterface>();\n```\n\nTransforms to:\n\n```ts\n\"MyInterface\";\n\"Array\";\n\"MyInnerInterface\";\n```\n\nThis is useful when working in the type domain.\n\n### `nameof<T>(o => ...)`\n\n```ts\nnameof<MyInterface>(o => o.prop);\n```\n\nTransforms to:\n\n```ts\n\"prop\";\n```\n\n## nameof.full transform\n\n### `nameof.full(...)`\n\n```ts\nnameof.full(console.log);\nnameof.full(window.alert.length, 1);\nnameof.full(window.alert.length, 2);\nnameof.full(window.alert.length, -1);\nnameof.full(window.alert.length, -2);\nnameof.full(window.alert.length, -3);\n```\n\nTransforms to:\n\n```ts\n\"console.log\";\n\"alert.length\";\n\"length\";\n\"length\";\n\"alert.length\";\n\"window.alert.length\";\n```\n\n### `nameof.full<T>()`\n\n```ts\nnameof.full<MyNamespace.MyInnerInterface>();\nnameof.full<MyNamespace.MyInnerInterface>(1);\nnameof.full<Array<MyInterface>>();\n```\n\nTransforms to:\n\n```ts\n\"MyNamespace.MyInnerInterface\";\n\"MyInnerInterface\";\n\"Array\";\n```\n\n### `nameof.full<T>(o => ...)`\n\n```ts\nnameof.full<MyInterface>(o => o.prop.prop2);\nnameof.full<MyInterface>(o => o.prop.prop2.prop3, 1);\n```\n\nTransforms to:\n\n```ts\n\"prop.prop2\";\n\"prop2.prop3\";\n```\n\n### `nameof.interpolate(value)`\n\nWriting the following:\n\n```ts\nnameof.full(myObj.prop[i]);\n```\n\n...does not interpolate the node in the computed property.\n\n```ts\n\"myObj.prop[i]\";\n```\n\nIf you want to interpolate the value then you can specify that explicitly with a `nameof.interpolate` function.\n\n```ts\nnameof.full(myObj.prop[nameof.interpolate(i)]);\n```\n\nTransforms to:\n\n```ts\n`myObj.prop[${i}]`;\n```\n\n## nameof.toArray transform\n\nContributed by: [@cecilyth](https://github.com/cecilyth)\n\n### `nameof.toArray(...)`\n\n```ts\nnameof.toArray(myObject, otherObject);\nnameof.toArray(obj.firstProp, obj.secondProp, otherObject, nameof.full(obj.other));\n```\n\nTransforms to:\n\n```ts\n[\"myObject\", \"otherObject\"];\n[\"firstProp\", \"secondProp\", \"otherObject\", \"obj.other\"];\n```\n\n### `nameof.toArray<T>(o => [...])`\n\n```ts\nnameof.toArray<MyType>(o => [o.firstProp, o.otherProp.secondProp, o.other]);\nnameof.toArray<MyType>(o => [o.prop, nameof.full(o.myProp.otherProp, 1)]);\n```\n\nTransforms to:\n\n```ts\n[\"firstProp\", \"secondProp\", \"other\"];\n[\"prop\", \"myProp.otherProp\"];\n```\n\n## nameof.split transform\n\nContributed by: [@cecilyth](https://github.com/cecilyth)\n\n### `nameof.split(...)`\n\n```ts\nnameof.split(myObj.prop.prop2);\nnameof.split(myObj.prop.prop2, 1);\nnameof.split(myObj.prop.prop2, -1);\nnameof.split(myObj.prop.prop2).join(\"/\");\n```\n\nTransforms to:\n\n```ts\n[\"myObj\", \"prop\", \"prop2\"];\n[\"prop\", \"prop2\"];\n[\"prop2\"];\n[\"myObj\", \"prop\", \"prop2\"].join(\"/\"); // \"myObj/prop/prop2\"\n```\n\n### `nameof.split<T>(o => ...)`\n\n```ts\nnameof.split<MyInterface>(o => o.prop.prop2.prop3);\nnameof.split<MyInterface>(o => o.prop.prop2.prop3, 1);\nnameof.split<MyInterface>(o => o.prop.prop2.prop3, -1);\nnameof.split<IState>(s => s.a.b.c).join(\"/\");\n```\n\nTransforms to:\n\n```ts\n[\"prop\", \"prop2\", \"prop3\"];\n[\"prop2\", \"prop3\"];\n[\"prop3\"];\n[\"a\", \"b\", \"c\"].join(\"/\"); // \"a/b/c\"\n```\n\n## Other\n\n- [Contributing](CONTRIBUTING.md)\n- [Development](DEVELOPMENT.md)\n"
  },
  {
    "path": "dprint.json",
    "content": "{\n  \"incremental\": true,\n  \"lineWidth\": 160,\n  \"indentWidth\": 2,\n  \"includes\": [\"**/*.{ts,tsx,js,jsx,json,md}\"],\n  \"excludes\": [\n    \"common\",\n    \"**/node_modules\",\n    \"**/*-lock.json\"\n  ],\n  \"plugins\": [\n    \"https://plugins.dprint.dev/typescript-0.60.0.wasm\",\n    \"https://plugins.dprint.dev/json-0.7.0.wasm\",\n    \"https://plugins.dprint.dev/markdown-0.11.3.wasm\"\n  ]\n}\n"
  },
  {
    "path": "lib/global.d.ts",
    "content": "/**\n * Gets a string representation of the final identifier of the given expression.\n *\n * @example nameof<MyInterface>() -> \"MyInterface\"\n * @example nameof<Array<MyInterface>>() -> \"Array\"\n * @example nameof<MyNamespace.MyInnerInterface>() -> \"MyInnerInterface\"\n * @example nameof<MyInterface>(o => o.prop) -> \"prop\"\n *\n * @param func An optional function for which the last identifier of the expression will be parsed.\n */\ndeclare function nameof<T>(func?: (obj: T) => any): string;\n\n/**\n * Gets a string representation of the last identifier of the given expression.\n *\n * @example nameof(console) -> \"console\"\n * @example nameof(console.log) -> \"log\"\n * @example nameof(console[\"warn\"]) -> \"warn\"\n *\n * @param obj An expression for which the last identifier will be parsed.\n */\ndeclare function nameof(obj: any): string;\n\ndeclare namespace nameof {\n  /**\n   * Gets the string representation of the entire type parameter expression.\n   *\n   * @example nameof.full<MyNamespace.MyInnerInterface>() -> \"MyNamespace.MyInnerInterface\"\n   * @example nameof.full<MyNamespace.MyInnerInterface>(1) -> \"MyInnerInterface\"\n   * @example nameof.full<Array<MyInterface>>() -> \"Array\"\n   * @example nameof.full<MyNamespace.AnotherNamespace.MyInnerInterface>>(-1) -> \"MyInnerInterface\"\n   *\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full<T>(periodIndex?: number): string;\n\n  /**\n   * Gets the string representation of the entire resultant expression.\n   *\n   * @example nameof.full<MyInterface>(o => o.prop.prop2) -> \"prop.prop2\"\n   * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, 1) -> \"prop2.prop3\"\n   * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, -1) -> `\"prop3\"\n   *\n   * @param func A function for which the result will be parsed, excluding the parameter's identifier.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full<T>(func: (obj: T) => any, periodIndex?: number): string;\n\n  /**\n   * Gets the string representation of the entire given expression.\n   *\n   * @example nameof.full(console.log) -> \"console.log\"\n   * @example nameof.full(window.alert.length, -1) -> \"length\"\n   * @example nameof.full(window.alert.length, 2) -> \"length\"\n   *\n   * @param obj The expression which will be parsed.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full(obj: any, periodIndex?: number): string;\n\n  /**\n   * Gets an array containing the string representation of the final identifier of each expression in the array returned by the provided function.\n   *\n   * @example nameof.toArray<MyType>(o => [o.firstProp, o.otherProp.secondProp, o.other]) -> [\"firstProp\", \"secondProp\", \"other\"]\n   * @example nameof.toArray<MyType>(o => [o.prop, nameof.full(o.myProp.otherProp, 1)]) -> [\"prop\", \"myProp.otherProp\"]\n   *\n   * @param func A function returning an array of expressions to be parsed, excluding the parameter's identifier.\n   */\n  function toArray<T>(func: (obj: T) => any[]): string[];\n\n  /**\n   * Gets an array containing the string representation of each expression in the arguments.\n   *\n   * @example nameof.toArray(myObject, otherObject) -> [\"myObject\", \"otherObject\"]\n   * @example nameof.toArray(obj.firstProp, obj.secondProp, otherObject, nameof.full(obj.other)) -> [\"firstProp\", \"secondProp\", \"otherObject\", \"obj.other\"]\n   *\n   * @param args An array of expressions to be parsed.\n   */\n  function toArray(...args: any[]): string[];\n\n  /**\n   * Embeds an expression into the string representation of the result of nameof.full.\n   *\n   * @example nameof.full(myObj.prop[nameof.interpolate(i)]) -> `myObj.prop[${i}]`\n   *\n   * @param value The value to interpolate.\n   */\n  function interpolate<T>(value: T): T;\n\n  /**\n   * Gets an array of strings where each element is a subsequent part of the expression provided.\n   *\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3) -> [\"prop\", \"prop2\", \"prop3\"]\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, 1) -> [\"prop2\", \"prop3\"]\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, -1) -> [\"prop\", \"prop2\"]\n   *\n   * @param func A function for which the resultant parts will be parsed, excluding the parameter's identifier.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function split<T>(func: (obj: T) => any, periodIndex?: number): string[];\n\n  /**\n   * Gets an array of strings where each element is a subsequent part of the expression provided.\n   *\n   * @example nameof.split(myObj.prop.prop2.prop3) -> [\"myObj\", \"prop\", \"prop2\", \"prop3\"]\n   * @example nameof.split(myObj.prop.prop2.prop3, -3);`, `[\"prop\", \"prop2\", \"prop3\"];\n   * @example nameof.split(myObj.prop.prop2.prop3, 2);`, `[\"prop2\", \"prop3\"]\n   *\n   * @param obj An expression for which the parts will be parsed.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function split(obj: any, periodIndex?: number): string[];\n}\n"
  },
  {
    "path": "lib/global.tests.ts",
    "content": "/// <reference path=\"./global.d.ts\" />\nnamespace TestNamespace {\n  export interface TestType {\n    prop: string;\n  }\n}\n\nclass TestClass {\n  prop1 = \"\";\n  prop2 = \"\";\n}\n\n// nameof tests\nnameof(TestClass); // $ExpectType string\nnameof<TestNamespace.TestType>(); // $ExpectType string\nnameof<TestClass>(t => t.prop1); // $ExpectType string\n\n// nameof.full tests\nconst testInstance = new TestClass();\nnameof.full(testInstance.prop1); // $ExpectType string\nnameof.full(testInstance.prop1, 1); // $ExpectType string\nnameof.full<TestNamespace.TestType>(); // $ExpectType string\nnameof.full<TestNamespace.TestType>(1); // $ExpectType string\nnameof.full<TestClass>(t => t.prop1); // $ExpectType string\nnameof.full<TestClass>(t => t.prop1, 1); // $ExpectType string\n\n// nameof.toArray tests\nnameof.toArray(testInstance.prop1); // $ExpectType string[]\nnameof.toArray(testInstance.prop1, testInstance.prop2); // $ExpectType string[]\nnameof.toArray<TestClass>(t => [t.prop1]); // $ExpectType string[]\n\n// nameof.split tests\nnameof.split(testInstance.prop1); // $ExpectType string[]\nnameof.split(testInstance.prop1, 1); // $ExpectType string[]\nnameof.split<TestClass>(obj => obj.prop1); // $ExpectType string[]\nnameof.split<TestClass>(obj => obj.prop1, 1); // $ExpectType string[]\n\n// nameof.interpolate tests\nnameof.interpolate(\"\"); // $ExpectType \"\"\n\n// reference type test\nconst myObj = { test: \"\" };\nnameof(myObj); // $ExpectType string\nnameof.full(myObj); // $ExpectType string\nnameof.toArray(myObj); // $ExpectType string[]\n\n// primitive type test\nconst myStr = \"\";\nnameof(myStr); // $ExpectType string\nnameof.full(myStr); // $ExpectType string\nnameof.toArray(myStr); // $ExpectType string[]\n\n// null test\nconst nullTypedVar = null;\nnameof(nullTypedVar); // $ExpectType string\nnameof.full(nullTypedVar); // $ExpectType string\nnameof.toArray(nullTypedVar); // $ExpectType string[]\n\n// undefined test\nconst undefinedTypedVar = undefined;\nnameof(undefinedTypedVar); // $ExpectType string\nnameof.full(undefinedTypedVar); // $ExpectType string\nnameof.toArray(undefinedTypedVar); // $ExpectType string[]\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ts-nameof-workspace\",\n  \"private\": true,\n  \"workspaces\": [\n    \"packages/common\",\n    \"packages/scripts-common\",\n    \"packages/tests-common\",\n    \"packages/transforms-common\",\n    \"packages/transforms-babel\",\n    \"packages/transforms-ts\",\n    \"packages/ts-nameof\",\n    \"packages/ts-nameof.macro\",\n    \"packages/babel-plugin-ts-nameof\"\n  ],\n  \"scripts\": {\n    \"clean\": \"yarn workspaces run clean\",\n    \"build\": \"yarn workspaces run build\",\n    \"test\": \"yarn workspaces run test\",\n    \"verify\": \"yarn test && yarn verify-declaration-file\",\n    \"create-declaration-file\": \"yarn workspace ts-nameof build:declarations && yarn workspace ts-nameof.macro build:declarations\",\n    \"verify-declaration-file\": \"yarn workspace ts-nameof verify-declaration-file\"\n  }\n}\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/.npmignore",
    "content": "/node_modules\n/.vscode\n/.vs\n/.git\n/obj\n/temp\n/bin\n/src\n/dist/tests\n/setup\n/scripts\n/lib\n*.js.map\n*.v12.suo\n*.csproj\n*.csproj.user\n*.sln\n*.log\n.travis.yml\n.gitignore\nCHANGELOG.md\n.mocharc.yml\ntsconfig.json\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 David Sherret\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/README.md",
    "content": "﻿# babel-plugin-ts-nameof\n\n[![npm version](https://badge.fury.io/js/babel-plugin-ts-nameof.svg)](https://badge.fury.io/js/babel-plugin-ts-nameof)\n[![Build Status](https://travis-ci.org/dsherret/ts-nameof.svg)](https://travis-ci.org/dsherret/ts-nameof)\n[![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges)\n\n[`nameof`](https://msdn.microsoft.com/en-us/library/dn986596.aspx) in TypeScript.\n\n## Setup\n\n1. Run:\n\n```\nnpm install babel-plugin-ts-nameof @types/ts-nameof --save-dev\n```\n\n2. Add an entry to `.babelrc` for `babel-plugin-ts-nameof`:\n\n```\n{\n  \"plugins\": [\"babel-plugin-ts-nameof\"]\n}\n```\n\n## Transforms\n\n[Read here](https://github.com/dsherret/ts-nameof/blob/master/README.md)\n\n## Other\n\n- [Contributing](https://github.com/dsherret/ts-nameof/blob/master/CONTRIBUTING.md)\n- [Development](https://github.com/dsherret/ts-nameof/blob/master/DEVELOPMENT.md)\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/package.json",
    "content": "{\n  \"name\": \"babel-plugin-ts-nameof\",\n  \"version\": \"4.2.1\",\n  \"description\": \"nameof in TypeScript for babel.\",\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"clean\": \"rimraf dist &&  tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"echo 'ignore'\",\n    \"dopublish\": \"npm run install && npm run build && echo \\\"Run: npm publish --otp\\\"\"\n  },\n  \"keywords\": [\n    \"nameof\",\n    \"typescript\",\n    \"transforms\",\n    \"babel\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/dsherret/ts-nameof.git\",\n    \"directory\": \"packages/babel-plugin-ts-nameof\"\n  },\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@ts-nameof/transforms-babel\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.16.5\",\n    \"@babel/preset-typescript\": \"^7.16.5\",\n    \"@ts-nameof/tests-common\": \"^4.2.0\",\n    \"@types/babel__core\": \"^7.1.17\",\n    \"@types/babel__generator\": \"^7.6.3\",\n    \"@types/babel__template\": \"^7.4.1\",\n    \"@types/babel__traverse\": \"^7.14.2\",\n    \"@types/node\": \"^17.0.0\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/src/index.ts",
    "content": "export { plugin as default } from \"@ts-nameof/transforms-babel\";\n"
  },
  {
    "path": "packages/babel-plugin-ts-nameof/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src\"],\n  \"references\": [\n    { \"path\": \"../transforms-babel\" },\n    { \"path\": \"../tests-common\" }\n  ]\n}\n"
  },
  {
    "path": "packages/common/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\n*.log\r\n*.js.map\r\nsrc\r\n"
  },
  {
    "path": "packages/common/README.md",
    "content": "# ts-nameof - Common\n\nContains common utilities functions."
  },
  {
    "path": "packages/common/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/common\",\n  \"version\": \"4.2.1\",\n  \"description\": \"ts-nameof - Common code across packages.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"echo 'ignore'\"\n  },\n  \"dependencies\": {\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^4.5.4\",\n    \"rimraf\": \"^3.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/common/src/errors.ts",
    "content": "export function throwError(message: string): never {\n    throw new Error(`[ts-nameof]: ${sanitizeMessage(message)}`);\n}\n\nexport function throwErrorForSourceFile(message: string, sourceFilePath: string): never {\n    throw new Error(`[ts-nameof:${sourceFilePath}]: ${sanitizeMessage(message)}`);\n}\n\nexport function assertNever(value: never, message: string): never {\n    return throwError(message);\n}\n\nfunction sanitizeMessage(message: string) {\n    return message.replace(/^\\[ts\\-nameof[^\\]]*\\]: /, \"\");\n}\n"
  },
  {
    "path": "packages/common/src/index.ts",
    "content": "export * from \"./errors\";\n"
  },
  {
    "path": "packages/common/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src/**/*.ts\"]\n}\n"
  },
  {
    "path": "packages/scripts-common/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\nsrc\r\n*.log\r\n*.js.map"
  },
  {
    "path": "packages/scripts-common/README.md",
    "content": "# ts-nameof - Scripts Common\n\nContains scripts for use across packages.\n"
  },
  {
    "path": "packages/scripts-common/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/scripts-common\",\n  \"version\": \"4.0.2\",\n  \"description\": \"ts-nameof - Common scripts for ts-nameof packages.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"echo 'ignore'\"\n  },\n  \"devDependencies\": {\n    \"@types/mocha\": \"^9.0.0\",\n    \"@types/node\": \"^17.0.0\",\n    \"rimraf\": \"^3.0.2\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/scripts-common/src/ArgsChecker.ts",
    "content": "export class ArgsChecker {\n  private readonly originalArgs: ReadonlyArray<string>;\n  private readonly args: string[];\n\n  constructor(args?: string[]) {\n    this.args = args || process.argv.slice(2);\n    this.originalArgs = [...this.args];\n  }\n\n  checkHasArg(argName: string) {\n    if (this.originalArgs.length === 0) {\n      return true; // run all\n    }\n\n    return this.checkHasExplicitArg(argName);\n  }\n\n  checkHasExplicitArg(argName: string) {\n    const index = this.args.indexOf(argName);\n    if (index === -1) {\n      return false;\n    }\n\n    this.args.splice(index, 1);\n    return true;\n  }\n\n  verifyArgsUsed() {\n    if (this.args.length > 0) {\n      console.error(`Unknown args: ${this.args.join(\", \")}`);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/scripts-common/src/index.ts",
    "content": "export * from \"./ArgsChecker\";\n"
  },
  {
    "path": "packages/scripts-common/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src/**/*.ts\"]\n}\n"
  },
  {
    "path": "packages/tests-common/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\nsrc\r\n*.log\r\n*.js.map\r\n"
  },
  {
    "path": "packages/tests-common/README.md",
    "content": "# ts-nameof - Tests Common\n\nContains tests that should work across any implementation of ts-nameof (whether babel or the typescript compiler).\n"
  },
  {
    "path": "packages/tests-common/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/tests-common\",\n  \"version\": \"4.2.0\",\n  \"description\": \"Common tests for ts-nameof packages.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"echo 'ignore'\"\n  },\n  \"devDependencies\": {\n    \"@dprint/formatter\": \"^0.1.5\",\n    \"@dprint/typescript\": \"^0.60.0\",\n    \"@types/mocha\": \"^9.0.0\",\n    \"@types/node\": \"^17.0.0\",\n    \"rimraf\": \"^3.0.2\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/tests-common/src/index.ts",
    "content": "export * from \"./runCommonTests\";\n"
  },
  {
    "path": "packages/tests-common/src/runCommonTests.ts",
    "content": "import { createFromBuffer } from \"@dprint/formatter\";\n// @ts-ignore\nimport { getBuffer } from \"@dprint/typescript\";\nimport * as assert from \"assert\";\nimport * as path from \"path\";\n\nconst formatter = createFromBuffer(getBuffer());\nformatter.setConfig({ indentWidth: 2 }, {});\n/**\n * Runs tests across different compilers.\n * @param getTransformedText Function to get the transformed text.\n * @param options Options for running the tests.\n */\nexport function runCommonTests(getTransformedText: (text: string) => string, options: { commonPrefix?: string } = {}) {\n  describe(\"nameof\", () => {\n    describe(\"bad call expressions\", () => {\n      it(\"should throw if someone does not provide arguments or type arguments\", () => {\n        runThrowTest(\"nameof();\", \"Call expression must have one argument or type argument: nameof()\");\n      });\n    });\n\n    describe(\"argument\", () => {\n      it(\"should get the result of an identifier\", () => {\n        runTest(`nameof(myObj);`, `\"myObj\";`);\n      });\n\n      it(\"should get the result of the this keyword\", () => {\n        runTest(`nameof(this);`, `\"this\";`);\n      });\n\n      it(\"should get the result of a property access expression\", () => {\n        runTest(`nameof(myObj.prop);`, `\"prop\";`);\n      });\n\n      it(\"should get the result of an expression with a parenthesized expression\", () => {\n        runTest(`nameof((myObj).prop);`, `\"prop\";`);\n      });\n\n      it(\"should get the result of an expression with a type assertion\", () => {\n        runTest(`nameof((myObj as any).prop);`, `\"prop\";`);\n      });\n\n      it(\"should get the result of a property access expression with null assertion operators\", () => {\n        runTest(`nameof(myObj!.prop!);`, `\"prop\";`);\n      });\n\n      it(\"should get the result of an identifier with a dollar sign\", () => {\n        runTest(`nameof(myObj.$prop);`, `\"$prop\";`);\n      });\n\n      it(\"should resolve to string when nesting nameofs\", () => {\n        runTest(`nameof(nameof(testing));`, `\"testing\";`);\n      });\n    });\n\n    describe(\"type parameter\", () => {\n      it(\"should get the result of an identifier\", () => {\n        runTest(`nameof<Test>();`, `\"Test\";`);\n      });\n\n      it(\"should get the result of a fully qualified name\", () => {\n        runTest(`nameof<This.Is.A.Test>();`, `\"Test\";`);\n      });\n\n      it(\"should get an identifier with a dollar sign\", () => {\n        runTest(`nameof<Test$>();`, `\"Test$\";`);\n      });\n\n      it(\"should handle when someone uses an import type as not the last node\", () => {\n        runTest(`nameof<import('test').prop>();`, `\"prop\";`);\n      });\n\n      it(\"should throw when someone only uses an import type\", () => {\n        runThrowTest(`nameof<import('test')>();`, getNotSupportedErrorText(\"import(\\\"test\\\")\"));\n      });\n\n      it(\"should throw when someone only uses an import type with typeof\", () => {\n        runThrowTest(`nameof<typeof import('test')>();`, getNotSupportedErrorText(\"typeof import(\\\"test\\\")\"));\n      });\n    });\n\n    describe(\"computed properties\", () => {\n      it(\"should not allow a computed property to be at the end with a number\", () => {\n        runThrowTest(`nameof(anyProp[0]);`, getFirstAccessedPropertyMustNotBeComputedErrorText(`anyProp[0]`));\n      });\n\n      it(\"should get after the period\", () => {\n        runTest(`nameof(anyProp[0].prop);`, `\"prop\";`);\n      });\n\n      it(\"should get the string inside the computed property\", () => {\n        runTest(`nameof(obj[\"prop\"]);`, `\"prop\";`);\n      });\n\n      it(\"should get the string inside the computed property for a function\", () => {\n        runTest(`nameof<MyInterface>(i => i[\"prop\"]);`, `\"prop\";`);\n      });\n\n      it(\"should not allow a computed property to be at the end with a number when using a function\", () => {\n        runThrowTest(`nameof<MyInterface>(i => i.prop[0]);`, getFirstAccessedPropertyMustNotBeComputedErrorText(\"(i) => i.prop[0]\"));\n      });\n\n      it(\"should not allow an identifier nested in a computed property\", () => {\n        runThrowTest(`nameof<MyInterface>(i => i.prop[prop[0]]);`, getFirstAccessedPropertyMustNotBeComputedErrorText(\"(i) => i.prop[prop[0]]\"));\n      });\n    });\n\n    describe(\"array\", () => {\n      it(\"should not allow only an array\", () => {\n        runThrowTest(`nameof([0]);`, getNotSupportedErrorText(\"[0]\"));\n      });\n\n      it(\"should allow getting an array's property\", () => {\n        runTest(`nameof([].length);`, `\"length\";`);\n      });\n    });\n\n    describe(\"with function\", () => {\n      it(\"should get the last string\", () => {\n        runTest(`nameof<MyInterface>(i => i.prop1.prop2);`, `\"prop2\";`);\n      });\n\n      it(\"should get from the return statement\", () => {\n        // no reason for people to do this, but don't bother complaining\n        runTest(`nameof<MyInterface>(i => { console.log('test'); return i.prop1.prop2; });`, `\"prop2\";`);\n      });\n\n      it(\"should handle when someone uses an import type\", () => {\n        runTest(`nameof<import('test')>(x => x.Foo);`, `\"Foo\";`);\n      });\n\n      it(\"should get when using an element access expression directly on the object\", () => {\n        runTest(`nameof<MyInterface>(i => i[\"prop1\"]);`, `\"prop1\";`);\n      });\n\n      it(\"should throw when using an element access expression directly on the object and it is not a string\", () => {\n        runThrowTest(`nameof<MyInterface>(i => i[0]);`, getFirstAccessedPropertyMustNotBeComputedErrorText(`(i) => i[0]`));\n      });\n\n      it(\"should throw when the function doesn't have a period\", () => {\n        runThrowTest(`nameof<MyInterface>(i => i);`, \"A property must be accessed on the object: (i) => i\");\n      });\n\n      it(\"should throw when the function doesn't have a return statement\", () => {\n        const errorPrefix = \"Cound not find return statement with an expression in function expression: \";\n        const possibleMessages = [\n          errorPrefix + \"{ i; }\", // babel\n          errorPrefix + \"{\\n    i;\\n}\", // typescript\n        ];\n        runThrowTest(`nameof<MyInterface>(i => { i; });`, possibleMessages);\n      });\n    });\n\n    describe(\"literals\", () => {\n      it(\"should leave the string literal as-is\", () => {\n        // this allows for nested nameofs\n        runTest(`nameof(\"test\");`, `\"test\";`);\n      });\n\n      it(\"should transform a numeric literal as a string\", () => {\n        runTest(`nameof(5);`, `\"5\";`);\n      });\n    });\n\n    describe(\"interpolate\", () => {\n      it(\"should throw when providing nameof.interpolate to nameof\", () => {\n        runThrowTest(`nameof(nameof.interpolate(5));`, [\n          getNotSupportedErrorText(\"nameof.interpolate(5)\"),\n          // it will be this for babel because it checks the parent nodes\n          getUnusedNameofInterpolateErrorText(\"5\"),\n        ]);\n      });\n    });\n\n    describe(\"template expression\", () => {\n      it(\"should return a no substitution template literal\", () => {\n        runTest(\"nameof(`testing`);\", \"`testing`;\");\n      });\n\n      it(\"should return the template expression when it has only a template tail\", () => {\n        runTest(\"nameof(`testing${test}final`);\", \"`testing${test}final`;\");\n      });\n\n      it(\"should return the template expression when it has a template middle\", () => {\n        runTest(\"nameof(`testing${other}asdf${test}${asdf}final`);\", \"`testing${other}asdf${test}${asdf}final`;\");\n      });\n\n      it(\"should return the template expression when it starts and ends with one\", () => {\n        runTest(\"nameof(`${other}`);\", \"`${other}`;\");\n      });\n\n      it(\"should return the template expression when it starts and ends with multiple\", () => {\n        runTest(\"nameof(`${other}${asdf}${test}`);\", \"`${other}${asdf}${test}`;\");\n      });\n\n      it(\"should throw when a nameof.interpolate is not used\", () => {\n        runThrowTest(\"nameof(`${nameof.interpolate(other)}`);\", getUnusedNameofInterpolateErrorText(\"other\"));\n      });\n    });\n\n    describe(\"other\", () => {\n      it(\"should ignore spread syntax\", () => {\n        runTest(`nameof(...test);`, `\"test\";`);\n      });\n    });\n  });\n\n  describe(\"nameof.full\", () => {\n    describe(\"bad call expressions\", () => {\n      it(\"should throw if someone does not provide arguments or type arguments\", () => {\n        runThrowTest(\"nameof.full();\", \"Unsupported use of nameof.full: nameof.full()\");\n      });\n    });\n\n    describe(\"argument\", () => {\n      it(\"should include everything when no count arg is provided\", () => {\n        runTest(`nameof.full(obj.prop.other);`, `\"obj.prop.other\";`);\n      });\n\n      it(\"should not include null assertion operators\", () => {\n        runTest(`nameof.full(obj!.prop!.other!);`, `\"obj.prop.other\";`);\n      });\n\n      it(\"should not include null assertion operators when also using element access expressions\", () => {\n        runTest(`nameof.full(obj!.prop![0].other!);`, `\"obj.prop[0].other\";`);\n      });\n\n      it(\"should escape string literals in element access expressions\", () => {\n        runTest(`nameof.full(obj.prop[\"other\"]);`, `\"obj.prop[\\\\\"other\\\\\"]\";`);\n      });\n\n      it(\"should allow using a period index\", () => {\n        runTest(\"nameof.full(MyTest.Test.This, 1);\", `\"Test.This\";`);\n      });\n\n      it(\"should allow using a period index of 0\", () => {\n        runTest(\"nameof.full(MyTest.Test.This, 0);\", `\"MyTest.Test.This\";`);\n      });\n\n      it(\"should allow using a period index up to its max value\", () => {\n        runTest(\"nameof.full(MyTest.Test.This, 2);\", `\"This\";`);\n      });\n\n      it(\"should allow using a negative period index\", () => {\n        runTest(\"nameof.full(MyTest.Test.This, -1);\", `\"This\";`);\n      });\n\n      it(\"should allow using a negative period index to its max value\", () => {\n        runTest(\"nameof.full(MyTest.Test.This, -3);\", `\"MyTest.Test.This\";`);\n      });\n\n      it(\"should throw when the periodIndex is not a number literal\", () => {\n        runThrowTest(\"nameof.full(MyTest.Test, 'test')\", `Expected count to be a number, but was: \"test\"`);\n      });\n\n      it(\"should throw when the periodIndex is greater than the number of periods\", () => {\n        runThrowTest(\"nameof.full(MyTest.Test, 2)\", \"Count of 2 was larger than max count of 1: nameof.full(MyTest.Test, 2)\");\n      });\n\n      it(\"should throw when the absolute value of the negative periodIndex is greater than the number of periods + 1\", () => {\n        runThrowTest(\"nameof.full(MyTest.Test, -3)\", \"Count of -3 was larger than max count of -2: nameof.full(MyTest.Test, -3)\");\n      });\n\n      it(\"should resolve to string when nesting nameofs\", () => {\n        runTest(`nameof.full(nameof(testing));`, `\"testing\";`);\n      });\n\n      it(\"should get the result of the super keyword\", () => {\n        runTest(\n          `class Test {\\n  constructor() {\\n    nameof.full(super.test);\\n  }\\n}`,\n          `class Test {\\n  constructor() {\\n    \"super.test\";\\n  }\\n}`,\n        );\n      });\n    });\n\n    describe(\"type parameter\", () => {\n      it(\"should include everything when no count arg is provided\", () => {\n        runTest(`nameof.full<Some.Test.Name>();`, `\"Some.Test.Name\";`);\n      });\n\n      it(\"should allow using a period index\", () => {\n        runTest(\"nameof.full<MyTest.Test.This>(1);\", `\"Test.This\";`);\n      });\n\n      it(\"should allow using a period index of 0\", () => {\n        runTest(\"nameof.full<MyTest.Test.This>(0);\", `\"MyTest.Test.This\";`);\n      });\n\n      it(\"should allow using a period index up to its max value\", () => {\n        runTest(\"nameof.full<MyTest.Test.This>(2);\", `\"This\";`);\n      });\n\n      it(\"should allow using a negative period index\", () => {\n        runTest(\"nameof.full<MyTest.Test.This>(-1);\", `\"This\";`);\n      });\n\n      it(\"should allow using a negative period index to its max value\", () => {\n        runTest(\"nameof.full<MyTest.Test.This>(-3);\", `\"MyTest.Test.This\";`);\n      });\n\n      it(\"should throw when the periodIndex is not a number literal\", () => {\n        runThrowTest(\"nameof.full<MyTest.Test>('test')\", `Expected count to be a number, but was: \"test\"`);\n      });\n\n      it(\"should throw when the periodIndex is greater than the number of periods\", () => {\n        runThrowTest(\"nameof.full<MyTest.Test>(2)\", \"Count of 2 was larger than max count of 1: nameof.full<MyTest.Test>(2)\");\n      });\n\n      it(\"should throw when the absolute value of the negative periodIndex is greater than the number of periods + 1\", () => {\n        runThrowTest(\"nameof.full<MyTest.Test>(-3)\", \"Count of -3 was larger than max count of -2: nameof.full<MyTest.Test>(-3)\");\n      });\n\n      it(\"should throw when someone uses an import type\", () => {\n        runThrowTest(`nameof.full<import('test').other.test>();`, getNotSupportedErrorText(\"import(\\\"test\\\").other.test\"));\n      });\n    });\n\n    describe(\"arrays\", () => {\n      it(\"should include the brackets\", () => {\n        runTest(`nameof.full(anyProp[0].myProp);`, `\"anyProp[0].myProp\";`);\n      });\n    });\n\n    describe(\"with function\", () => {\n      it(\"should get the text\", () => {\n        runTest(`nameof.full<MyInterface>(i => i.prop1.prop2);`, `\"prop1.prop2\";`);\n      });\n\n      it(\"should get the text without the null assertion operator\", () => {\n        runTest(`nameof.full<MyInterface>(i => i.prop1!.prop2!);`, `\"prop1.prop2\";`);\n      });\n\n      it(\"should get the text when there's a trailing comma with whitespace\", () => {\n        runTest(\"nameof.full<IState>(state => state.field.dates, );\", `\"field.dates\";`);\n      });\n\n      it(\"should get the text when using a function\", () => {\n        runTest(`nameof.full<MyInterface>(function(i) { return i.prop1.prop2; });`, `\"prop1.prop2\";`);\n      });\n\n      it(\"should get the text when providing a period\", () => {\n        runTest(`nameof.full<MyInterface>(i => i.prop1.prop2, 0);`, `\"prop1.prop2\";`);\n        runTest(`nameof.full<MyInterface>(i => i.prop1.prop2, 1);`, `\"prop2\";`);\n        runTest(`nameof.full<MyInterface>(i => i.prop1.prop2.prop3, -1);`, `\"prop3\";`);\n      });\n\n      it(\"should throw when the function doesn't have a period\", () => {\n        runThrowTest(`nameof.full<MyInterface>(i => i);`, \"A property must be accessed on the object: (i) => i\");\n      });\n\n      it(\"should throw when someone nests a function within a function\", () => {\n        runThrowTest(`nameof.full<MyInterface>(i => () => 5);`, \"A property must be accessed on the object: (i) => () => 5\");\n      });\n    });\n\n    describe(\"interpolate\", () => {\n      const singleArgumentErrorMessage = \"Unexpected scenario where a nameof.interpolate function did not have a single argument.\";\n\n      it(\"should interpolate the provided expression\", () => {\n        runTest(`nameof.full(Test.Other[nameof.interpolate(other)]);`, \"`Test.Other[${other}]`;\");\n      });\n\n      it(\"should interpolate when using a function\", () => {\n        runTest(`nameof.full<a>(a => a.b.c[nameof.interpolate(index)].d);`, \"`b.c[${index}].d`;\");\n      });\n\n      it(\"should throw when the interpolate function has zero arguments\", () => {\n        runThrowTest(`nameof.full(Test.Other[nameof.interpolate()]);`, singleArgumentErrorMessage);\n      });\n\n      it(\"should throw when the interpolate function has multiple arguments\", () => {\n        runThrowTest(`nameof.full(Test.Other[nameof.interpolate(test, test)]);`, singleArgumentErrorMessage);\n      });\n\n      it(\"should throw when a nameof.interpolate is not used inside a nameof.full\", () => {\n        runThrowTest(\"nameof.interpolate(some.expression);\", getUnusedNameofInterpolateErrorText(\"some.expression\"));\n      });\n\n      it(\"should handle the scenarios in issue #104\", () => {\n        runTest(\"nameof.full(m.Data[nameof.interpolate(i)].Title);\", \"`m.Data[${i}].Title`;\");\n        runTest(\"nameof.full(m.Data[i].Title);\", `\"m.Data[i].Title\";`);\n      });\n    });\n  });\n\n  describe(\"toArray\", () => {\n    it(\"should return an array of values when given a function that returns an array as input\", () => {\n      runTest(`nameof.toArray<MyInterface>(o => [o.Prop1, o.Prop2, o.Prop3]);`, `[\"Prop1\", \"Prop2\", \"Prop3\"];`);\n    });\n\n    it(\"should return an array of values when given multiple arguments\", () => {\n      runTest(`nameof.toArray(myObject.Prop1, otherObject.Prop2);`, `[\"Prop1\", \"Prop2\"];`);\n    });\n\n    it(\"should return an array with a single element if a non-function argument is passed\", () => {\n      runTest(`nameof.toArray(myObject.Prop1);`, `[\"Prop1\"];`);\n    });\n\n    it(\"should support nested nameof calls\", () => {\n      runTest(`nameof.toArray(nameof.full(Some.Qualified.Name), Some.Qualified.Name);`, `[\"Some.Qualified.Name\", \"Name\"];`);\n    });\n\n    it(\"should support a non-arrow function expression\", () => {\n      runTest(`nameof.toArray<MyInterface>(function(o) { return [o.Prop1, o.Prop2]; });`, `[\"Prop1\", \"Prop2\"];`);\n    });\n\n    it(\"should throw when the function argument does not return an array\", () => {\n      runThrowTest(\n        `nameof.toArray<MyInterface>(o => o.Prop1);`,\n        \"Unsupported toArray call expression. An array must be returned by the provided function: nameof.toArray<MyInterface>((o) => o.Prop1)\",\n      );\n    });\n\n    it(\"should throw when no arguments are provided\", () => {\n      runThrowTest(`nameof.toArray<MyInterface>();`, \"Unable to parse call expression. No arguments provided: nameof.toArray<MyInterface>()\");\n    });\n  });\n\n  describe(\"split\", () => {\n    it(\"should return an array of values where each element is a subsequent part of the path provided\", () => {\n      runTest(`nameof.split<MyInterface>(o => o.Prop1.Prop2.Prop3);`, `[\"Prop1\", \"Prop2\", \"Prop3\"];`);\n    });\n\n    it(\"should return an array of values where each element is a subsequent part of the path provided\", () => {\n      runTest(`nameof.split(o.Prop1.Prop2.Prop3);`, `[\"o\", \"Prop1\", \"Prop2\", \"Prop3\"];`);\n    });\n\n    it(\"should allow using a period index\", () => {\n      runTest(`nameof.split(MyTest.Test.This, 1);`, `[\"Test\", \"This\"];`);\n    });\n\n    it(\"should allow using a period index of 0\", () => {\n      runTest(`nameof.split(MyTest.Test.This, 0);`, `[\"MyTest\", \"Test\", \"This\"];`);\n    });\n\n    it(\"should allow using a period index up to its max value\", () => {\n      runTest(`nameof.split(MyTest.Test.This, 2);`, `[\"This\"];`);\n    });\n\n    it(\"should allow using a negative period index\", () => {\n      runTest(`nameof.split(MyTest.Test.This, -1);`, `[\"This\"];`);\n    });\n\n    it(\"should allow using a negative period index to its max value\", () => {\n      runTest(`nameof.split(MyTest.Test.This, -3);`, `[\"MyTest\", \"Test\", \"This\"];`);\n    });\n\n    it(\"should throw when the periodIndex is not a number literal\", () => {\n      runThrowTest(`nameof.split(MyTest.Test, 'test')`, `Expected count to be a number, but was: \"test\"`);\n    });\n\n    it(\"should throw when the periodIndex is greater than the number of periods\", () => {\n      runThrowTest(`nameof.split(MyTest.Test, 2)`, \"Count of 2 was larger than max count of 1: nameof.split(MyTest.Test, 2)\");\n    });\n\n    it(\"should throw when the absolute value of the negative periodIndex is greater than the number of periods + 1\", () => {\n      runThrowTest(`nameof.split(MyTest.Test, -3)`, \"Count of -3 was larger than max count of -2: nameof.split(MyTest.Test, -3)\");\n    });\n  });\n\n  describe(\"general\", () => {\n    it(\"should error when specifying a different nameof property\", () => {\n      runThrowTest(`nameof.nonExistent()`, \"Unsupported nameof call expression with property 'nonExistent': nameof.nonExistent()\");\n    });\n\n    it(\"should replace handling comments\", () => {\n      const input = `nameof(window);\n// nameof(window);\nnameof(window);\n/* nameof(window); nameof(window); */\nnameof(window);\n`;\n      const expected = `\"window\";\n// nameof(window);\n\"window\";\n/* nameof(window); nameof(window); */\n\"window\";\n`;\n      runTest(input, expected);\n    });\n\n    it(\"should replace handling strings\", () => {\n      const input = `nameof(window);\nconst t = /\\`/g;\n\\`nameof(window); /\n\\${nameof(window)}\n\\${nameof(alert)}\nnameof(window);\n\\`; // test\n\"nameof(window);\";\n\"\\\\\"nameof(window);\";\n'nameof(window);';\n'\\\\'\\\\\"nameof(window);';\n\"C:\\\\\\\\\";\nnameof(window);\n\\`\\${() => {\n  nameof(console);\n}}\\`;\n`;\n      const expected = `\"window\";\nconst t = /\\`/g;\n\\`nameof(window); /\n$\\{\"window\"\\}\n$\\{\"alert\"\\}\nnameof(window);\n\\`; // test\n\"nameof(window);\";\n\"\\\\\"nameof(window);\";\n\"nameof(window);\";\n\"'\\\\\"nameof(window);\";\n\"C:\\\\\\\\\";\n\"window\";\n\\`\\${() => {\n  \"console\";\n}}\\`;\n`;\n      runTest(input, expected);\n    });\n\n    it(\"should handle division operators\", () => {\n      const input = `const t = 2 / 1;\\nnameof(testing);`;\n      const expected = `const t = 2 / 1;\\n\"testing\";`;\n      runTest(input, expected);\n    });\n  });\n\n  function runTest(text: string, expected: string) {\n    if (options.commonPrefix != null) {\n      text = options.commonPrefix + text;\n    }\n\n    const result = getTransformedText(text);\n    if (!expected.endsWith(\"\\n\")) {\n      expected += \"\\n\";\n    }\n    assert.strictEqual(formatter.formatText(\"file.ts\", result), expected);\n  }\n\n  function runThrowTest(text: string, possibleExpectedMessages: string | string[]) {\n    if (options.commonPrefix != null) {\n      text = options.commonPrefix + text;\n    }\n    let transformedText: string | undefined;\n\n    // for some reason, assert.throws was not working\n    try {\n      transformedText = getTransformedText(text);\n    } catch (ex: any) {\n      possibleExpectedMessages = getPossibleExpectedMessages();\n\n      const actualMessage = (ex as any).message;\n      for (const message of possibleExpectedMessages) {\n        if (message === actualMessage) {\n          return;\n        }\n      }\n\n      throw new Error(\n        `Expected the error message of ${JSON.stringify(actualMessage)} to equal `\n          + `one of the following messages: ${JSON.stringify(possibleExpectedMessages)}`,\n      );\n    }\n\n    throw new Error(`Expected to throw, but returned: ${transformedText}`);\n\n    function getPossibleExpectedMessages() {\n      const result = getAsArray();\n\n      for (let i = result.length - 1; i >= 0; i--) {\n        const originalText = result[i];\n        result[i] = \"[ts-nameof]: \" + originalText;\n        // ts\n        result.push(\"[ts-nameof:/file.ts]: \" + originalText);\n        // babel\n        const babelPath = path.resolve(__dirname, \"../../transforms-babel/src/tests/test.ts\");\n        // todo: temporary... switch to one path in the year 2021 (old versions of babel won't have the prefixed path)\n        result.push(`${babelPath}: [ts-nameof:${babelPath}]: ${originalText}`);\n        // babel macro (not ideal, but whatever)\n        result.push(`${path.resolve(__dirname, \"../../ts-nameof.macro/src/tests/test.ts\")}: ./ts-nameof.macro: [ts-nameof]: ${originalText}`);\n      }\n\n      return result;\n\n      function getAsArray() {\n        if (typeof possibleExpectedMessages === \"string\") {\n          return [possibleExpectedMessages];\n        }\n        return possibleExpectedMessages;\n      }\n    }\n  }\n}\n\nfunction getFirstAccessedPropertyMustNotBeComputedErrorText(nodeText: string) {\n  return `First accessed property must not be computed except if providing a string: ${nodeText}`;\n}\n\nfunction getNotSupportedErrorText(nodeText: string) {\n  return `The node \\`${nodeText}\\` is not supported in this scenario.`;\n}\n\nfunction getUnusedNameofInterpolateErrorText(nodeText: string) {\n  return `Found a nameof.interpolate that did not exist within a nameof.full call expression: nameof.interpolate(${nodeText})`;\n}\n"
  },
  {
    "path": "packages/tests-common/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src/**/*.ts\"]\n}\n"
  },
  {
    "path": "packages/transforms-babel/.mocharc.yml",
    "content": "require: ts-node/register\nrecursive: true\nreporter: progress\nwatch-extensions: ts\ntimeout: 10000\nspec: src/tests/**/*.ts\n"
  },
  {
    "path": "packages/transforms-babel/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\nsrc\r\n*.log\r\n*.js.map\r\n.mocharc.yml\r\n"
  },
  {
    "path": "packages/transforms-babel/README.md",
    "content": "# ts-nameof - Babel transforms\n\nContains the babel transforms used in ts-nameof.\n\n## Development Commands\n\n```\nnpm run test\n```\n"
  },
  {
    "path": "packages/transforms-babel/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/transforms-babel\",\n  \"version\": \"4.2.1\",\n  \"description\": \"ts-nameof - Babel transforms for ts-nameof packages.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"npm run build && mocha\",\n    \"test:debug\": \"npm run build && mocha --inspect-brk\"\n  },\n  \"dependencies\": {\n    \"@ts-nameof/common\": \"^4.2.1\",\n    \"@ts-nameof/transforms-common\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.16.5\",\n    \"@babel/preset-typescript\": \"^7.16.5\",\n    \"@babel/types\": \"^7.16.0\",\n    \"@ts-nameof/tests-common\": \"^4.2.0\",\n    \"@types/babel__core\": \"^7.1.17\",\n    \"@types/babel__generator\": \"^7.6.3\",\n    \"@types/babel__template\": \"^7.4.1\",\n    \"@types/babel__traverse\": \"^7.14.2\",\n    \"@types/node\": \"^17.0.0\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/VisitSourceFileContext.ts",
    "content": "import { Node } from \"@babel/types\";\n\nexport interface VisitSourceFileContext {\n  interpolateExpressions: Set<Node>;\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/helpers.ts",
    "content": "import * as babelTypes from \"@babel/types\";\nimport { BlockStatement, Node, UnaryExpression } from \"@babel/types\";\nimport { throwError } from \"@ts-nameof/common\";\n\nexport function isNegativeNumericLiteral(t: typeof babelTypes, node: Node): node is UnaryExpression {\n  if (!t.isUnaryExpression(node)) {\n    return false;\n  }\n\n  return node.operator === \"-\" && t.isNumericLiteral(node.argument);\n}\n\nexport function getNegativeNumericLiteralValue(t: typeof babelTypes, node: UnaryExpression) {\n  if (node.operator !== \"-\" || !t.isNumericLiteral(node.argument)) {\n    return throwError(\"The passed in UnaryExpression must be for a negative numeric literal.\");\n  }\n\n  return node.argument.value * -1;\n}\n\nexport function getReturnStatementArgumentFromBlock(t: typeof babelTypes, block: BlockStatement) {\n  for (const statement of block.body) {\n    if (t.isReturnStatement(statement) && statement.argument != null) {\n      return statement.argument;\n    }\n  }\n\n  return undefined;\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/index.ts",
    "content": "import * as babel from \"@babel/core\";\nimport { Node, NodePath } from \"@babel/traverse\";\nimport * as babelTypes from \"@babel/types\";\nimport { throwErrorForSourceFile } from \"@ts-nameof/common\";\nimport { transformCallExpression } from \"@ts-nameof/transforms-common\";\nimport { parse, ParseOptions } from \"./parse\";\nimport { transform } from \"./transform\";\n\nexport interface TransformOptions extends ParseOptions {\n}\n\nexport function plugin({ types: t }: { types: typeof babelTypes }): babel.PluginItem {\n  const visitor = {\n    CallExpression(path: NodePath, state: unknown) {\n      const filePath = (state as any).file.opts.filename as string;\n      try {\n        transformNode(t, path, {\n          // temp assertion because I'm too lazy to investigate what's going on here\n          traverseChildren: () => path.traverse(visitor as any, state as any),\n        });\n      } catch (err: any) {\n        return throwErrorForSourceFile(err.message, filePath);\n      }\n    },\n  };\n  return { visitor };\n}\n\nexport function transformNode(t: typeof babelTypes, path: NodePath, options: TransformOptions = {}) {\n  const parseResult = parse(t, path, options);\n  if (parseResult == null) {\n    return;\n  }\n  const transformResult = transform(t, transformCallExpression(parseResult));\n  // temporary assertion due to conflicting type declaration versions\n  path.replaceWith(transformResult as Node);\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/parse.ts",
    "content": "import { NodePath } from \"@babel/traverse\";\nimport * as babelTypes from \"@babel/types\";\nimport {\n  ArrayExpression,\n  ArrowFunctionExpression,\n  BlockStatement,\n  CallExpression,\n  Expression,\n  FunctionExpression,\n  MemberExpression,\n  Node,\n  NumericLiteral,\n  StringLiteral,\n  TemplateLiteral,\n  TSImportType,\n  TSQualifiedName,\n  TSTypeParameterInstantiation,\n  UnaryExpression,\n  V8IntrinsicIdentifier,\n} from \"@babel/types\";\nimport { throwError } from \"@ts-nameof/common\";\nimport * as common from \"@ts-nameof/transforms-common\";\nimport { getNegativeNumericLiteralValue, getReturnStatementArgumentFromBlock, isNegativeNumericLiteral } from \"./helpers\";\n\nexport interface ParseOptions {\n  /**\n   * Action to prompt the children to be traversed. This is to allow traversing the nodes in post order.\n   */\n  traverseChildren?: () => void;\n  /**\n   * Expected identifier name at the start of the call expression. This could be different when using a macro.\n   * @default Defaults to \"nameof\".\n   */\n  nameofIdentifierName?: string;\n}\n\n/**\n * Parses a Babel AST node to a common NameofCallExpression or returns undefined if the current node\n * is not a nameof call expression.\n * @param t - Babel types namespace to use.\n * @param path - Path of the current Babel AST node.\n * @param options - Options for parsing.\n * @remarks Parsing to a common structure allows for the same code to be used to determine the final string.\n */\nexport function parse(t: typeof babelTypes, path: NodePath, options: ParseOptions = {}) {\n  if (!isNameof(path.node)) {\n    return undefined;\n  }\n\n  if (options.traverseChildren) {\n    options.traverseChildren(); // tell the caller to go over the nodes in post order\n  }\n\n  const propertyName = parsePropertyName(path.node);\n  // ignore nameof.interpolate function calls... they will be dealt with later\n  if (isInterpolatePropertyName(propertyName)) {\n    handleNameofInterpolate(path.node);\n    return undefined;\n  }\n\n  return parseNameof(path.node);\n\n  function parseNameof(callExpr: CallExpression): common.NameofCallExpression {\n    return {\n      property: propertyName,\n      typeArguments: parseTypeArguments(callExpr),\n      arguments: parseArguments(callExpr),\n    };\n  }\n\n  function parsePropertyName(callExpr: CallExpression) {\n    const { callee } = callExpr;\n    if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property)) {\n      return undefined;\n    }\n    return callee.property.name;\n  }\n\n  function parseTypeArguments(callExpr: CallExpression) {\n    // babel uses incorrect naming. these are type arguments\n    const typeArguments = (callExpr as any).typeParameters as TSTypeParameterInstantiation | undefined;\n    if (typeArguments == null) {\n      return [];\n    }\n    return typeArguments.params.map(arg => parseCommonNode(arg));\n  }\n\n  function parseArguments(callExpr: CallExpression) {\n    return callExpr.arguments.map(arg => parseCommonNode(arg));\n  }\n\n  function parseCommonNode(node: Node): common.Node {\n    if (t.isMemberExpression(node)) {\n      return parseMemberExpression(node);\n    }\n    if (t.isArrowFunctionExpression(node)) {\n      return parseFunctionReturnExpression(node, getArrowFunctionReturnExpression(node));\n    }\n    if (t.isFunctionExpression(node)) {\n      return parseFunctionReturnExpression(node, getReturnStatementArgumentFromBlockOrThrow(node.body));\n    }\n    if (t.isTSNonNullExpression(node) || t.isParenthesizedExpression(node) || t.isTSAsExpression(node)) {\n      return parseCommonNode(node.expression);\n    }\n    if (t.isTSQualifiedName(node)) {\n      return parseQualifiedName(node);\n    }\n    if (t.isTSTypeReference(node)) {\n      return parseCommonNode(node.typeName);\n    }\n    if (t.isSpreadElement(node)) {\n      return parseCommonNode(node.argument);\n    }\n    if (t.isNumericLiteral(node) || isNegativeNumericLiteral(t, node)) {\n      return parseNumeric(node);\n    }\n    if (t.isStringLiteral(node)) {\n      return parseStringLiteral(node);\n    }\n    if (t.isIdentifier(node)) {\n      return parseIdentifier(node);\n    }\n    if (t.isArrayExpression(node)) {\n      return parseArrayExpression(node);\n    }\n    if (t.isThisExpression(node)) {\n      return common.createIdentifierNode(\"this\");\n    }\n    if (t.isSuper(node)) {\n      return common.createIdentifierNode(\"super\");\n    }\n    if (t.isTSImportType(node)) {\n      return parseImportType(node, false);\n    }\n    if (t.isTSTypeQuery(node) && t.isTSImportType(node.exprName)) {\n      return parseImportType(node.exprName, true);\n    }\n    if (t.isTSLiteralType(node)) {\n      return parseCommonNode(node.literal); // skip over and go straight to the literal\n    }\n    if (t.isTemplateLiteral(node)) {\n      return parseTemplateExpression(node);\n    }\n    if (isNameof(node) && isInterpolatePropertyName(parsePropertyName(node))) {\n      return parseInterpolateNode(node);\n    }\n    return throwError(`Unhandled node type (${node.type}) in text: ${getNodeText(node)} (Please open an issue if you believe this should be supported.)`);\n  }\n\n  function parseArrayExpression(node: ArrayExpression) {\n    const result: common.Node[] = [];\n    node.elements.forEach(element => {\n      if (element == null) {\n        return throwError(`Unsupported scenario with empty element encountered in array: ${getNodeText(node)}`);\n      }\n      result.push(parseCommonNode(element));\n    });\n    return common.createArrayLiteralNode(result);\n  }\n\n  function parseMemberExpression(node: MemberExpression) {\n    const expressionCommonNode = parseCommonNode(node.object);\n    const nameCommonNode = parseCommonNode(node.property);\n    const computedCommonNode = node.computed ? common.createComputedNode(nameCommonNode) : undefined;\n    getEndCommonNode(expressionCommonNode).next = computedCommonNode || nameCommonNode;\n    return expressionCommonNode;\n  }\n\n  function parseQualifiedName(node: TSQualifiedName) {\n    const leftCommonNode = parseCommonNode(node.left);\n    const rightCommonNode = parseCommonNode(node.right);\n    getEndCommonNode(leftCommonNode).next = rightCommonNode;\n    return leftCommonNode;\n  }\n\n  function parseNumeric(node: NumericLiteral | UnaryExpression) {\n    return common.createNumericLiteralNode(getNodeValue());\n\n    function getNodeValue() {\n      if (t.isNumericLiteral(node)) {\n        return node.value;\n      }\n      return getNegativeNumericLiteralValue(t, node);\n    }\n  }\n\n  function parseStringLiteral(node: StringLiteral) {\n    return common.createStringLiteralNode(node.value);\n  }\n\n  function parseIdentifier(node: Node) {\n    const text = getIdentifierTextOrThrow(node);\n    return common.createIdentifierNode(text);\n  }\n\n  function parseFunctionReturnExpression(functionNode: FunctionExpression | ArrowFunctionExpression, node: Expression) {\n    const parameterNames = functionNode.params.map(p => {\n      if (t.isIdentifier(p)) {\n        return p.name;\n      }\n      return getNodeText(p);\n    });\n\n    return common.createFunctionNode(parseCommonNode(node), parameterNames);\n  }\n\n  function parseImportType(node: TSImportType, isTypeOf: boolean) {\n    const importTypeNode = common.createImportTypeNode(isTypeOf, parseCommonNode(node.argument));\n    const qualifier = node.qualifier == null ? undefined : parseCommonNode(node.qualifier);\n    getEndCommonNode(importTypeNode).next = qualifier;\n    return importTypeNode;\n  }\n\n  function parseTemplateExpression(node: TemplateLiteral) {\n    return common.createTemplateExpressionNode(getParts());\n\n    function getParts() {\n      const parts: (string | common.InterpolateNode)[] = [];\n\n      // the number of quasis will always be greater than the number of expressions\n      for (let i = 0; i < node.quasis.length; i++) {\n        parts.push(node.quasis[i].value.raw);\n        const expression = node.expressions[i];\n        if (expression != null) {\n          parts.push(common.createInterpolateNode(expression, getNodeText(expression)));\n        }\n      }\n\n      return parts;\n    }\n  }\n\n  function parseInterpolateNode(node: CallExpression) {\n    if (node.arguments.length !== 1) {\n      return throwError(`Expected a single argument for the nameof.interpolate function call ${getNodeText(node.arguments[0])}.`);\n    }\n    return common.createInterpolateNode(node.arguments[0], getNodeText(node.arguments[0]));\n  }\n\n  function getEndCommonNode(commonNode: common.Node) {\n    while (commonNode.next != null) {\n      commonNode = commonNode.next;\n    }\n    return commonNode;\n  }\n\n  function getArrowFunctionReturnExpression(func: ArrowFunctionExpression) {\n    if (t.isBlock(func.body)) {\n      return getReturnStatementArgumentFromBlockOrThrow(func.body);\n    }\n    return func.body;\n  }\n\n  function getIdentifierTextOrThrow(node: Node) {\n    if (!t.isIdentifier(node)) {\n      return throwError(`Expected node to be an identifier: ${getNodeText(node)}`);\n    }\n    return node.name;\n  }\n\n  function getReturnStatementArgumentFromBlockOrThrow(block: BlockStatement) {\n    return getReturnStatementArgumentFromBlock(t, block)\n      || throwError(`Cound not find return statement with an expression in function expression: ${getNodeText(block)}`);\n  }\n\n  function getNodeText(node: Node) {\n    const outerNodeStart = path.node.start!;\n    const innerNodeStart = node.start!;\n    const offset = innerNodeStart - outerNodeStart;\n\n    return path.getSource().substr(offset, node.end! - node.start!);\n  }\n\n  function isNameof(node: Node): node is CallExpression {\n    if (!t.isCallExpression(node)) {\n      return false;\n    }\n\n    const identifier = getIdentifierToInspect(node.callee);\n    return identifier != null && identifier.name === (options.nameofIdentifierName || \"nameof\");\n\n    function getIdentifierToInspect(expression: Expression | V8IntrinsicIdentifier) {\n      if (t.isIdentifier(expression)) {\n        return expression;\n      }\n      if (t.isMemberExpression(expression) && t.isIdentifier(expression.object)) {\n        return expression.object;\n      }\n      return undefined;\n    }\n  }\n\n  function handleNameofInterpolate(callExpr: CallExpression) {\n    if (!hasAncestorNameofFull()) {\n      return throwError(\n        `Found a nameof.interpolate that did not exist within a `\n          + `nameof.full call expression: ${getNodeText(callExpr)}`,\n      );\n    }\n\n    if (callExpr.arguments.length !== 1) {\n      return throwError(\"Unexpected scenario where a nameof.interpolate function did not have a single argument.\");\n    }\n\n    function hasAncestorNameofFull() {\n      let parentPath: NodePath | null | undefined = path.parentPath;\n      while (parentPath != null) {\n        if (isNameof(parentPath.node) && parsePropertyName(parentPath.node) === \"full\") {\n          return true;\n        }\n        parentPath = parentPath.parentPath;\n      }\n      return false;\n    }\n  }\n\n  function isInterpolatePropertyName(propertyName: string | undefined) {\n    return propertyName === \"interpolate\";\n  }\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/tests/pluginTests.ts",
    "content": "import * as babel from \"@babel/core\";\nimport \"@babel/preset-typescript\";\nimport { runCommonTests } from \"@ts-nameof/tests-common\";\nimport * as path from \"path\";\nimport { plugin } from \"../index\";\n\nrunCommonTests(run);\n\nfunction run(text: string) {\n  return babel.transformSync(text, {\n    presets: [\n      \"@babel/preset-typescript\",\n    ],\n    plugins: [\n      plugin,\n    ],\n    filename: path.resolve(__dirname, \"test.ts\"),\n    ast: false,\n    generatorOpts: {\n      retainLines: true,\n    },\n  })!.code!;\n}\n"
  },
  {
    "path": "packages/transforms-babel/src/transform.ts",
    "content": "import * as babelTypes from \"@babel/types\";\nimport { throwError } from \"@ts-nameof/common\";\nimport * as common from \"@ts-nameof/transforms-common\";\n\n/**\n * Transforms a common node to a Babel node.\n * @param node Common node to be transformed.\n */\nexport function transform(t: typeof babelTypes, node: common.Node): babelTypes.StringLiteral | babelTypes.ArrayExpression | babelTypes.TemplateLiteral {\n  switch (node.kind) {\n    case \"StringLiteral\":\n      return t.stringLiteral(node.value);\n    case \"ArrayLiteral\":\n      return t.arrayExpression(node.elements.map(element => transform(t, element)));\n    case \"TemplateExpression\":\n      return createTemplateLiteral(t, node);\n    default:\n      return throwError(`Unsupported node kind: ${node.kind}`);\n  }\n}\n\nfunction createTemplateLiteral(t: typeof babelTypes, node: common.TemplateExpressionNode) {\n  const quasis: babelTypes.TemplateElement[] = [];\n  const expressions: babelTypes.Expression[] = [];\n\n  for (const part of node.parts) {\n    if (typeof part === \"string\") {\n      quasis.push(t.templateElement({\n        // I believe for the use case of this library, both the raw and cooked can be the same, but adding this\n        // just in case for the future...\n        raw: getRawValue(part),\n        // Need to add this for @babel/preset-env.\n        cooked: part,\n      }));\n    } else {\n      const expr = part.expression as babelTypes.Expression;\n      expressions.push(expr);\n    }\n  }\n\n  // set the last quasi as the tail\n  quasis[quasis.length - 1].tail = true;\n\n  return t.templateLiteral(quasis, expressions);\n\n  function getRawValue(text: string) {\n    // From\n    // Adds a backslash before every `, \\ and ${\n    return text.replace(/\\\\|`|\\${/g, \"\\\\$&\");\n  }\n}\n"
  },
  {
    "path": "packages/transforms-babel/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src\"],\n  \"references\": [\n    { \"path\": \"../common\" },\n    { \"path\": \"../transforms-common\" },\n    { \"path\": \"../tests-common\" }\n  ]\n}\n"
  },
  {
    "path": "packages/transforms-common/.mocharc.yml",
    "content": "require: ts-node/register\nrecursive: true\nreporter: progress\nwatch-extensions: ts\ntimeout: 10000\nspec: src/tests/**/*.ts\n"
  },
  {
    "path": "packages/transforms-common/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\nsrc\r\ndist/tests\r\n.mocharc.yml\r\n*.log\r\n*.js.map"
  },
  {
    "path": "packages/transforms-common/README.md",
    "content": "# ts-nameof - Transforms Common\n\nContains the code shared between babel and typescript transforms.\n"
  },
  {
    "path": "packages/transforms-common/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/transforms-common\",\n  \"version\": \"4.2.1\",\n  \"description\": \"ts-nameof - Common code for transforms.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"npm run build && mocha\",\n    \"test:debug\": \"npm run build && mocha --inspect-brk\"\n  },\n  \"dependencies\": {\n    \"@ts-nameof/common\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/mocha\": \"^9.0.0\",\n    \"@types/node\": \"^17.0.0\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/transforms-common/src/StringOrTemplateExpressionBuilder.ts",
    "content": "import { createStringLiteralNode, createTemplateExpressionNode } from \"./nodeFactories\";\nimport { InterpolateNode, StringLiteralNode, TemplateExpressionNode } from \"./nodes\";\n\n/**\n * Builds up a string that will be a string literal if able, but will change to a template\n * expression if necessary.\n */\nexport class StringOrTemplateExpressionNodeBuilder {\n  private text: string | undefined = \"\";\n  private items: (string | InterpolateNode)[] = [];\n\n  hasText() {\n    return this.text != null && this.text.length > 0 || this.items.length > 0;\n  }\n\n  buildNode(): StringLiteralNode | TemplateExpressionNode {\n    if (this.text != null) {\n      return createStringLiteralNode(this.text);\n    }\n    return createTemplateExpressionNode(this.items);\n  }\n\n  addItem(item: string | InterpolateNode | StringLiteralNode | TemplateExpressionNode) {\n    if (typeof item === \"string\") {\n      this.addText(item);\n    } else if (item.kind === \"StringLiteral\") {\n      this.addText(item.value);\n    } else if (item.kind === \"TemplateExpression\") {\n      for (const part of item.parts) {\n        this.addItem(part);\n      }\n    } else {\n      this.addInterpolate(item);\n    }\n  }\n\n  addText(newText: string) {\n    if (this.text == null) {\n      if (typeof this.items[this.items.length - 1] === \"string\") {\n        this.items[this.items.length - 1] += newText;\n      } else {\n        this.items.push(newText);\n      }\n    } else {\n      this.text += newText;\n    }\n  }\n\n  private addInterpolate(interpolate: InterpolateNode) {\n    if (this.text != null) {\n      this.items.push(this.text);\n      this.text = undefined;\n    }\n    this.items.push(interpolate);\n  }\n}\n"
  },
  {
    "path": "packages/transforms-common/src/index.ts",
    "content": "export * from \"./nodeFactories\";\nexport * from \"./nodes\";\nexport * from \"./transformCallExpression\";\n"
  },
  {
    "path": "packages/transforms-common/src/nodeFactories.ts",
    "content": "import {\n  ArrayLiteralNode,\n  ComputedNode,\n  FunctionNode,\n  IdentifierNode,\n  ImportTypeNode,\n  InterpolateNode,\n  Node,\n  NumericLiteralNode,\n  StringLiteralNode,\n  TemplateExpressionNode,\n} from \"./nodes\";\n\nexport function createIdentifierNode(value: string, next?: Node | undefined): IdentifierNode {\n  return {\n    kind: \"Identifier\",\n    value,\n    next,\n  };\n}\n\nexport function createStringLiteralNode(value: string, next?: Node | undefined): StringLiteralNode {\n  return {\n    kind: \"StringLiteral\",\n    value,\n    next,\n  };\n}\n\nexport function createNumericLiteralNode(value: number, next?: Node | undefined): NumericLiteralNode {\n  return {\n    kind: \"NumericLiteral\",\n    value,\n    next,\n  };\n}\n\nexport function createArrayLiteralNode(elements: ArrayLiteralNode[\"elements\"], next?: Node | undefined): ArrayLiteralNode {\n  return {\n    kind: \"ArrayLiteral\",\n    elements,\n    next,\n  };\n}\n\nexport function createComputedNode(value: Node, next?: Node | undefined): ComputedNode {\n  return {\n    kind: \"Computed\",\n    value,\n    next,\n  };\n}\n\nexport function createFunctionNode(value: Node, parameterNames: string[], next?: Node | undefined): FunctionNode {\n  return {\n    kind: \"Function\",\n    parameterNames,\n    value,\n    next,\n  };\n}\n\nexport function createImportTypeNode(isTypeOf: boolean, argument: Node | undefined, next?: Node | undefined): ImportTypeNode {\n  return {\n    kind: \"ImportType\",\n    isTypeOf,\n    argument,\n    next,\n  };\n}\n\nexport function createTemplateExpressionNode(parts: (string | InterpolateNode)[], next?: Node | undefined): TemplateExpressionNode {\n  return {\n    kind: \"TemplateExpression\",\n    parts,\n    next,\n  };\n}\n\nexport function createInterpolateNode(expression: unknown, expressionText: string, next?: Node | undefined): InterpolateNode {\n  return {\n    kind: \"Interpolate\",\n    expression,\n    expressionText,\n    next,\n  };\n}\n"
  },
  {
    "path": "packages/transforms-common/src/nodeHelpers.ts",
    "content": "import { Node } from \"./nodes\";\n\nexport function flattenNodeToArray(node: Node) {\n  const flattenedNodes: Node[] = [node];\n  while (node.next != null) {\n    flattenedNodes.push(node.next);\n    node = node.next;\n  }\n  return flattenedNodes;\n}\n\nexport function getLastNextNode(node: Node) {\n  while (node.next != null) {\n    node = node.next;\n  }\n  return node;\n}\n"
  },
  {
    "path": "packages/transforms-common/src/nodes.ts",
    "content": "// common AST to share between babel and typescript\n\nexport interface NameofCallExpression {\n  property: string | undefined;\n  typeArguments: Node[];\n  arguments: Node[];\n}\n\nexport type Node =\n  | IdentifierNode\n  | StringLiteralNode\n  | NumericLiteralNode\n  | ArrayLiteralNode\n  | ComputedNode\n  | FunctionNode\n  | ImportTypeNode\n  | TemplateExpressionNode\n  | InterpolateNode;\n\nexport interface IdentifierNode {\n  kind: \"Identifier\";\n  value: string;\n  next: Node | undefined;\n}\n\nexport interface StringLiteralNode {\n  kind: \"StringLiteral\";\n  value: string;\n  next: Node | undefined;\n}\n\nexport interface NumericLiteralNode {\n  kind: \"NumericLiteral\";\n  value: number;\n  next: Node | undefined;\n}\n\nexport interface ArrayLiteralNode {\n  kind: \"ArrayLiteral\";\n  elements: Node[];\n  next: Node | undefined;\n}\n\n/**\n * Node surrounded in brackets.\n * Ex. `[4]` in `obj[4]`\n */\nexport interface ComputedNode {\n  kind: \"Computed\";\n  value: Node;\n  next: Node | undefined;\n}\n\nexport interface FunctionNode {\n  kind: \"Function\";\n  parameterNames: string[];\n  value: Node;\n  next: Node | undefined;\n}\n\nexport interface ImportTypeNode {\n  kind: \"ImportType\";\n  isTypeOf: boolean;\n  argument: Node | undefined;\n  next: Node | undefined;\n}\n\nexport interface TemplateExpressionNode {\n  kind: \"TemplateExpression\";\n  parts: (string | InterpolateNode)[];\n  next: Node | undefined;\n}\n\n/**\n * An interpolate node.\n * Ex. Created from call expressions such as: `nameof.interpolate(expression)`\n */\nexport interface InterpolateNode {\n  kind: \"Interpolate\";\n  /** The original AST node. */\n  expression: unknown;\n  /** The expression text for printing purposes. */\n  expressionText: string;\n  next: Node | undefined;\n}\n"
  },
  {
    "path": "packages/transforms-common/src/printers.ts",
    "content": "import { assertNever } from \"@ts-nameof/common\";\nimport { NameofCallExpression, Node, TemplateExpressionNode } from \"./nodes\";\n\n/**\n * Prints the call expression to a string. Useful for displaying diagnostic information to the user.\n * @param callExpr `nameof` call expression to print.\n */\nexport function printCallExpression(callExpr: NameofCallExpression) {\n  let result = \"nameof\";\n\n  writePropertyName();\n  if (callExpr.typeArguments.length > 0) {\n    writeTypeArguments();\n  }\n  writeArguments();\n\n  return result;\n\n  function writePropertyName() {\n    if (callExpr.property != null) {\n      result += `.${callExpr.property}`;\n    }\n  }\n\n  function writeTypeArguments() {\n    result += \"<\";\n    for (let i = 0; i < callExpr.typeArguments.length; i++) {\n      if (i > 0) {\n        result += \", \";\n      }\n      result += printNode(callExpr.typeArguments[i]);\n    }\n    result += \">\";\n  }\n\n  function writeArguments() {\n    result += \"(\";\n    for (let i = 0; i < callExpr.arguments.length; i++) {\n      if (i > 0) {\n        result += \", \";\n      }\n      result += printNode(callExpr.arguments[i]);\n    }\n    result += \")\";\n  }\n}\n\n/**\n * Prints a node to a string. Useful for displaying diagnostic information to the user.\n * @param node Node to print.\n */\nexport function printNode(node: Node): string {\n  // todo: this should throw in more scenarios (ex. string literal after an identifier)\n  let result = getCurrentText();\n\n  if (node.next != null) {\n    if (node.next.kind === \"Identifier\") {\n      result += \".\" + printNode(node.next);\n    } else {\n      result += printNode(node.next);\n    }\n  }\n\n  return result;\n\n  function getCurrentText() {\n    switch (node.kind) {\n      case \"StringLiteral\":\n        return `\\\"${node.value}\\\"`;\n      case \"NumericLiteral\":\n        return node.value.toString();\n      case \"Identifier\":\n        return node.value;\n      case \"Computed\":\n        return `[${printNode(node.value)}]`;\n      case \"Function\":\n        let functionResult = `(${node.parameterNames.join(\", \")}) => ${printNode(node.value)}`;\n        if (node.next != null) {\n          functionResult = `(${functionResult})`;\n        }\n        return functionResult;\n      case \"ArrayLiteral\":\n        return `[${node.elements.map(e => printNode(e)).join(\", \")}]`;\n      case \"ImportType\":\n        return (node.isTypeOf ? \"typeof \" : \"\") + `import(${node.argument == null ? \"\" : printNode(node.argument)})`;\n      case \"Interpolate\":\n        return `nameof.interpolate(${node.expressionText})`;\n      case \"TemplateExpression\":\n        return printTemplateExpression(node);\n      default:\n        return assertNever(node, `Unhandled kind: ${(node as Node).kind}`);\n    }\n  }\n\n  function printTemplateExpression(TemplateExpression: TemplateExpressionNode) {\n    let text = \"`\";\n    for (const part of TemplateExpression.parts) {\n      if (typeof part === \"string\") {\n        text += part;\n      } else {\n        text += \"${\" + printNode(part) + \"}\";\n      }\n    }\n    text += \"`\";\n    return text;\n  }\n}\n"
  },
  {
    "path": "packages/transforms-common/src/tests/printerTests.ts",
    "content": "import * as assert from \"assert\";\nimport * as factories from \"../nodeFactories\";\nimport { NameofCallExpression, Node } from \"../nodes\";\nimport * as printers from \"../printers\";\n\ndescribe(\"printCallExpression\", () => {\n  function doTest(callExpr: NameofCallExpression, expectedText: string) {\n    const result = printers.printCallExpression(callExpr);\n    assert.equal(result, expectedText);\n  }\n\n  it(\"should print a basic call expression\", () => {\n    doTest({\n      property: undefined,\n      typeArguments: [],\n      arguments: [],\n    }, \"nameof()\");\n  });\n\n  it(\"should print with a property\", () => {\n    doTest({\n      property: \"full\",\n      typeArguments: [],\n      arguments: [],\n    }, \"nameof.full()\");\n  });\n\n  it(\"should print with an argument\", () => {\n    doTest({\n      property: undefined,\n      typeArguments: [],\n      arguments: [factories.createIdentifierNode(\"test\")],\n    }, \"nameof(test)\");\n  });\n\n  it(\"should print with arguments\", () => {\n    doTest({\n      property: undefined,\n      typeArguments: [],\n      arguments: [\n        factories.createIdentifierNode(\"test1\"),\n        factories.createIdentifierNode(\"test2\"),\n      ],\n    }, \"nameof(test1, test2)\");\n  });\n\n  it(\"should print with a type argument\", () => {\n    doTest({\n      property: undefined,\n      typeArguments: [factories.createIdentifierNode(\"T\")],\n      arguments: [],\n    }, \"nameof<T>()\");\n  });\n\n  it(\"should print with type arguments\", () => {\n    doTest({\n      property: undefined,\n      typeArguments: [\n        factories.createIdentifierNode(\"T\"),\n        factories.createIdentifierNode(\"U\"),\n      ],\n      arguments: [],\n    }, \"nameof<T, U>()\");\n  });\n\n  it(\"should print with everything\", () => {\n    doTest({\n      property: \"full\",\n      typeArguments: [\n        factories.createIdentifierNode(\"T\"),\n        factories.createIdentifierNode(\"U\"),\n      ],\n      arguments: [\n        factories.createIdentifierNode(\"test1\"),\n        factories.createIdentifierNode(\"test2\"),\n      ],\n    }, \"nameof.full<T, U>(test1, test2)\");\n  });\n});\n\ndescribe(\"printNode\", () => {\n  function doTest(node: Node, expectedText: string) {\n    const result = printers.printNode(node);\n    assert.equal(result, expectedText);\n  }\n\n  describe(\"identifier\", () => {\n    it(\"should print an identifier\", () => {\n      doTest(factories.createIdentifierNode(\"Test\"), \"Test\");\n    });\n\n    it(\"should print the next identifier separated by a period\", () => {\n      doTest(factories.createIdentifierNode(\"Test\", factories.createIdentifierNode(\"Next\")), \"Test.Next\");\n    });\n\n    it(\"should print the next computed value with no separation\", () => {\n      const node = factories.createIdentifierNode(\"Test\", factories.createComputedNode(factories.createStringLiteralNode(\"prop\")));\n      doTest(node, `Test[\"prop\"]`);\n    });\n  });\n\n  describe(\"string literal\", () => {\n    it(\"should print in quotes\", () => {\n      doTest(factories.createStringLiteralNode(\"test\"), `\"test\"`);\n    });\n\n    it(\"should print with a property after\", () => {\n      const node = factories.createStringLiteralNode(\"test\", factories.createIdentifierNode(\"length\"));\n      doTest(node, `\"test\".length`);\n    });\n  });\n\n  describe(\"numeric literal\", () => {\n    it(\"should print\", () => {\n      doTest(factories.createNumericLiteralNode(5), `5`);\n    });\n\n    it(\"should print with a property after\", () => {\n      const node = factories.createNumericLiteralNode(5, factories.createIdentifierNode(\"length\"));\n      doTest(node, `5.length`);\n    });\n  });\n\n  describe(\"computed\", () => {\n    it(\"should print inside brackets\", () => {\n      const node = factories.createComputedNode(factories.createStringLiteralNode(\"test\"));\n      doTest(node, `[\"test\"]`);\n    });\n\n    it(\"should print with a property after\", () => {\n      const node = factories.createComputedNode(factories.createNumericLiteralNode(5), factories.createIdentifierNode(\"length\"));\n      doTest(node, `[5].length`);\n    });\n  });\n\n  describe(\"function\", () => {\n    it(\"should print with no arguments\", () => {\n      const node = factories.createFunctionNode(factories.createNumericLiteralNode(5), []);\n      doTest(node, `() => 5`);\n    });\n\n    it(\"should print with an argument\", () => {\n      const node = factories.createFunctionNode(factories.createNumericLiteralNode(5), [\"p\"]);\n      doTest(node, `(p) => 5`); // keep it simple (don't bother removing parens)\n    });\n\n    it(\"should print with arguments\", () => {\n      const node = factories.createFunctionNode(factories.createNumericLiteralNode(5), [\"a\", \"b\"]);\n      doTest(node, `(a, b) => 5`);\n    });\n\n    it(\"should print with a property after\", () => {\n      const node = factories.createFunctionNode(factories.createNumericLiteralNode(5), [\"a\", \"b\"], factories.createIdentifierNode(\"length\"));\n      doTest(node, `((a, b) => 5).length`);\n    });\n  });\n\n  describe(\"array\", () => {\n    it(\"should print the array with no elements\", () => {\n      const node = factories.createArrayLiteralNode([]);\n      doTest(node, \"[]\");\n    });\n\n    it(\"should print the array with one element\", () => {\n      const node = factories.createArrayLiteralNode([factories.createStringLiteralNode(\"test\")]);\n      doTest(node, `[\"test\"]`);\n    });\n\n    it(\"should print the array with multiple elements\", () => {\n      const node = factories.createArrayLiteralNode([factories.createStringLiteralNode(\"test\"), factories.createStringLiteralNode(\"test2\")]);\n      doTest(node, `[\"test\", \"test2\"]`);\n    });\n\n    it(\"should print with a property after\", () => {\n      const node = factories.createArrayLiteralNode([], factories.createIdentifierNode(\"length\"));\n      doTest(node, `[].length`);\n    });\n  });\n\n  describe(\"import type\", () => {\n    it(\"should print when it has no argument\", () => {\n      const node = factories.createImportTypeNode(false, undefined, factories.createIdentifierNode(\"length\"));\n      doTest(node, `import().length`);\n    });\n\n    it(\"should print when it receives an identifier\", () => {\n      const node = factories.createImportTypeNode(false, factories.createIdentifierNode(\"test\"), undefined);\n      doTest(node, `import(test)`);\n    });\n\n    it(\"should print when it receives a string literal\", () => {\n      const node = factories.createImportTypeNode(false, factories.createStringLiteralNode(\"test\"), undefined);\n      doTest(node, `import(\"test\")`);\n    });\n\n    it(\"should print when it has a typeof\", () => {\n      const node = factories.createImportTypeNode(true, factories.createIdentifierNode(\"test\"));\n      doTest(node, `typeof import(test)`);\n    });\n  });\n\n  describe(\"template literal\", () => {\n    it(\"should print when only has a string\", () => {\n      const node = factories.createTemplateExpressionNode([\"testing\"], factories.createIdentifierNode(\"length\"));\n      doTest(node, \"`testing`.length\");\n    });\n\n    it(\"should print when also has an interpolate node\", () => {\n      const node = factories.createTemplateExpressionNode([\"testing\", factories.createInterpolateNode(undefined, \"myVar\"), \"this\"]);\n      // in practice, the printer will never be printing a template literal\n      doTest(node, \"`testing${nameof.interpolate(myVar)}this`\");\n    });\n  });\n\n  describe(\"interpolate node\", () => {\n    it(\"should print\", () => {\n      const node = factories.createInterpolateNode(undefined, \"myVar\", factories.createIdentifierNode(\"length\"));\n      doTest(node, \"nameof.interpolate(myVar).length\");\n    });\n  });\n});\n"
  },
  {
    "path": "packages/transforms-common/src/transformCallExpression.ts",
    "content": "import { assertNever, throwError } from \"@ts-nameof/common\";\nimport { createArrayLiteralNode, createStringLiteralNode, createTemplateExpressionNode } from \"./nodeFactories\";\nimport { flattenNodeToArray, getLastNextNode } from \"./nodeHelpers\";\nimport { FunctionNode, NameofCallExpression, Node, StringLiteralNode, TemplateExpressionNode } from \"./nodes\";\nimport { printCallExpression, printNode } from \"./printers\";\nimport { StringOrTemplateExpressionNodeBuilder } from \"./StringOrTemplateExpressionBuilder\";\n\nexport function transformCallExpression(callExpr: NameofCallExpression) {\n  if (callExpr.property == null) {\n    return handleNameof(callExpr);\n  }\n  if (callExpr.property === \"full\") {\n    return handleNameofFull(callExpr);\n  }\n  if (callExpr.property === \"toArray\") {\n    return handleNameofToArray(callExpr);\n  }\n  if (callExpr.property === \"split\") {\n    return handleNameofSplit(callExpr);\n  }\n  return throwError(`Unsupported nameof call expression with property '${callExpr.property}': ${printCallExpression(callExpr)}`);\n}\n\nfunction handleNameof(callExpr: NameofCallExpression) {\n  return parseNameofExpression(getExpression());\n\n  function getExpression() {\n    if (callExpr.arguments.length === 1) {\n      return callExpr.arguments[0];\n    } else if (callExpr.typeArguments.length === 1) {\n      return callExpr.typeArguments[0];\n    }\n    return throwError(`Call expression must have one argument or type argument: ${printCallExpression(callExpr)}`);\n  }\n}\n\nfunction handleNameofFull(callExpr: NameofCallExpression) {\n  return parseNameofFullExpression(getNodesFromCallExpression(callExpr));\n}\n\nfunction handleNameofSplit(callExpr: NameofCallExpression) {\n  const literalNodes = getNodesFromCallExpression(callExpr).map(node => parseNode(node));\n  return createArrayLiteralNode(literalNodes);\n}\n\nfunction handleNameofToArray(callExpr: NameofCallExpression) {\n  const arrayArguments = getNodeArray();\n  return createArrayLiteralNode(arrayArguments.map(element => parseNameofExpression(element)));\n\n  function getNodeArray() {\n    if (callExpr.arguments.length === 0) {\n      return throwError(`Unable to parse call expression. No arguments provided: ${printCallExpression(callExpr)}`);\n    }\n\n    const firstArgument = callExpr.arguments[0];\n    if (callExpr.arguments.length === 1 && firstArgument.kind === \"Function\") {\n      return handleFunction(firstArgument);\n    } else {\n      return callExpr.arguments;\n    }\n\n    function handleFunction(func: FunctionNode) {\n      const functionReturnValue = func.value;\n\n      if (functionReturnValue == null || functionReturnValue.kind !== \"ArrayLiteral\") {\n        return throwError(`Unsupported toArray call expression. An array must be returned by the provided function: ${printCallExpression(callExpr)}`);\n      }\n\n      return functionReturnValue.elements;\n    }\n  }\n}\n\nfunction getNodesFromCallExpression(callExpr: NameofCallExpression) {\n  const { expression, count } = getExpressionAndCount();\n  return getNodesFromCount(flattenNodeToArray(expression), count);\n\n  function getExpressionAndCount() {\n    if (shouldUseArguments()) {\n      return {\n        expression: getArgumentExpression(),\n        count: getCountFromNode(callExpr.arguments.length > 1 ? callExpr.arguments[1] : undefined),\n      };\n    }\n    if (callExpr.typeArguments.length > 0) {\n      return {\n        expression: callExpr.typeArguments[0],\n        count: getCountFromNode(callExpr.arguments.length > 0 ? callExpr.arguments[0] : undefined),\n      };\n    }\n\n    return throwError(`Unsupported use of nameof.full: ${printCallExpression(callExpr)}`);\n\n    function shouldUseArguments() {\n      if (callExpr.arguments.length === 0) {\n        return false;\n      }\n      if (callExpr.typeArguments.length === 0) {\n        return true;\n      }\n\n      return callExpr.arguments[0].kind === \"Function\";\n    }\n\n    function getArgumentExpression() {\n      let expression = callExpr.arguments[0];\n      if (expression.kind === \"Function\") {\n        expression = expression.value;\n        // skip over the first identifier (ex. skip over `obj` in `obj => obj.test`)\n        if (expression.next == null) {\n          return throwError(`A property must be accessed on the object: ${printNode(callExpr.arguments[0])}`);\n        }\n        expression = expression.next;\n      }\n      return expression;\n    }\n\n    function getCountFromNode(countExpr: Node | undefined) {\n      if (countExpr == null) {\n        return 0;\n      }\n\n      if (countExpr.kind !== \"NumericLiteral\") {\n        return throwError(`Expected count to be a number, but was: ${printNode(countExpr)}`);\n      }\n\n      return countExpr.value;\n    }\n  }\n\n  function getNodesFromCount(nodes: Node[], count: number) {\n    if (count > 0) {\n      if (count > nodes.length - 1) {\n        return throwError(`Count of ${count} was larger than max count of ${nodes.length - 1}: ${printCallExpression(callExpr)}`);\n      }\n      return nodes.slice(count);\n    }\n    if (count < 0) {\n      if (Math.abs(count) > nodes.length) {\n        return throwError(`Count of ${count} was larger than max count of ${nodes.length * -1}: ${printCallExpression(callExpr)}`);\n      }\n      return nodes.slice(nodes.length + count);\n    }\n    return nodes;\n  }\n}\n\nfunction parseNameofExpression(expression: Node) {\n  return parseNode(getNodeForNameOf(), expression);\n\n  function getNodeForNameOf() {\n    const node = getLastNextNode(expression);\n    if (node.kind === \"Function\") {\n      const argument = node.value;\n      if (argument.next == null) {\n        return throwError(`A property must be accessed on the object: ${printNode(expression)}`);\n      }\n      return getLastNextNode(argument.next);\n    }\n    return node;\n  }\n}\n\nfunction parseNode(node: Node, parent?: Node) {\n  switch (node.kind) {\n    case \"Identifier\":\n      return createStringLiteralNode(node.value);\n    case \"StringLiteral\":\n      // make a copy\n      return createStringLiteralNode(node.value);\n    case \"TemplateExpression\":\n      // todo: test this\n      return createTemplateExpressionNode(node.parts);\n    case \"NumericLiteral\":\n      // make a copy\n      return createStringLiteralNode(node.value.toString());\n    case \"Function\":\n      return throwError(`Nesting functions is not supported: ${printNode(parent || node)}`);\n    case \"Computed\":\n      if (node.value.kind === \"StringLiteral\" && node.value.next == null) {\n        return createStringLiteralNode(node.value.value);\n      }\n      return throwError(`First accessed property must not be computed except if providing a string: ${printNode(parent || node)}`);\n    case \"Interpolate\":\n    case \"ArrayLiteral\":\n    case \"ImportType\":\n      return throwNotSupportedErrorForNode(node);\n    default:\n      return assertNever(node, `Not implemented node: ${JSON.stringify(node)}`);\n  }\n}\n\nfunction parseNameofFullExpression(expressionNodes: Node[]): StringLiteralNode | TemplateExpressionNode {\n  const nodeBuilder = new StringOrTemplateExpressionNodeBuilder();\n\n  for (let i = 0; i < expressionNodes.length; i++) {\n    const node = expressionNodes[i];\n    if (i > 0 && node.kind === \"Identifier\") {\n      nodeBuilder.addText(\".\");\n    }\n    addNodeToBuilder(node);\n  }\n\n  return nodeBuilder.buildNode();\n\n  function addNodeToBuilder(node: Node) {\n    switch (node.kind) {\n      case \"Identifier\":\n        nodeBuilder.addText(node.value);\n        break;\n      case \"Computed\":\n        nodeBuilder.addText(\"[\");\n        const computedNodes = flattenNodeToArray(node.value);\n        for (let i = 0; i < computedNodes.length; i++) {\n          const computedNode = computedNodes[i];\n          if (computedNode.kind === \"StringLiteral\") {\n            nodeBuilder.addText(`\"${computedNode.value}\"`);\n          } else {\n            if (i > 0 && computedNode.kind === \"Identifier\") {\n              nodeBuilder.addText(\".\");\n            }\n            addNodeToBuilder(computedNode);\n          }\n        }\n        nodeBuilder.addText(\"]\");\n        break;\n      case \"TemplateExpression\":\n      case \"StringLiteral\":\n        nodeBuilder.addItem(node);\n        break;\n      case \"NumericLiteral\":\n        nodeBuilder.addText(node.value.toString());\n        break;\n      case \"Interpolate\":\n        nodeBuilder.addItem(node);\n        break;\n      case \"ArrayLiteral\":\n      case \"ImportType\":\n      case \"Function\":\n        return throwNotSupportedErrorForNode(node);\n      default:\n        return assertNever(node, `Not implemented node: ${JSON.stringify(node)}`);\n    }\n  }\n}\n\nfunction throwNotSupportedErrorForNode(node: Node) {\n  return throwError(`The node \\`${printNode(node)}\\` is not supported in this scenario.`);\n}\n"
  },
  {
    "path": "packages/transforms-common/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src/**/*.ts\"],\n  \"references\": [\n    { \"path\": \"../common\" }\n  ]\n}\n"
  },
  {
    "path": "packages/transforms-ts/.mocharc.yml",
    "content": "require: ts-node/register\nrecursive: true\nreporter: progress\nwatch-extensions: ts\ntimeout: 10000\nspec: src/tests/**/*.ts\n"
  },
  {
    "path": "packages/transforms-ts/.npmignore",
    "content": "tsconfig.json\r\ntsconfig.tsbuildinfo\r\nsrc\r\ndist/tests\r\n.mocharc.yml\r\n*.log\r\n*.js.map\r\n"
  },
  {
    "path": "packages/transforms-ts/README.md",
    "content": "# ts-nameof - TypeScript transforms\n\nContains the TypeScript Compiler API transforms used in ts-nameof.\n\n## Development Commands\n\n```\nnpm run test\n```\n"
  },
  {
    "path": "packages/transforms-ts/package.json",
    "content": "{\n  \"name\": \"@ts-nameof/transforms-ts\",\n  \"version\": \"4.2.1\",\n  \"description\": \"ts-nameof - TypeScript compiler transforms for ts-nameof packages.\",\n  \"main\": \"./dist/index.js\",\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b\",\n    \"test\": \"npm run build && mocha\",\n    \"test:debug\": \"npm run build && mocha --inspect-brk\"\n  },\n  \"dependencies\": {\n    \"@ts-nameof/common\": \"^4.2.1\",\n    \"@ts-nameof/transforms-common\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"@ts-nameof/tests-common\": \"^4.2.0\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/VisitSourceFileContext.ts",
    "content": "import * as ts from \"typescript\";\n\nexport interface VisitSourceFileContext {\n  interpolateExpressions: Set<ts.Node>;\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/helpers.ts",
    "content": "import { throwError } from \"@ts-nameof/common\";\nimport * as ts from \"typescript\";\n\nexport function isNegativeNumericLiteral(node: ts.Node): node is ts.PrefixUnaryExpression {\n  if (!ts.isPrefixUnaryExpression(node)) {\n    return false;\n  }\n\n  return node.operator === ts.SyntaxKind.MinusToken\n    && ts.isNumericLiteral(node.operand);\n}\n\nexport function getNegativeNumericLiteralValue(node: ts.PrefixUnaryExpression) {\n  if (node.operator !== ts.SyntaxKind.MinusToken || !ts.isNumericLiteral(node.operand)) {\n    return throwError(\"The passed in PrefixUnaryExpression must be for a negative numeric literal.\");\n  }\n\n  const result = parseFloat(node.operand.text);\n  if (isNaN(result)) {\n    return throwError(`Unable to parse negative numeric literal: ${node.operand.text}`);\n  }\n  return result * -1;\n}\n\nexport function getReturnStatementExpressionFromBlock(block: ts.Block) {\n  for (const statement of block.statements) {\n    if (ts.isReturnStatement(statement) && statement.expression != null) {\n      return statement.expression;\n    }\n  }\n\n  return undefined;\n}\n\n// todo: remove the use of the printer except for exceptions\nconst printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n\nexport function getNodeText(node: ts.Node, sourceFile: ts.SourceFile) {\n  return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/index.ts",
    "content": "export { TransformResult } from \"./transform\";\nexport * from \"./transformerFactory\";\nexport { VisitSourceFileContext } from \"./VisitSourceFileContext\";\n"
  },
  {
    "path": "packages/transforms-ts/src/parse.ts",
    "content": "import { assertNever, throwError } from \"@ts-nameof/common\";\nimport * as common from \"@ts-nameof/transforms-common\";\nimport { createInterpolateNode, InterpolateNode } from \"@ts-nameof/transforms-common\";\nimport * as ts from \"typescript\";\nimport { getNegativeNumericLiteralValue, getNodeText, getReturnStatementExpressionFromBlock, isNegativeNumericLiteral } from \"./helpers\";\nimport { VisitSourceFileContext } from \"./VisitSourceFileContext\";\n\n/**\n * Parses a TypeScript AST node to a common NameofCallExpression or returns undefined if the current node\n * is not a nameof call expression.\n * @param parsingNode - Babel AST node to parse.\n * @param sourceFile - Containing source file.\n * @param context - Context for when visiting all the source file nodes\n */\nexport function parse(parsingNode: ts.Node, sourceFile: ts.SourceFile, context: VisitSourceFileContext | undefined) {\n  if (!isNameof(parsingNode)) {\n    return undefined;\n  }\n\n  const propertyName = parsePropertyName(parsingNode);\n\n  // Ignore nameof.interpolate function calls... they will be dealt with later.\n  if (isInterpolatePropertyName(propertyName)) {\n    handleNameofInterpolate(parsingNode);\n    return undefined;\n  }\n\n  return parseNameof(parsingNode);\n\n  function parseNameof(callExpr: ts.CallExpression): common.NameofCallExpression {\n    return {\n      property: propertyName,\n      typeArguments: parseTypeArguments(callExpr),\n      arguments: parseArguments(callExpr),\n    };\n  }\n\n  function parsePropertyName(callExpr: ts.CallExpression) {\n    const { expression } = callExpr;\n    if (!ts.isPropertyAccessExpression(expression) || !ts.isIdentifier(expression.name)) {\n      return undefined;\n    }\n    return expression.name.text;\n  }\n\n  function parseTypeArguments(callExpr: ts.CallExpression) {\n    if (callExpr.typeArguments == null) {\n      return [];\n    }\n    return callExpr.typeArguments.map(arg => parseCommonNode(arg));\n  }\n\n  function parseArguments(callExpr: ts.CallExpression) {\n    return callExpr.arguments.map(arg => parseCommonNode(arg));\n  }\n\n  function parseCommonNode(node: ts.Expression | ts.TypeNode | ts.EntityName): common.Node {\n    if (ts.isPropertyAccessExpression(node)) {\n      return parsePropertyAccessExpression(node);\n    }\n    if (ts.isElementAccessExpression(node)) {\n      return parseElementAccessExpression(node);\n    }\n    if (ts.isArrowFunction(node)) {\n      return parseFunctionReturnExpression(node, getArrowFunctionReturnExpression(node));\n    }\n    if (ts.isFunctionExpression(node)) {\n      return parseFunctionReturnExpression(node, getReturnStatementExpressionFromBlockOrThrow(node.body));\n    }\n    if (ts.isNonNullExpression(node) || ts.isParenthesizedExpression(node) || ts.isAsExpression(node)) {\n      return parseCommonNode(node.expression);\n    }\n    if (ts.isQualifiedName(node)) {\n      return parseQualifiedName(node);\n    }\n    if (ts.isTypeReferenceNode(node)) {\n      return parseCommonNode(node.typeName);\n    }\n    if (ts.isSpreadElement(node)) {\n      return parseCommonNode(node.expression);\n    }\n    if (ts.isNumericLiteral(node) || isNegativeNumericLiteral(node)) {\n      return parseNumeric(node);\n    }\n    if (ts.isStringLiteral(node)) {\n      return parseStringLiteral(node);\n    }\n    if (ts.isArrayLiteralExpression(node)) {\n      return parseArrayLiteralExpression(node);\n    }\n    if (ts.isIdentifier(node)) {\n      return parseIdentifier(node);\n    }\n    if (ts.isImportTypeNode(node)) {\n      return parseImportType(node);\n    }\n    if (ts.isLiteralTypeNode(node)) {\n      return parseCommonNode(node.literal); // skip over and go straight to the literal\n    }\n    if (node.kind === ts.SyntaxKind.ThisKeyword) {\n      return common.createIdentifierNode(\"this\");\n    }\n    if (node.kind === ts.SyntaxKind.SuperKeyword) {\n      return common.createIdentifierNode(\"super\");\n    }\n    if (ts.isNoSubstitutionTemplateLiteral(node)) {\n      return common.createTemplateExpressionNode([node.text]);\n    }\n    if (ts.isTemplateExpression(node)) {\n      return parseTemplateExpression(node);\n    }\n    if (isNameof(node) && isInterpolatePropertyName(parsePropertyName(node))) {\n      return parseInterpolateNode(node);\n    }\n    return throwError(\n      `Unhandled node kind (${node.kind}) in text: ${getNodeText(node, sourceFile)}`\n        + ` (Please open an issue if you believe this should be supported.)`,\n    );\n  }\n\n  function parseArrayLiteralExpression(node: ts.ArrayLiteralExpression) {\n    const elements = node.elements.map(element => parseCommonNode(element));\n    return common.createArrayLiteralNode(elements);\n  }\n\n  function parsePropertyAccessExpression(node: ts.PropertyAccessExpression) {\n    const expressionCommonNode = parseCommonNode(node.expression);\n    const nameCommonNode = parseIdentifier(node.name);\n    getEndCommonNode(expressionCommonNode).next = nameCommonNode;\n    return expressionCommonNode;\n  }\n\n  function parseElementAccessExpression(node: ts.ElementAccessExpression) {\n    const expressionCommonNode = parseCommonNode(node.expression);\n    const argumentExpressionCommonNode = parseCommonNode(node.argumentExpression);\n    const computedCommonNode = common.createComputedNode(argumentExpressionCommonNode);\n    getEndCommonNode(expressionCommonNode).next = computedCommonNode;\n    return expressionCommonNode;\n  }\n\n  function parseQualifiedName(node: ts.QualifiedName) {\n    const leftCommonNode = parseCommonNode(node.left);\n    const rightCommonNode = parseCommonNode(node.right);\n    getEndCommonNode(leftCommonNode).next = rightCommonNode;\n    return leftCommonNode;\n  }\n\n  function parseNumeric(node: ts.NumericLiteral | ts.PrefixUnaryExpression) {\n    return common.createNumericLiteralNode(getNodeValue());\n\n    function getNodeValue() {\n      if (ts.isNumericLiteral(node)) {\n        return parseFloat(node.text);\n      }\n      return getNegativeNumericLiteralValue(node);\n    }\n  }\n\n  function parseStringLiteral(node: ts.StringLiteral) {\n    return common.createStringLiteralNode(node.text);\n  }\n\n  function parseIdentifier(node: ts.Node) {\n    const text = getIdentifierTextOrThrow(node);\n    return common.createIdentifierNode(text);\n  }\n\n  function parseFunctionReturnExpression(functionLikeNode: ts.FunctionLike, node: ts.Expression) {\n    const parameterNames = functionLikeNode.parameters.map(p => {\n      const name = p.name;\n      if (ts.isIdentifier(name)) {\n        return name.text;\n      }\n      return getNodeText(name, sourceFile);\n    });\n\n    return common.createFunctionNode(parseCommonNode(node), parameterNames);\n  }\n\n  function parseImportType(node: ts.ImportTypeNode) {\n    const importType = common.createImportTypeNode(node.isTypeOf || false, node.argument && parseCommonNode(node.argument));\n    const qualifier = node.qualifier && parseCommonNode(node.qualifier);\n    getEndCommonNode(importType).next = qualifier;\n    return importType;\n  }\n\n  function parseTemplateExpression(node: ts.TemplateExpression) {\n    return common.createTemplateExpressionNode(getParts());\n\n    function getParts() {\n      const parts: (string | InterpolateNode)[] = [];\n      if (node.head.text.length > 0) {\n        parts.push(node.head.text);\n      }\n      for (const templateSpan of node.templateSpans) {\n        parts.push(createInterpolateNode(templateSpan.expression, getNodeText(templateSpan.expression, sourceFile)));\n        parts.push(templateSpan.literal.text);\n      }\n      return parts;\n    }\n  }\n\n  function parseInterpolateNode(node: ts.CallExpression) {\n    if (node.arguments.length !== 1) {\n      return throwError(`Should never happen as this would have been tested for earlier.`);\n    }\n    return common.createInterpolateNode(node.arguments[0], getNodeText(node.arguments[0], sourceFile));\n  }\n\n  function getEndCommonNode(commonNode: common.Node) {\n    while (commonNode.next != null) {\n      commonNode = commonNode.next;\n    }\n    return commonNode;\n  }\n\n  function getArrowFunctionReturnExpression(func: ts.ArrowFunction) {\n    if (ts.isBlock(func.body)) {\n      return getReturnStatementExpressionFromBlockOrThrow(func.body);\n    }\n    return func.body;\n  }\n\n  function getIdentifierTextOrThrow(node: ts.Node) {\n    if (!ts.isIdentifier(node)) {\n      return throwError(`Expected node to be an identifier: ${getNodeText(node, sourceFile)}`);\n    }\n    return node.text;\n  }\n\n  function getReturnStatementExpressionFromBlockOrThrow(block: ts.Block) {\n    return getReturnStatementExpressionFromBlock(block)\n      || throwError(`Cound not find return statement with an expression in function expression: ${getNodeText(block, sourceFile)}`);\n  }\n\n  function handleNameofInterpolate(callExpr: ts.CallExpression) {\n    if (callExpr.arguments.length !== 1) {\n      return throwError(\"Unexpected scenario where a nameof.interpolate function did not have a single argument.\");\n    }\n\n    // Add the interpolate expression to the context so that it can be checked later to find\n    // nameof.interpolate calls that were never resolved.\n    if (context != null) {\n      context.interpolateExpressions.add(callExpr.arguments[0]);\n    }\n  }\n\n  function isNameof(node: ts.Node): node is ts.CallExpression {\n    if (!ts.isCallExpression(node)) {\n      return false;\n    }\n\n    const identifier = getIdentifierToInspect(node.expression);\n    return identifier != null && identifier.text === \"nameof\";\n\n    function getIdentifierToInspect(expression: ts.LeftHandSideExpression) {\n      if (ts.isIdentifier(expression)) {\n        return expression;\n      }\n      if (ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression)) {\n        return expression.expression;\n      }\n    }\n  }\n\n  function isInterpolatePropertyName(propertyName: string | undefined) {\n    return propertyName === \"interpolate\";\n  }\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/tests/transformerFactoryTests.ts",
    "content": "import { runCommonTests } from \"@ts-nameof/tests-common\";\nimport * as ts from \"typescript\";\nimport { transformerFactory } from \"../transformerFactory\";\n\nrunCommonTests(run);\n\nfunction run(text: string) {\n  const results: { fileName: string; fileText: string }[] = [];\n  const compilerOptions: ts.CompilerOptions = {\n    strictNullChecks: true,\n    target: ts.ScriptTarget.ES2017,\n  };\n  const transformers: ts.CustomTransformers = {\n    before: [transformerFactory],\n    after: [],\n  };\n  const testFileName = \"/file.ts\";\n  const host: ts.CompilerHost = {\n    fileExists: (fileName: string) => fileName === testFileName,\n    readFile: (fileName: string) => fileName === testFileName ? text : undefined,\n    getSourceFile: (fileName, languageVersion) => {\n      if (fileName !== testFileName) {\n        return undefined;\n      }\n      return ts.createSourceFile(fileName, text, languageVersion, false, ts.ScriptKind.TS);\n    },\n    getDefaultLibFileName: options => ts.getDefaultLibFileName(options),\n    writeFile: () => {\n      throw new Error(\"Not implemented\");\n    },\n    getCurrentDirectory: () => \"/\",\n    getDirectories: () => [],\n    getCanonicalFileName: fileName => fileName,\n    useCaseSensitiveFileNames: () => true,\n    getNewLine: () => \"\\n\",\n  };\n  const program = ts.createProgram([\"/file.ts\"], compilerOptions, host);\n  program.emit(undefined, (fileName, fileText) => results.push({ fileName, fileText }), undefined, false, transformers);\n  return results[0].fileText;\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/transform.ts",
    "content": "import { throwError } from \"@ts-nameof/common\";\nimport * as common from \"@ts-nameof/transforms-common\";\nimport * as ts from \"typescript\";\nimport { VisitSourceFileContext } from \"./VisitSourceFileContext\";\n\n/**\n * Resulting node type of a nameof transform.\n */\nexport type TransformResult = ts.StringLiteral | ts.ArrayLiteralExpression | ts.NoSubstitutionTemplateLiteral | ts.TemplateExpression;\n\n/**\n * Transforms a common node to a TypeScript compiler node.\n * @param node Common node to be transformed.\n */\nexport function transform(node: common.Node, context: VisitSourceFileContext | undefined): TransformResult {\n  switch (node.kind) {\n    case \"StringLiteral\":\n      return ts.createLiteral(node.value);\n    case \"ArrayLiteral\":\n      return ts.createArrayLiteral(node.elements.map(element => transform(element, context)));\n    case \"TemplateExpression\":\n      if (node.parts.length === 1 && typeof node.parts[0] === \"string\") {\n        return ts.createNoSubstitutionTemplateLiteral(node.parts[0] as string);\n      }\n      return createTemplateExpression(node, context);\n    default:\n      return throwError(`Unsupported node kind: ${node.kind}`);\n  }\n}\n\nfunction createTemplateExpression(node: common.TemplateExpressionNode, context: VisitSourceFileContext | undefined) {\n  const firstPart = typeof node.parts[0] === \"string\" ? node.parts[0] as string : undefined;\n  const parts = firstPart != null ? node.parts.slice(1) : [...node.parts];\n\n  return ts.createTemplateExpression(ts.createTemplateHead(firstPart || \"\"), getParts());\n\n  function getParts() {\n    const templateSpans: ts.TemplateSpan[] = [];\n    for (let i = 0; i < parts.length; i += 2) {\n      const isLast = i + 2 === parts.length;\n      const interpolatedNode = parts[i];\n      if (typeof interpolatedNode === \"string\") {\n        return throwError(\"Unexpected scenario where an interpolated node was expected, but a string was found.\");\n      }\n      const text = parts[i + 1];\n      if (typeof text !== \"string\") {\n        return throwError(\"Unexpected scenario where a string was expected, but an interpolated node was found.\");\n      }\n\n      const tsExpression = interpolatedNode.expression as ts.Expression;\n      const tsText = !isLast ? ts.createTemplateMiddle(text) : ts.createTemplateTail(text);\n\n      // mark this nameof.interpolate expression as being handled\n      if (context != null) {\n        context.interpolateExpressions.delete(tsExpression);\n      }\n\n      templateSpans.push(ts.createTemplateSpan(tsExpression, tsText));\n    }\n    return templateSpans;\n  }\n}\n"
  },
  {
    "path": "packages/transforms-ts/src/transformerFactory.ts",
    "content": "import { throwError, throwErrorForSourceFile } from \"@ts-nameof/common\";\nimport { transformCallExpression } from \"@ts-nameof/transforms-common\";\nimport * as ts from \"typescript\";\nimport { getNodeText } from \"./helpers\";\nimport { parse } from \"./parse\";\nimport { transform, TransformResult } from \"./transform\";\nimport { VisitSourceFileContext } from \"./VisitSourceFileContext\";\n\n/** Transformer factory for performing nameof transformations. */\nexport const transformerFactory: ts.TransformerFactory<ts.SourceFile> = context => {\n  return file => visitSourceFile(file, context) as ts.SourceFile;\n};\n\n/** Visits all the nodes of the source file. */\nexport function visitSourceFile(sourceFile: ts.SourceFile, context: ts.TransformationContext) {\n  const visitSourceFileContext: VisitSourceFileContext = {\n    interpolateExpressions: new Set(),\n  };\n  try {\n    const result = visitNodeAndChildren(sourceFile);\n\n    throwIfContextHasInterpolateExpressions(visitSourceFileContext, sourceFile);\n\n    return result;\n  } catch (err: any) {\n    return throwErrorForSourceFile(err.message, sourceFile.fileName);\n  }\n\n  function visitNodeAndChildren(node: ts.Node): ts.Node {\n    if (node == null) {\n      return node;\n    }\n\n    // visit the children in post order\n    node = ts.visitEachChild(node, childNode => visitNodeAndChildren(childNode), context);\n    return visitNode(node, sourceFile, visitSourceFileContext);\n  }\n}\n\n/**\n * Throws if the context contains any remaining interpolate expressions.\n * @param context - Context to check.\n * @param sourceFile - Source file being transformed.\n */\nexport function throwIfContextHasInterpolateExpressions(context: VisitSourceFileContext, sourceFile: ts.SourceFile) {\n  if (context.interpolateExpressions.size > 0) {\n    const firstResult = Array.from(context.interpolateExpressions.values())[0];\n    return throwError(\n      `Found a nameof.interpolate that did not exist within a `\n        + `nameof.full call expression: nameof.interpolate(${getNodeText(firstResult, sourceFile)})`,\n    );\n  }\n}\n\n/** Visit a node and do a nameof transformation on it if necessary. */\nexport function visitNode(visitingNode: ts.Node, sourceFile: ts.SourceFile): TransformResult;\n/** @internal */\nexport function visitNode(visitingNode: ts.Node, sourceFile: ts.SourceFile, context: VisitSourceFileContext | undefined): TransformResult;\nexport function visitNode(visitingNode: ts.Node, sourceFile: ts.SourceFile, context?: VisitSourceFileContext) {\n  const parseResult = parse(visitingNode, sourceFile, context);\n  if (parseResult == null) {\n    return visitingNode;\n  }\n  return transform(transformCallExpression(parseResult), context);\n}\n"
  },
  {
    "path": "packages/transforms-ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src/**/*.ts\"],\n  \"references\": [\n    { \"path\": \"../common\" },\n    { \"path\": \"../transforms-common\" },\n    { \"path\": \"../tests-common\" }\n  ]\n}\n"
  },
  {
    "path": "packages/ts-nameof/.mocharc.yml",
    "content": "require: ts-node/register\nrecursive: true\nreporter: progress\nwatch-extensions: ts\ntimeout: 10000\nspec: src/tests/**/*.ts\n"
  },
  {
    "path": "packages/ts-nameof/.npmignore",
    "content": "/node_modules\r\n/.vscode\r\n/.vs\r\n/.git\r\n/obj\r\n/temp\r\n/bin\r\n/src\r\n/dist/tests\r\n/setup\r\n/scripts\r\n/lib\r\n*.js.map\r\n*.v12.suo\r\n*.csproj\r\n*.csproj.user\r\n*.sln\r\n*.log\r\n.travis.yml\r\n.gitignore\r\nCHANGELOG.md\r\n.mocharc.yml\r\ntsconfig.json\r\ntsconfig.scripts.json\r\ntsconfig.tsbuildinfo\r\n"
  },
  {
    "path": "packages/ts-nameof/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 David Sherret\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "packages/ts-nameof/README.md",
    "content": "﻿# ts-nameof\n\n[![npm version](https://badge.fury.io/js/ts-nameof.svg)](https://badge.fury.io/js/ts-nameof)\n[![Build Status](https://travis-ci.org/dsherret/ts-nameof.svg)](https://travis-ci.org/dsherret/ts-nameof)\n[![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges)\n\n[`nameof`](https://msdn.microsoft.com/en-us/library/dn986596.aspx) in TypeScript.\n\n```\nnpm install ts-nameof @types/ts-nameof --save-dev\n```\n\n## Setup\n\n### 1. Build Setup\n\nFollow any of these instructions:\n\n- [Webpack](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/webpack.md)\n- [Gulp](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/gulp.md)\n- [FuseBox](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/fusebox.md)\n- [tsc](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/tsc.md)\n- [Jest](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/jest.md)\n- [Custom](https://github.com/dsherret/ts-nameof/blob/master/packages/ts-nameof/setup/custom.md)\n- Others - Open an [issue](https://github.com/dsherret/ts-nameof/issues).\n\nThese instructions need updating to use the transformation API, but will still work in the meantime:\n\n- Nuxt - Use [https://github.com/Kukks/nuxt-ts-nameof](https://github.com/Kukks/nuxt-ts-nameof#readme)\n\n### 2. Declaring global `nameof` function\n\nInstall `@types/ts-nameof`:\n\n```\nnpm install @types/ts-nameof --save-dev\n```\n\n## Transforms\n\n[Read here](https://github.com/dsherret/ts-nameof/blob/master/README.md)\n\n## Other\n\n- [Contributing](https://github.com/dsherret/ts-nameof/blob/master/CONTRIBUTING.md)\n- [Development](https://github.com/dsherret/ts-nameof/blob/master/DEVELOPMENT.md)\n"
  },
  {
    "path": "packages/ts-nameof/lib/declarationFileTests.ts",
    "content": "/// <reference path=\"../ts-nameof.d.ts\" />\n/* istanbul ignore next */\nimport tsNameOf = require(\"ts-nameof\");\nimport { assert, IsExact } from \"conditional-type-checks\";\nimport * as tsNameOfEs6 from \"ts-nameof\";\n\n/* istanbul ignore next */\nfunction testFunc() {\n  tsNameOf.replaceInFiles([\"test\"]);\n  tsNameOf.replaceInFiles([\"test\"]).then(() => {});\n\n  // replaceInText\n  const replaceInTextResult = tsNameOf.replaceInText(\"fileName.ts\", \"const t = 5;\");\n  console.log(replaceInTextResult);\n  assert<IsExact<typeof replaceInTextResult.fileText, string | undefined>>(true);\n  assert<IsExact<typeof replaceInTextResult.replaced, boolean>>(true);\n\n  // es6 test\n  const es6Result = tsNameOfEs6.replaceInText(\"file.ts\", \"\");\n  console.log(es6Result.replaced);\n}\n"
  },
  {
    "path": "packages/ts-nameof/package.json",
    "content": "{\n  \"name\": \"ts-nameof\",\n  \"version\": \"5.0.0\",\n  \"description\": \"nameof in TypeScript\",\n  \"main\": \"dist/main.js\",\n  \"typings\": \"ts-nameof.d.ts\",\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b && npm run build:declarations\",\n    \"build-test\": \"tsc --build && npm run --silent copy-test-files\",\n    \"test\": \"npm run build-test && mocha\",\n    \"test:debug\": \"npm run build-test && mocha --inspect-brk\",\n    \"copy-test-files\": \"rimraf temp && copyfiles -u 2 \\\"./src/tests/testFiles/**/*{.js,.txt}\\\" \\\"./temp\\\"\",\n    \"build:declarations\": \"ts-node --project scripts/tsconfig.json scripts/generation/main create-declaration-file && npm run --silent verify-declaration-file\",\n    \"verify-declaration-file\": \"ts-node --project scripts/tsconfig.json scripts/verification/main verify-declaration-file\",\n    \"dopublish\": \"npm run test && npm run build && npm run verify-declaration-file && echo \\\"run: npm publish --otp\\\"\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/dsherret/ts-nameof.git\",\n    \"directory\": \"packages/ts-nameof\"\n  },\n  \"keywords\": [\n    \"nameof\",\n    \"typescript\",\n    \"transformer\",\n    \"custom-transformer\"\n  ],\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/dsherret/ts-nameof/issues\"\n  },\n  \"homepage\": \"https://github.com/dsherret/ts-nameof#readme\",\n  \"peerDependencies\": {\n    \"typescript\": \"*\"\n  },\n  \"dependencies\": {\n    \"@ts-nameof/common\": \"^4.2.1\",\n    \"@ts-nameof/transforms-ts\": \"^4.2.1\",\n    \"glob\": \"^7.2.0\"\n  },\n  \"devDependencies\": {\n    \"@ts-nameof/scripts-common\": \"^4.0.2\",\n    \"@ts-nameof/tests-common\": \"^4.2.0\",\n    \"@types/glob\": \"^7.2.0\",\n    \"@types/mocha\": \"^9.0.0\",\n    \"@types/node\": \"^17.0.0\",\n    \"conditional-type-checks\": \"^1.0.5\",\n    \"copyfiles\": \"^2.4.1\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-morph\": \"^13.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.4.3\"\n  }\n}\n"
  },
  {
    "path": "packages/ts-nameof/scripts/common/createProject.ts",
    "content": "import { Project } from \"ts-morph\";\n\nexport function getProject() {\n    return new Project({ tsConfigFilePath: \"tsconfig.json\", compilerOptions: { declaration: true } });\n}\n"
  },
  {
    "path": "packages/ts-nameof/scripts/common/index.ts",
    "content": "export * from \"./createProject\";\n"
  },
  {
    "path": "packages/ts-nameof/scripts/generation/createDeclarationFile.ts",
    "content": "import { ModuleDeclarationKind, Project } from \"ts-morph\";\n\nexport function createDeclarationFile(project: Project) {\n  const mainFile = project.getSourceFileOrThrow(\"src/main.ts\");\n  const outputFiles = mainFile.getEmitOutput({ emitOnlyDtsFiles: true }).getOutputFiles();\n  if (outputFiles.length !== 1) {\n    throw new Error(`Expected 1 file when emitting, but had ${outputFiles.length}`);\n  }\n\n  const declarationFile = project.createSourceFile(\"ts-nameof.d.ts\", outputFiles[0].getText(), { overwrite: true });\n\n  removePreceedingCommentReference();\n  commentExternalTypes();\n  removeTypeScriptImport();\n  wrapInGlobalModule();\n  addGlobalDeclarations();\n\n  function removePreceedingCommentReference() {\n    const firstChild = declarationFile.getFirstChildOrThrow();\n    declarationFile.removeText(0, firstChild.getStart());\n  }\n\n  function commentExternalTypes() {\n    // these types are made to be any so that this library will work when included in\n    // web projects and NodeJS does not exist. See issue #22.\n    const typesToComment = [\n      \"ts.TransformerFactory<ts.SourceFile>\",\n      \"NodeJS.ErrnoException\",\n    ];\n    declarationFile.forEachDescendant(descendant => {\n      if (typesToComment.indexOf(descendant.getText()) >= 0) {\n        descendant.replaceWithText(`any /* ${descendant.getText()} */`);\n      }\n    });\n  }\n\n  function removeTypeScriptImport() {\n    declarationFile.getImportDeclarationOrThrow(\"typescript\").remove();\n  }\n\n  function wrapInGlobalModule() {\n    const fileText = declarationFile.getText();\n    declarationFile.removeText();\n    const apiModule = declarationFile.addModule({\n      hasDeclareKeyword: true,\n      declarationKind: ModuleDeclarationKind.Module,\n      name: `\"ts-nameof\"`,\n    });\n    apiModule.setBodyText(fileText);\n    apiModule.getVariableStatementOrThrow(s => s.getDeclarations().some(d => d.getName() === \"api\"))\n      .setHasDeclareKeyword(false);\n  }\n\n  function addGlobalDeclarations() {\n    const globalFile = project.addSourceFileAtPath(\"../../lib/global.d.ts\");\n    declarationFile.addStatements(writer => {\n      writer.newLine();\n      writer.write(globalFile.getText().replace(/\\r?\\n$/, \"\"));\n    });\n  }\n}\n"
  },
  {
    "path": "packages/ts-nameof/scripts/generation/main.ts",
    "content": "import { ArgsChecker } from \"@ts-nameof/scripts-common\";\nimport { getProject } from \"../common\";\nimport { createDeclarationFile } from \"./createDeclarationFile\";\n\nconst argsChecker = new ArgsChecker();\nconst project = getProject();\n\nif (argsChecker.checkHasArg(\"create-declaration-file\")) {\n  console.log(\"Creating declaration file...\");\n  createDeclarationFile(project);\n}\n\nargsChecker.verifyArgsUsed();\nproject.save();\n"
  },
  {
    "path": "packages/ts-nameof/scripts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"noEmit\": true\n  },\n  \"extends\": \"../../../tsconfig.common.json\",\n  \"exclude\": [\n    \"./lib\",\n    \"./src\"\n  ]\n}\n"
  },
  {
    "path": "packages/ts-nameof/scripts/verification/main.ts",
    "content": "import { ArgsChecker } from \"@ts-nameof/scripts-common\";\nimport { verifyDeclarationFile } from \"./verifyDeclarationFile\";\n\nconst argsChecker = new ArgsChecker();\n\nif (argsChecker.checkHasArg(\"verify-declaration-file\")) {\n  console.log(\"Verifying declaration file...\");\n  verifyDeclarationFile();\n}\n\nargsChecker.verifyArgsUsed();\n"
  },
  {
    "path": "packages/ts-nameof/scripts/verification/verifyDeclarationFile.ts",
    "content": "import { Project } from \"ts-morph\";\n\nexport function verifyDeclarationFile() {\n  const project = new Project();\n  const declarationFile = project.addSourceFileAtPath(\"ts-nameof.d.ts\");\n  const declarationFileTests = project.addSourceFileAtPath(\"lib/declarationFileTests.ts\");\n  const diagnostics = [...declarationFile.getPreEmitDiagnostics(), ...declarationFileTests.getPreEmitDiagnostics()];\n\n  if (diagnostics.length > 0) {\n    console.error(project.formatDiagnosticsWithColorAndContext(diagnostics));\n  }\n}\n"
  },
  {
    "path": "packages/ts-nameof/setup/custom.md",
    "content": "﻿# Using ts-nameof with a Custom Setup\n\n## Transformation API\n\nThe export from `ts-nameof` is a `ts.TransformerFactory<ts.SourceFile>` so that can be used anywhere custom transformers are accepted. For example, see the [webpack instructions](webpack.md).\n\n```ts\nconst tsNameof = require(\"ts-nameof\");\n\n// tsNameof is a ts.TransformerFactory<ts.SourceFile>\n```\n\nIf you find this works for the library you're using to do a build then please consider submitting a PR with setup instructions for that library.\n\n## Working with text\n\nNote that these solution require reparsing the source file text and that might make the build slow. The other solutions mostly all use the\ntransformation api which will be much faster.\n\n### Replacing in Files\n\nYou can use `replaceInFiles` to replace in .ts files:\n\n```javascript\nvar replaceInFiles = require(\"ts-nameof\").replaceInFiles;\nreplaceInFiles([\"./dist/**/*.ts\"]);\n```\n\n1. Copy your .ts files to a build folder. This is necessary so you don't overwrite your original source files.\n2. Run `replaceInFiles` on these files.\n3. Compile the final typescript files.\n\n### Replacing in Text\n\nYou can also use the `replaceInText` function to replace occurrences of `nameof` in any string:\n\n```javascript\nvar replaceInText = require(\"ts-nameof\").replaceInText;\nvar replacedText = replaceInText(\"filename.ts\", \"nameof(test);\");\n```\n"
  },
  {
    "path": "packages/ts-nameof/setup/fusebox.md",
    "content": "# Using ts-nameof with FuseBox\n\nTo use ts-nameof with [FuseBox](https://github.com/fuse-box/fuse-box), specify it as a custom transformer:\n\n```javascript\nconst tsNameof = require(\"ts-nameof\");\n\nFuseBox.init({\n  transformers: {\n    before: [tsNameof],\n  },\n});\n```\n"
  },
  {
    "path": "packages/ts-nameof/setup/gulp.md",
    "content": "﻿# Using ts-nameof with Gulp\n\nSpecify it as a custom transformer with [gulp-typescript](https://github.com/ivogabe/gulp-typescript):\n\n```javascript\nconst gulp = require(\"gulp\");\nconst ts = require(\"gulp-typescript\");\nconst tsNameof = require(\"ts-nameof\");\n\ngulp.task(\"typescript\", function() {\n  gulp.src(\"src/**/*.ts\")\n    .pipe(ts({\n      getCustomTransformers: () => ({ before: [tsNameof] }),\n    }))\n    .pipe(gulp.dest(\"dist\"));\n});\n```\n"
  },
  {
    "path": "packages/ts-nameof/setup/jest.md",
    "content": "﻿# Using ts-nameof with Jest\n\n1. Setup jest with [ts-jest](https://github.com/kulshekhar/ts-jest)\n\n2. `npm install --save-dev ts-nameof @types/ts-nameof`\n\n3. In _package.json_ specify...\n\n```jsonc\n{\n  // ...\n  \"jest\": {\n    \"globals\": {\n      \"ts-jest\": {\n        \"astTransformers\": [\"ts-nameof\"]\n      }\n    }\n  }\n}\n```\n\n...or in _jest.config.js_...\n\n```ts\nmodule.exports = {\n  // ...\n  globals: {\n    \"ts-jest\": {\n      \"astTransformers\": [\"ts-nameof\"],\n    },\n  },\n};\n```\n"
  },
  {
    "path": "packages/ts-nameof/setup/tsc.md",
    "content": "# Using ts-nameof with tsc\n\nTransformation plugins are currently not supported by `tsc` alone. Please go and upvote [this issue](https://github.com/Microsoft/TypeScript/issues/14419) on TypeScript's issue tracker.\n\nIn the meantime, this is possible using [ttypescript](https://github.com/cevek/ttypescript) thanks to [@cevek](https://github.com/cevek)!\n\n## Setup\n\n1. Install `ttypescript` and `ts-nameof`:\n\n   ```bash\n   npm install --save-dev ttypescript ts-nameof\n   // or\n   yarn add --dev ttypescript ts-nameof\n   ```\n\n2. Add `ts-nameof` to `tsconfig.json` as a custom transformer:\n\n   ```json\n   {\n     \"compilerOptions\": {\n       \"plugins\": [{ \"transform\": \"ts-nameof\", \"type\": \"raw\" }]\n     }\n   }\n   ```\n\n3. Compile with `ttsc` instead of `tsc`:\n\n   ```bash\n   npx ttsc\n   ```\n\n### Swapping out TypeScript with TTypeScript\n\nRead the instructions at [`ttypescript`'s GitHub page](https://github.com/cevek/ttypescript) for how to use with tools like `ts-node` and visual studio code.\n\nGenerally, most build tools have a way to swap out which version of the compiler you use (ex. using environment variables or command line arguments) so this should work across a lot of build tools.\n"
  },
  {
    "path": "packages/ts-nameof/setup/webpack.md",
    "content": "# Using ts-nameof with Webpack\n\n## ts-loader / awesome-typescript-loader\n\nIf using [ts-loader](https://github.com/TypeStrong/ts-loader) or [awesome-typescript-loader](https://github.com/s-panferov/awesome-typescript-loader), specify ts-nameof as a custom transformation like so in _webpack.config.js_:\n\n```ts\nconst tsNameof = require(\"ts-nameof\");\n\nmodule.exports = {\n  // ...etc...\n  module: {\n    rules: [{\n      test: /\\.tsx?$/,\n      use: [{\n        loader: \"ts-loader\", // or awesome-typescript-loader\n        options: {\n          getCustomTransformers: () => ({ before: [tsNameof] }),\n        },\n      }],\n    }],\n  },\n};\n```\n"
  },
  {
    "path": "packages/ts-nameof/src/main.ts",
    "content": "import { transformerFactory } from \"@ts-nameof/transforms-ts\";\nimport * as ts from \"typescript\";\nimport { replaceInFiles, replaceInText } from \"./text\";\n\ninterface Api {\n  (): ts.TransformerFactory<ts.SourceFile>;\n  replaceInFiles(fileNames: ReadonlyArray<string>): Promise<void[]>;\n  replaceInText(fileName: string, fileText: string): { fileText?: string; replaced: boolean };\n}\n\nconst api: Api = transformerFactory as any as Api;\napi.replaceInFiles = replaceInFiles;\napi.replaceInText = replaceInText;\n// this is for ts-jest support... not ideal\n(api as any).factory = () => transformerFactory;\n\nexport = api;\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/GeneralTestFile.txt",
    "content": "console.log(nameof(alert));\nconsole.log(nameof(window.alert));\nconsole.log(nameof.full(window.alert));\nconsole.log(nameof.full(window   .alert));\nconsole.log(nameof.full(window.alert.length, -3));\nconsole.log(nameof.full(window.alert.length, -2));\nconsole.log(nameof.full(window.alert.length, -1));\nconsole.log(nameof.full(window.alert.length, 0));\nconsole.log(nameof.full(window.alert.length, 1));\nconsole.log(nameof.full(window.alert.length, 2));\nconsole.log( nameof( window ) );\nconsole.log(  nameof (window) );\nconsole.log(nameof(nameof(nameof(clearTimeout))));\nconsole.log(nameof<Array<string>>());\nconsole.log(nameof.full<Array<string>>());\nconsole.log(nameof<MyInterface>(i => i.prop));\nconsole.log(nameof<MyInterface>(function(i) { return i.prop; }));\nconsole.log(nameof<MyInterface>(function(i) { return i.prop }));\nconsole.log(nameof.full<MyNamespace.MyInnerInterface>());\nconsole.log(nameof.full<MyNamespace.MyInnerInterface>(-2));\nconsole.log(nameof.full<MyNamespace.MyInnerInterface>(-1));\nconsole.log(nameof.full<MyNamespace.MyInnerInterface>(0));\nconsole.log(nameof.full<MyNamespace.MyInnerInterface>(1));\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/StreamNoNameofTestFile.txt",
    "content": "console.log(\"\");\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/StreamTestFile.txt",
    "content": "nameof(window);\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/globFolder/MyGlobTestFile.txt",
    "content": "console.log(nameof(console));\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/issues/11-expected.txt",
    "content": "class Test {\n    private x: Test;\n    public y: Test;\n    public z: string;\n\n    constructor() {\n        \"x\";\n        \"y\";\n        \"this.x.y.z\";\n        \"x.y.z\";\n    }\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/issues/11-source.txt",
    "content": "class Test {\n    private x: Test;\n    public y: Test;\n    public z: string;\n\n    constructor() {\n        nameof(this.x);\n        nameof(this.x.y);\n        nameof.full(this.x.y.z);\n        nameof.full(this.x.y.z, 1);\n    }\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/issues/8-expected.txt",
    "content": "import CodeBlockWriter from \"code-block-writer\";\nimport {expect} from \"chai\";\nimport {FunctionDefinition, InterfaceMethodDefinition, ClassMethodDefinition} from \"./../../definitions\";\nimport {FunctionBodyWriter} from \"./../../writers\";\nimport {WriteFlags} from \"./../../WriteFlags\";\nimport * as mocks from \"./mocks\";\n\ndescribe(\"FunctionBodyWriter\", () => {\n    function createObjects() {\n        const writer = new CodeBlockWriter();\n        const defWriter = new FunctionBodyWriter(writer);\n        return {writer, defWriter};\n    }\n\n    describe(\"write\", () => {\n\n        it(`should not write out the function body if ${\"HideFunctionBodies\"} is set`, () => {\n            const def = new FunctionDefinition();\n            const {writer, defWriter} = createObjects();\n            defWriter.write(def, WriteFlags.HideFunctionBodies);\n            expect(writer.toString()).to.equal(\";\");\n        });\n\n        it(`should not write out the function body if it's an ${\"InterfaceMethodDefinition\"}`, () => {\n            const def = new InterfaceMethodDefinition();\n            const {writer, defWriter} = createObjects();\n            defWriter.write(def, WriteFlags.None);\n            expect(writer.toString()).to.equal(\";\");\n        });\n    });\n});\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/testFiles/issues/8-source.txt",
    "content": "import CodeBlockWriter from \"code-block-writer\";\nimport {expect} from \"chai\";\nimport {FunctionDefinition, InterfaceMethodDefinition, ClassMethodDefinition} from \"./../../definitions\";\nimport {FunctionBodyWriter} from \"./../../writers\";\nimport {WriteFlags} from \"./../../WriteFlags\";\nimport * as mocks from \"./mocks\";\n\ndescribe(nameof(FunctionBodyWriter), () => {\n    function createObjects() {\n        const writer = new CodeBlockWriter();\n        const defWriter = new FunctionBodyWriter(writer);\n        return {writer, defWriter};\n    }\n\n    describe(nameof<FunctionBodyWriter>(w => w.write), () => {\n\n        it(`should not write out the function body if ${nameof(WriteFlags.HideFunctionBodies)} is set`, () => {\n            const def = new FunctionDefinition();\n            const {writer, defWriter} = createObjects();\n            defWriter.write(def, WriteFlags.HideFunctionBodies);\n            expect(writer.toString()).to.equal(\";\");\n        });\n\n        it(`should not write out the function body if it's an ${nameof(InterfaceMethodDefinition)}`, () => {\n            const def = new InterfaceMethodDefinition();\n            const {writer, defWriter} = createObjects();\n            defWriter.write(def, WriteFlags.None);\n            expect(writer.toString()).to.equal(\";\");\n        });\n    });\n});\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/helpers/fileHelpers.ts",
    "content": "import * as fs from \"fs\";\n\nexport function readFile(path: string) {\n  return new Promise<string>((resolve, reject) => {\n    fs.readFile(path, { encoding: \"utf-8\" }, (err, data) => {\n      if (err) {\n        reject(err);\n        return;\n      }\n\n      resolve(data);\n    });\n  });\n}\n\nexport function writeFile(path: string, contents: string) {\n  return new Promise<void>((resolve, reject) => {\n    fs.writeFile(path, contents, err => {\n      if (err) {\n        reject(err);\n        return;\n      }\n\n      resolve();\n    });\n  });\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/helpers/getTestFilePath.ts",
    "content": "import * as path from \"path\";\n\nexport function getTestFilePath(...paths: string[]) {\n  return path.join(\"./temp/testFiles\", ...paths);\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/helpers/index.ts",
    "content": "export * from \"./fileHelpers\";\nexport * from \"./getTestFilePath\";\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/issuesTests.ts",
    "content": "import * as assert from \"assert\";\nimport { replaceInFiles } from \"../../text\";\nimport { getTestFilePath, readFile, writeFile } from \"./helpers\";\n\ndescribe(\"replaceInFiles()\", () => {\n  async function runTest(fileName: string, expectedFileName: string) {\n    fileName = getTestFilePath(fileName);\n    expectedFileName = getTestFilePath(expectedFileName);\n\n    const originalFileText = await readFile(expectedFileName);\n\n    try {\n      await replaceInFiles([fileName]);\n      const data = await readFile(fileName);\n      const expectedContents = await readFile(expectedFileName);\n      assert.equal(data.replace(/\\r?\\n/g, \"\\n\"), expectedContents.replace(/\\r?\\n/g, \"\\n\"));\n    } finally {\n      await writeFile(expectedFileName, originalFileText);\n    }\n  }\n\n  function runIssueTest(issueNumber: number) {\n    describe(`issue ${issueNumber}`, () => {\n      it(\"should replace\", async () => {\n        await runTest(`issues/${issueNumber}-source.txt`, `issues/${issueNumber}-expected.txt`);\n      });\n    });\n  }\n\n  runIssueTest(8);\n  runIssueTest(11);\n});\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/replaceInFilesTests.ts",
    "content": "import * as assert from \"assert\";\nimport { replaceInFiles } from \"../../text\";\nimport { getTestFilePath, readFile, writeFile } from \"./helpers\";\n\ndescribe(\"replaceInFiles()\", () => {\n  interface FileInfo {\n    filePath: string;\n    contents: string;\n  }\n\n  async function runTest(paths: string[], expectedFiles: FileInfo[]) {\n    paths = paths.map(p => getTestFilePath(p));\n    expectedFiles.forEach(f => f.filePath = getTestFilePath(f.filePath));\n\n    const initialFiles = await Promise.all(expectedFiles.map(f =>\n      readFile(f.filePath).then(data => ({\n        filePath: f.filePath,\n        contents: data,\n      } as FileInfo))\n    ));\n\n    try {\n      await replaceInFiles(paths);\n      const readFilePromises = expectedFiles.map(f => readFile(f.filePath).then(data => ({ data, expectedContents: f.contents })));\n\n      for (const promise of readFilePromises) {\n        const { data, expectedContents } = await promise;\n        assert.equal(data.replace(/\\r?\\n/g, \"\\n\"), expectedContents.replace(/\\r?\\n/g, \"\\n\"));\n      }\n    } finally {\n      await Promise.all(initialFiles.map(f => writeFile(f.filePath, f.contents)));\n    }\n  }\n\n  describe(\"glob support\", () => {\n    it(\"should replace in MyGlobTestFile.txt\", async () => {\n      await runTest([\"globFolder/**/*.txt\"], [{\n        filePath: \"globFolder/MyGlobTestFile.txt\",\n        contents: `console.log(\"console\");\\n`,\n      }]);\n    });\n  });\n\n  describe(\"general file\", () => {\n    it(\"should have the correct number of characters\", async () => {\n      // because an IDE might auto-format the code, this makes sure that hasn't happened\n      assert.equal((await readFile(getTestFilePath(\"GeneralTestFile.txt\"))).replace(/\\r?\\n/g, \"\\n\").length, 1121);\n    });\n\n    const expected = `console.log(\"alert\");\nconsole.log(\"alert\");\nconsole.log(\"window.alert\");\nconsole.log(\"window.alert\");\nconsole.log(\"window.alert.length\");\nconsole.log(\"alert.length\");\nconsole.log(\"length\");\nconsole.log(\"window.alert.length\");\nconsole.log(\"alert.length\");\nconsole.log(\"length\");\nconsole.log( \"window\" );\nconsole.log(  \"window\" );\nconsole.log(\"clearTimeout\");\nconsole.log(\"Array\");\nconsole.log(\"Array\");\nconsole.log(\"prop\");\nconsole.log(\"prop\");\nconsole.log(\"prop\");\nconsole.log(\"MyNamespace.MyInnerInterface\");\nconsole.log(\"MyNamespace.MyInnerInterface\");\nconsole.log(\"MyInnerInterface\");\nconsole.log(\"MyNamespace.MyInnerInterface\");\nconsole.log(\"MyInnerInterface\");\n`;\n\n    describe(\"file modifying test\", () => {\n      it(\"should modify the file\", async () => {\n        await runTest([\"GeneralTestFile.txt\"], [{\n          filePath: \"GeneralTestFile.txt\",\n          contents: expected,\n        }]);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/ts-nameof/src/tests/text/replaceInTextTests.ts",
    "content": "import { runCommonTests } from \"@ts-nameof/tests-common\";\nimport * as assert from \"assert\";\nimport { replaceInText } from \"../../text\";\n\ndescribe(\"replaceInText\", () => {\n  it(\"should unofficially maintain backwards compatibility when providing one argument\", () => {\n    assert.equal((replaceInText as any)(\"nameof(window);\").fileText, `\"window\";`);\n  });\n\n  it(\"should not replace when no nameof\", () => {\n    const result = replaceInText(\"file.ts\", \"some random text with no nameof in it\");\n    assert.equal(result.replaced, false);\n    assert.equal(result.fileText, undefined);\n  });\n\n  it(\"should replace when there was a nameof\", () => {\n    const result = replaceInText(\"file.ts\", \"describe(nameof(myTest), () => {});\");\n    assert.equal(result.replaced, true);\n    assert.equal(result.fileText, `describe(\"myTest\", () => {});`);\n  });\n\n  it(\"should replace when there was a nameof in tsx file\", () => {\n    const result = replaceInText(\"file.tsx\", \"const t = <div t={nameof(t)} />;\");\n    assert.equal(result.replaced, true);\n    assert.equal(result.fileText, `const t = <div t={\"t\"} />;`);\n  });\n\n  runCommonTests(text => {\n    return replaceInText(\"file.ts\", text).fileText || text;\n  });\n});\n"
  },
  {
    "path": "packages/ts-nameof/src/text/getFileNamesFromGlobs.ts",
    "content": "import glob from \"glob\";\n\nexport function getFileNamesFromGlobs(globs: ReadonlyArray<string>) {\n  const promises = globs.map(g => getFileNamesFromGlob(g));\n\n  return Promise.all(promises).then(values => values.reduce((a, b) => a.concat(b), []));\n}\n\nfunction getFileNamesFromGlob(globFileName: string) {\n  return new Promise<string[]>((resolve, reject) => {\n    glob(globFileName, (err, files) => {\n      /* istanbul ignore if */\n      if (err) {\n        reject(err);\n        return;\n      }\n\n      resolve(files);\n    });\n  });\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/text/index.ts",
    "content": "export * from \"./getFileNamesFromGlobs\";\nexport * from \"./replaceInFiles\";\nexport * from \"./replaceInText\";\n"
  },
  {
    "path": "packages/ts-nameof/src/text/replaceInFiles.ts",
    "content": "import * as fs from \"fs\";\nimport { getFileNamesFromGlobs } from \"./getFileNamesFromGlobs\";\nimport { replaceInText } from \"./replaceInText\";\n\nexport function replaceInFiles(fileNames: ReadonlyArray<string>): Promise<void[]> {\n  return getFileNamesFromGlobs(fileNames).then(globbedFileNames => doReplaceInFiles(globbedFileNames));\n}\n\nfunction doReplaceInFiles(fileNames: ReadonlyArray<string>) {\n  const promises: Promise<void>[] = [];\n\n  fileNames.forEach(fileName => {\n    promises.push(\n      new Promise<void>((resolve, reject) => {\n        fs.readFile(fileName, { encoding: \"utf8\" }, (err, fileText) => {\n          /* istanbul ignore if */\n          if (err) {\n            reject(err);\n            return;\n          }\n\n          const result = replaceInText(fileName, fileText);\n\n          if (result.replaced) {\n            fs.writeFile(fileName, result.fileText!, writeErr => {\n              /* istanbul ignore if */\n              if (writeErr) {\n                reject(writeErr);\n                return;\n              }\n\n              resolve();\n            });\n          } else {\n            resolve();\n          }\n        });\n      }),\n    );\n  });\n\n  return Promise.all(promises);\n}\n"
  },
  {
    "path": "packages/ts-nameof/src/text/replaceInText.ts",
    "content": "import { throwIfContextHasInterpolateExpressions, visitNode, VisitSourceFileContext } from \"@ts-nameof/transforms-ts\";\nimport * as ts from \"typescript\";\n\nconst printer = ts.createPrinter();\n\nexport function replaceInText(fileName: string, fileText: string): { fileText?: string; replaced: boolean } {\n  // unofficial pre-2.0 backwards compatibility for this method\n  if (arguments.length === 1) {\n    fileText = fileName;\n    fileName = \"/file.tsx\"; // assume tsx\n  }\n\n  const visitSourceFileContext: VisitSourceFileContext = {\n    interpolateExpressions: new Set<ts.Node>(),\n  };\n  const sourceFile = ts.createSourceFile(fileName, fileText, ts.ScriptTarget.Latest, false);\n  const transformations: { start: number; end: number; text: string }[] = [];\n  const transformerFactory: ts.TransformerFactory<ts.SourceFile> = context => {\n    // this will always use the source file above\n    return _ => visitSourceFile(context);\n  };\n  ts.transform(sourceFile, [transformerFactory]);\n\n  throwIfContextHasInterpolateExpressions(visitSourceFileContext, sourceFile);\n\n  if (transformations.length === 0) {\n    return { replaced: false };\n  }\n\n  return { fileText: getTransformedText(), replaced: true };\n\n  function getTransformedText() {\n    let finalText = \"\";\n    let lastPos = 0;\n\n    for (const transform of transformations) {\n      finalText += fileText.substring(lastPos, transform.start);\n      finalText += transform.text;\n      lastPos = transform.end;\n    }\n\n    finalText += fileText.substring(lastPos);\n    return finalText;\n  }\n\n  function visitSourceFile(context: ts.TransformationContext) {\n    return visitNodeAndChildren(sourceFile) as ts.SourceFile;\n\n    function visitNodeAndChildren(node: ts.Node): ts.Node {\n      if (node == null) {\n        return node;\n      }\n\n      node = ts.visitEachChild(node, childNode => visitNodeAndChildren(childNode), context);\n\n      const resultNode = visitNode(node, sourceFile, visitSourceFileContext);\n      const wasTransformed = resultNode !== node;\n\n      if (wasTransformed) {\n        storeTransformation();\n      }\n\n      return resultNode;\n\n      function storeTransformation() {\n        const nodeStart = node.getStart(sourceFile);\n        const lastTransformation = transformations[transformations.length - 1];\n\n        // remove the last transformation if it's nested within this transformation\n        if (lastTransformation != null && lastTransformation.start > nodeStart) {\n          transformations.pop();\n        }\n\n        transformations.push({\n          start: nodeStart,\n          end: node.end,\n          text: printer.printNode(ts.EmitHint.Unspecified, resultNode, sourceFile),\n        });\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ts-nameof/ts-nameof.d.ts",
    "content": "declare module \"ts-nameof\" {\n  interface Api {\n    (): any /* ts.TransformerFactory<ts.SourceFile> */;\n    replaceInFiles(fileNames: ReadonlyArray<string>): Promise<void[]>;\n    replaceInText(fileName: string, fileText: string): {\n      fileText?: string;\n      replaced: boolean;\n    };\n  }\n  const api: Api;\n  export = api;\n}\n\ndeclare function nameof<T>(func?: (obj: T) => any): string;\n\n/**\n * Gets a string representation of the last identifier of the given expression.\n *\n * @example nameof(console) -> \"console\"\n * @example nameof(console.log) -> \"log\"\n * @example nameof(console[\"warn\"]) -> \"warn\"\n *\n * @param obj An expression for which the last identifier will be parsed.\n */\ndeclare function nameof(obj: any): string;\n\ndeclare namespace nameof {\n  /**\n   * Gets the string representation of the entire type parameter expression.\n   *\n   * @example nameof.full<MyNamespace.MyInnerInterface>() -> \"MyNamespace.MyInnerInterface\"\n   * @example nameof.full<MyNamespace.MyInnerInterface>(1) -> \"MyInnerInterface\"\n   * @example nameof.full<Array<MyInterface>>() -> \"Array\"\n   * @example nameof.full<MyNamespace.AnotherNamespace.MyInnerInterface>>(-1) -> \"MyInnerInterface\"\n   *\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full<T>(periodIndex?: number): string;\n\n  /**\n   * Gets the string representation of the entire resultant expression.\n   *\n   * @example nameof.full<MyInterface>(o => o.prop.prop2) -> \"prop.prop2\"\n   * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, 1) -> \"prop2.prop3\"\n   * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, -1) -> `\"prop3\"\n   *\n   * @param func A function for which the result will be parsed, excluding the parameter's identifier.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full<T>(func: (obj: T) => any, periodIndex?: number): string;\n\n  /**\n   * Gets the string representation of the entire given expression.\n   *\n   * @example nameof.full(console.log) -> \"console.log\"\n   * @example nameof.full(window.alert.length, -1) -> \"length\"\n   * @example nameof.full(window.alert.length, 2) -> \"length\"\n   *\n   * @param obj The expression which will be parsed.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function full(obj: any, periodIndex?: number): string;\n\n  /**\n   * Gets an array containing the string representation of the final identifier of each expression in the array returned by the provided function.\n   *\n   * @example nameof.toArray<MyType>(o => [o.firstProp, o.otherProp.secondProp, o.other]) -> [\"firstProp\", \"secondProp\", \"other\"]\n   * @example nameof.toArray<MyType>(o => [o.prop, nameof.full(o.myProp.otherProp, 1)]) -> [\"prop\", \"myProp.otherProp\"]\n   *\n   * @param func A function returning an array of expressions to be parsed, excluding the parameter's identifier.\n   */\n  function toArray<T>(func: (obj: T) => any[]): string[];\n\n  /**\n   * Gets an array containing the string representation of each expression in the arguments.\n   *\n   * @example nameof.toArray(myObject, otherObject) -> [\"myObject\", \"otherObject\"]\n   * @example nameof.toArray(obj.firstProp, obj.secondProp, otherObject, nameof.full(obj.other)) -> [\"firstProp\", \"secondProp\", \"otherObject\", \"obj.other\"]\n   *\n   * @param args An array of expressions to be parsed.\n   */\n  function toArray(...args: any[]): string[];\n\n  /**\n   * Embeds an expression into the string representation of the result of nameof.full.\n   *\n   * @example nameof.full(myObj.prop[nameof.interpolate(i)]) -> `myObj.prop[${i}]`\n   *\n   * @param value The value to interpolate.\n   */\n  function interpolate<T>(value: T): T;\n\n  /**\n   * Gets an array of strings where each element is a subsequent part of the expression provided.\n   *\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3) -> [\"prop\", \"prop2\", \"prop3\"]\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, 1) -> [\"prop2\", \"prop3\"]\n   * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, -1) -> [\"prop\", \"prop2\"]\n   *\n   * @param func A function for which the resultant parts will be parsed, excluding the parameter's identifier.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function split<T>(func: (obj: T) => any, periodIndex?: number): string[];\n\n  /**\n   * Gets an array of strings where each element is a subsequent part of the expression provided.\n   *\n   * @example nameof.split(myObj.prop.prop2.prop3) -> [\"myObj\", \"prop\", \"prop2\", \"prop3\"]\n   * @example nameof.split(myObj.prop.prop2.prop3, -3);`, `[\"prop\", \"prop2\", \"prop3\"];\n   * @example nameof.split(myObj.prop.prop2.prop3, 2);`, `[\"prop2\", \"prop3\"]\n   *\n   * @param obj An expression for which the parts will be parsed.\n   * @param periodIndex Specifies the index of the part of the expression to parse.\n   * When absent, the full expression will be parsed.\n   * A negative index can be used, indicating an offset from the end of the sequence.\n   */\n  function split(obj: any, periodIndex?: number): string[];\n}\n"
  },
  {
    "path": "packages/ts-nameof/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src\"],\n  \"references\": [\n    { \"path\": \"../transforms-ts\" },\n    { \"path\": \"../tests-common\" },\n    { \"path\": \"../scripts-common\" }\n  ]\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/.mocharc.yml",
    "content": "require: ts-node/register\nrecursive: true\nreporter: progress\nwatch-extensions: ts\ntimeout: 10000\nspec: src/tests/**/*.ts\n"
  },
  {
    "path": "packages/ts-nameof.macro/.npmignore",
    "content": "/node_modules\r\n/.vscode\r\n/.vs\r\n/.git\r\n/obj\r\n/temp\r\n/bin\r\n/src\r\n/dist/tests\r\n/setup\r\n/scripts\r\n/lib\r\n*.js.map\r\n*.v12.suo\r\n*.csproj\r\n*.csproj.user\r\n*.sln\r\n*.log\r\n.travis.yml\r\n.gitignore\r\nCHANGELOG.md\r\n.mocharc.yml\r\ntsconfig.json\r\ntsconfig.tsbuildinfo\r\n"
  },
  {
    "path": "packages/ts-nameof.macro/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 David Sherret\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "packages/ts-nameof.macro/README.md",
    "content": "﻿# ts-nameof.macro\n\n[![npm version](https://badge.fury.io/js/ts-nameof.macro.svg)](https://badge.fury.io/js/ts-nameof.macro)\n[![Build Status](https://travis-ci.org/dsherret/ts-nameof.svg)](https://travis-ci.org/dsherret/ts-nameof)\n[![Babel Macro](https://img.shields.io/badge/babel--macro-%F0%9F%8E%A3-f5da55.svg?style=flat-square)](https://github.com/kentcdodds/babel-plugin-macros)\n[![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges)\n\n[`nameof`](https://msdn.microsoft.com/en-us/library/dn986596.aspx) in TypeScript.\n\nThis is a [babel macro](https://github.com/kentcdodds/babel-plugin-macros) of [ts-nameof](https://github.com/dsherret/ts-nameof).\n\n## Setup\n\n1. Install dependencies:\n\n```\nnpm install --save-dev babel-plugin-macros ts-nameof.macro\n```\n\n2. Ensure `babel-plugin-macros` is properly setup ([Instructions](https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md)).\n\n3. Import and use the default export. For example:\n\n```ts\nimport nameof from \"ts-nameof.macro\";\n\nnameof(window.alert);\n```\n\nTransforms to:\n\n```ts\n\"alert\";\n```\n\n## Transforms\n\n[Read here](https://github.com/dsherret/ts-nameof/blob/master/README.md)\n\n## Other\n\n- [Contributing](https://github.com/dsherret/ts-nameof/blob/master/CONTRIBUTING.md)\n- [Development](https://github.com/dsherret/ts-nameof/blob/master/DEVELOPMENT.md)\n"
  },
  {
    "path": "packages/ts-nameof.macro/package.json",
    "content": "{\n  \"name\": \"ts-nameof.macro\",\n  \"version\": \"4.2.2\",\n  \"description\": \"Babel macro for nameof in TypeScript.\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"ts-nameof.macro.d.ts\",\n  \"scripts\": {\n    \"clean\": \"rimraf dist && tsc --b --clean\",\n    \"build\": \"tsc --b && npm run build:declarations\",\n    \"build:declarations\": \"ts-node --project scripts/tsconfig.json scripts/generation/main create-declaration-file\",\n    \"test\": \"tsc --build && mocha\",\n    \"test:debug\": \"npm run build && mocha --inspect-brk\",\n    \"dopublish\": \"npm run install && npm run build && echo \\\"Run: npm publish --otp\\\"\"\n  },\n  \"keywords\": [\n    \"nameof\",\n    \"typescript\",\n    \"transforms\",\n    \"babel\",\n    \"babel-plugin-macros\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/dsherret/ts-nameof.git\",\n    \"directory\": \"packages/ts-nameof.macro\"\n  },\n  \"author\": \"David Sherret\",\n  \"license\": \"MIT\",\n  \"peerDependencies\": {\n    \"babel-plugin-macros\": \"^3.1.0\"\n  },\n  \"dependencies\": {\n    \"@ts-nameof/transforms-babel\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.16.5\",\n    \"@babel/preset-typescript\": \"^7.16.5\",\n    \"@ts-nameof/scripts-common\": \"^4.0.2\",\n    \"@ts-nameof/tests-common\": \"^4.2.0\",\n    \"@types/babel__core\": \"^7.1.17\",\n    \"@types/babel__generator\": \"^7.6.3\",\n    \"@types/babel__template\": \"^7.4.1\",\n    \"@types/babel__traverse\": \"^7.14.2\",\n    \"@types/mocha\": \"^9.0.0\",\n    \"@types/node\": \"^17.0.0\",\n    \"babel-plugin-macros\": \"^3.1.0\",\n    \"mocha\": \"^9.1.3\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-morph\": \"^13.0.2\",\n    \"ts-node\": \"^10.4.0\",\n    \"typescript\": \"^4.5.4\"\n  }\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/scripts/common/createProject.ts",
    "content": "import { Project } from \"ts-morph\";\n\nexport function getProject() {\n    return new Project({ tsConfigFilePath: \"tsconfig.json\" });\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/scripts/common/index.ts",
    "content": "export * from \"./createProject\";\n"
  },
  {
    "path": "packages/ts-nameof.macro/scripts/generation/createDeclarationFile.ts",
    "content": "import { ModuleDeclarationKind, Node, Project } from \"ts-morph\";\n\nexport function createDeclarationFile(project: Project) {\n  const globalFile = project.addSourceFileAtPath(\"../../lib/global.d.ts\");\n  const declarationFile = project.createSourceFile(\"ts-nameof.macro.d.ts\", \"\", { overwrite: true });\n  const namespaceDec = declarationFile.addModule({\n    name: `\"ts-nameof.macro\"`,\n    declarationKind: ModuleDeclarationKind.Module,\n    hasDeclareKeyword: true,\n  });\n\n  namespaceDec.setBodyText(globalFile.getFullText());\n\n  for (const statement of namespaceDec.getStatements()) {\n    if (Node.isAmbientable(statement)) {\n      statement.setHasDeclareKeyword(false);\n    }\n  }\n\n  namespaceDec.addExportAssignment({\n    expression: \"nameof\",\n    isExportEquals: false,\n  });\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/scripts/generation/main.ts",
    "content": "import { ArgsChecker } from \"@ts-nameof/scripts-common\";\nimport { getProject } from \"../common\";\nimport { createDeclarationFile } from \"./createDeclarationFile\";\n\nconst argsChecker = new ArgsChecker();\nconst project = getProject();\n\nif (argsChecker.checkHasArg(\"create-declaration-file\")) {\n  console.log(\"Creating declaration file...\");\n  createDeclarationFile(project);\n}\n\nargsChecker.verifyArgsUsed();\nproject.save();\n"
  },
  {
    "path": "packages/ts-nameof.macro/scripts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"noEmit\": true\n  },\n  \"extends\": \"../../../tsconfig.common.json\",\n  \"exclude\": [\n    \"./lib\",\n    \"./src\"\n  ]\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/src/index.js",
    "content": "/// @ts-check\n/// <reference path=\"references.d.ts\" />\nimport { transformNode } from \"@ts-nameof/transforms-babel\";\nimport { createMacro, MacroError } from \"babel-plugin-macros\";\n\nexport default createMacro(nameofMacro);\n\n// @ts-ignore\nfunction nameofMacro({ references, state, babel }) {\n  // go over in reverse as if traversing in post order\n  const reverseDefault = references.default.slice().reverse();\n\n  // @ts-ignore\n  reverseDefault.forEach(path => {\n    const t = babel.types;\n    transformNode(t, getPath(), {\n      // tell the transformation to expect this identifier's name\n      nameofIdentifierName: path.node.name,\n    });\n\n    function getPath() {\n      const parentPath = path.parentPath; // identifier;\n      if (parentPath.type === \"CallExpression\") {\n        return parentPath;\n      }\n      const grandParentPath = parentPath.parentPath;\n      if (parentPath.type === \"MemberExpression\" && grandParentPath.type === \"CallExpression\") {\n        return grandParentPath;\n      }\n      throw new MacroError(\"[ts-nameof]: Could not find a call expression at path: \" + grandParentPath.getSource());\n    }\n  });\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/src/references.d.ts",
    "content": "declare module \"babel-plugin-macros\";\n"
  },
  {
    "path": "packages/ts-nameof.macro/src/tests/macroTests.ts",
    "content": "/// <reference path=\"../references.d.ts\" />\nimport * as babel from \"@babel/core\";\nimport \"@babel/preset-typescript\";\nimport { runCommonTests } from \"@ts-nameof/tests-common\";\nimport * as assert from \"assert\";\nimport babelPluginMacros from \"babel-plugin-macros\";\nimport * as path from \"path\";\n\nrunCommonTests(run, { commonPrefix: \"import nameof from './ts-nameof.macro';\\n\" });\n\ndescribe(\"using a name other than nameof\", () => {\n  it(\"should work when using a different import name\", () => {\n    const text = \"import other from './ts-nameof.macro';other(console.log);other.full(console.log);\";\n    assert.equal(run(text), `\"log\";\"console.log\";`);\n  });\n});\n\nfunction run(text: string) {\n  return babel.transformSync(text, {\n    presets: [\n      \"@babel/preset-typescript\",\n    ],\n    plugins: [\n      babelPluginMacros,\n    ],\n    filename: path.join(__dirname, \"test.ts\"),\n    ast: false,\n    generatorOpts: {\n      retainLines: true,\n    },\n  })!.code!;\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/src/tests/ts-nameof.macro/index.js",
    "content": "/// @ts-check\n// hack to get tests working\nexport { default } from \"../../index\";\n"
  },
  {
    "path": "packages/ts-nameof.macro/ts-nameof.macro.d.ts",
    "content": "declare module \"ts-nameof.macro\" {\n  /**\n   * Gets a string representation of the final identifier of the given expression.\n   *\n   * @example nameof<MyInterface>() -> \"MyInterface\"\n   * @example nameof<Array<MyInterface>>() -> \"Array\"\n   * @example nameof<MyNamespace.MyInnerInterface>() -> \"MyInnerInterface\"\n   * @example nameof<MyInterface>(o => o.prop) -> \"prop\"\n   *\n   * @param func An optional function for which the last identifier of the expression will be parsed.\n   */\n  function nameof<T>(func?: (obj: T) => any): string;\n\n  /**\n   * Gets a string representation of the last identifier of the given expression.\n   *\n   * @example nameof(console) -> \"console\"\n   * @example nameof(console.log) -> \"log\"\n   * @example nameof(console[\"warn\"]) -> \"warn\"\n   *\n   * @param obj An expression for which the last identifier will be parsed.\n   */\n  function nameof(obj: any): string;\n\n  namespace nameof {\n    /**\n     * Gets the string representation of the entire type parameter expression.\n     *\n     * @example nameof.full<MyNamespace.MyInnerInterface>() -> \"MyNamespace.MyInnerInterface\"\n     * @example nameof.full<MyNamespace.MyInnerInterface>(1) -> \"MyInnerInterface\"\n     * @example nameof.full<Array<MyInterface>>() -> \"Array\"\n     * @example nameof.full<MyNamespace.AnotherNamespace.MyInnerInterface>>(-1) -> \"MyInnerInterface\"\n     *\n     * @param periodIndex Specifies the index of the part of the expression to parse.\n     * When absent, the full expression will be parsed.\n     * A negative index can be used, indicating an offset from the end of the sequence.\n     */\n    function full<T>(periodIndex?: number): string;\n\n    /**\n     * Gets the string representation of the entire resultant expression.\n     *\n     * @example nameof.full<MyInterface>(o => o.prop.prop2) -> \"prop.prop2\"\n     * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, 1) -> \"prop2.prop3\"\n     * @example nameof.full<MyInterface>(o => o.prop.prop2.prop3, -1) -> `\"prop3\"\n     *\n     * @param func A function for which the result will be parsed, excluding the parameter's identifier.\n     * @param periodIndex Specifies the index of the part of the expression to parse.\n     * When absent, the full expression will be parsed.\n     * A negative index can be used, indicating an offset from the end of the sequence.\n     */\n    function full<T>(func: (obj: T) => any, periodIndex?: number): string;\n\n    /**\n     * Gets the string representation of the entire given expression.\n     *\n     * @example nameof.full(console.log) -> \"console.log\"\n     * @example nameof.full(window.alert.length, -1) -> \"length\"\n     * @example nameof.full(window.alert.length, 2) -> \"length\"\n     *\n     * @param obj The expression which will be parsed.\n     * @param periodIndex Specifies the index of the part of the expression to parse.\n     * When absent, the full expression will be parsed.\n     * A negative index can be used, indicating an offset from the end of the sequence.\n     */\n    function full(obj: any, periodIndex?: number): string;\n\n    /**\n     * Gets an array containing the string representation of the final identifier of each expression in the array returned by the provided function.\n     *\n     * @example nameof.toArray<MyType>(o => [o.firstProp, o.otherProp.secondProp, o.other]) -> [\"firstProp\", \"secondProp\", \"other\"]\n     * @example nameof.toArray<MyType>(o => [o.prop, nameof.full(o.myProp.otherProp, 1)]) -> [\"prop\", \"myProp.otherProp\"]\n     *\n     * @param func A function returning an array of expressions to be parsed, excluding the parameter's identifier.\n     */\n    function toArray<T>(func: (obj: T) => any[]): string[];\n\n    /**\n     * Gets an array containing the string representation of each expression in the arguments.\n     *\n     * @example nameof.toArray(myObject, otherObject) -> [\"myObject\", \"otherObject\"]\n     * @example nameof.toArray(obj.firstProp, obj.secondProp, otherObject, nameof.full(obj.other)) -> [\"firstProp\", \"secondProp\", \"otherObject\", \"obj.other\"]\n     *\n     * @param args An array of expressions to be parsed.\n     */\n    function toArray(...args: any[]): string[];\n\n    /**\n     * Embeds an expression into the string representation of the result of nameof.full.\n     *\n     * @example nameof.full(myObj.prop[nameof.interpolate(i)]) -> `myObj.prop[${i}]`\n     *\n     * @param value The value to interpolate.\n     */\n    function interpolate<T>(value: T): T;\n\n    /**\n     * Gets an array of strings where each element is a subsequent part of the expression provided.\n     *\n     * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3) -> [\"prop\", \"prop2\", \"prop3\"]\n     * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, 1) -> [\"prop2\", \"prop3\"]\n     * @example nameof.split<MyInterface>(o => o.prop.prop2.prop3, -1) -> [\"prop\", \"prop2\"]\n     *\n     * @param func A function for which the resultant parts will be parsed, excluding the parameter's identifier.\n     * @param periodIndex Specifies the index of the part of the expression to parse.\n     * When absent, the full expression will be parsed.\n     * A negative index can be used, indicating an offset from the end of the sequence.\n     */\n    function split<T>(func: (obj: T) => any, periodIndex?: number): string[];\n\n    /**\n     * Gets an array of strings where each element is a subsequent part of the expression provided.\n     *\n     * @example nameof.split(myObj.prop.prop2.prop3) -> [\"myObj\", \"prop\", \"prop2\", \"prop3\"]\n     * @example nameof.split(myObj.prop.prop2.prop3, -3);`, `[\"prop\", \"prop2\", \"prop3\"];\n     * @example nameof.split(myObj.prop.prop2.prop3, 2);`, `[\"prop2\", \"prop3\"]\n     *\n     * @param obj An expression for which the parts will be parsed.\n     * @param periodIndex Specifies the index of the part of the expression to parse.\n     * When absent, the full expression will be parsed.\n     * A negative index can be used, indicating an offset from the end of the sequence.\n     */\n    function split(obj: any, periodIndex?: number): string[];\n  }\n\n  export default nameof;\n}\n"
  },
  {
    "path": "packages/ts-nameof.macro/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"outDir\": \"./dist\"\n  },\n  \"extends\": \"../../tsconfig.common.json\",\n  \"include\": [\"./src\"],\n  \"references\": [\n    { \"path\": \"../transforms-babel\" },\n    { \"path\": \"../tests-common\" },\n    { \"path\": \"../scripts-common\" }\n  ]\n}\n"
  },
  {
    "path": "tsconfig.common.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": false,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"removeComments\": true,\n    \"experimentalDecorators\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"lib\": [\"es2015\", \"DOM\"],\n    \"esModuleInterop\": true\n  },\n  \"compileOnSave\": false\n}\n"
  }
]