├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── pull_request_template.md ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Editor.meta ├── Editor ├── AsmdefEx.cs ├── AsmdefEx.cs.meta ├── CSProjectModifier.cs ├── CSProjectModifier.cs.meta ├── Coffee.AsmdefEx.asmdef ├── Coffee.AsmdefEx.asmdef.meta ├── InspectorGUI.cs └── InspectorGUI.cs.meta ├── LICENSE.md ├── LICENSE.md.meta ├── README.md ├── README.md.meta ├── Tests.meta ├── Tests ├── AsmdefEx.EditorTests.meta ├── AsmdefEx.EditorTests │ ├── AsmdefEx.cs │ ├── AsmdefEx.cs.meta │ ├── Coffee.AsmdefEx.EditorTests.asmdef │ ├── Coffee.AsmdefEx.EditorTests.asmdef.meta │ ├── EditorTests.cs │ ├── EditorTests.cs.meta │ ├── Menus.cs │ └── Menus.cs.meta ├── AsmdefEx.RuntimeTests.meta └── AsmdefEx.RuntimeTests │ ├── AsmdefEx.cs │ ├── AsmdefEx.cs.meta │ ├── Coffee.AsmdefEx.RuntimeTests.asmdef │ ├── Coffee.AsmdefEx.RuntimeTests.asmdef.meta │ ├── InternalLibrary.meta │ ├── InternalLibrary │ ├── Coffee.AsmdefEx.RuntimeTests.InternalLibrary.asmdef │ ├── Coffee.AsmdefEx.RuntimeTests.InternalLibrary.asmdef.meta │ ├── InternalLibrary.cs │ └── InternalLibrary.cs.meta │ ├── RuntimeTests.cs │ └── RuntimeTests.cs.meta ├── package.json └── package.json.meta /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: mob-sakai # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: mob_sakai # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: mob-sakai 7 | 8 | --- 9 | 10 | NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one. 11 | 12 | **Describe the bug** 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Environment (please complete the following information):** 29 | - Version [e.g. 1.0.0] 30 | - Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL] 31 | - Unity version: [e.g. 2018.2.8f1] 32 | - Build options: [e.g. IL2CPP, .Net 4.x, LWRP] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: mob-sakai 7 | 8 | --- 9 | 10 | NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one. 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | **Additional context** 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question about this project 4 | title: '' 5 | labels: question 6 | assignees: mob-sakai 7 | 8 | --- 9 | 10 | NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one. 11 | 12 | **Describe what help do you need** 13 | A description of the question. 14 | 15 | **Additional context** 16 | Add any other context or screenshots about the question here. 17 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Pull Request 3 | about: Create a pull request 4 | title: '' 5 | assignees: mob-sakai 6 | 7 | --- 8 | 9 | **NOTE: Create a pull request to merge into `develop` branch** 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.0.0-preview.26](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.25...v1.0.0-preview.26) (2020-08-11) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * Not recompiling on first launch ([88c05b7](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/88c05b7a7d4b777cd952adbbcfacb7848515f50d)) 7 | 8 | # [1.0.0-preview.25](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.24...v1.0.0-preview.25) (2020-08-11) 9 | 10 | 11 | ### Features 12 | 13 | * support windows ([511bc47](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/511bc47ae34021eb78720dea2a5b36e4ad208c25)) 14 | 15 | # [1.0.0-preview.24](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.23...v1.0.0-preview.24) (2020-08-07) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * AsmdefEx.cs in package was unexpectedly deleted ([4ffd27a](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/4ffd27a17c4855d67154d444b097a1b9dc346b9e)) 21 | * assembly is repeatedly compiled when IgnoreAccessChecks=false ([592d81c](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/592d81c9207d4f124fa9f5e97309b2a70be03193)) 22 | 23 | 24 | ### Features 25 | 26 | * hide custom compiler option ([7eb27e5](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/7eb27e51d32f40a400f338cb275d0124866615ad)) 27 | * install custom compiler with nuget package id ([4b754cd](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/4b754cda3e78a8fc295063574010b0cd1b36c159)) 28 | * Reload only when there are changes ([9bb6af8](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/9bb6af8c522d12ff45378da765e4d2cd17861b11)) 29 | * runtime support ([cbea4b5](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/cbea4b52c8bbee90eba0834cc7180f47b43fb1d7)) 30 | * skip the initial compile request if not needed ([35845c9](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/35845c9d9b165ab7a099545e4429c60421f000f1)) 31 | * support linux ([3477df2](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/3477df260418b766ec4c736d1b3c3fe23072e860)) 32 | * update OpenSesameCompiler to 3.4.0-beta.3 ([3eb9aea](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/3eb9aeaa747d3fffe8b5dfe9c36c2a5f4d4c900c)) 33 | 34 | 35 | ### BREAKING CHANGES 36 | 37 | * `IgnoresAccessChecksTo` attribute is required to access internals/privates in other assemblies as following: 38 | ```cs 39 | [assembly: System.Runtime.CompilerServices.IgnoresAccessChecksTo("")] 40 | ``` 41 | 42 | # [1.0.0-preview.23](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.22...v1.0.0-preview.23) (2020-07-26) 43 | 44 | 45 | ### Bug Fixes 46 | 47 | * exe path ([afd3b70](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/afd3b700a5ebd9a0901eba755e11f8c62a2b18ae)) 48 | * fix typo ([528b821](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/528b821f43006fb4ea5d844fd8b8ae9e94f31fd3)) 49 | * Windows support ([2dd9086](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/2dd90865157d21c0039aad41ad6edb28f6959d3e)) 50 | 51 | 52 | ### Features 53 | 54 | * Add button to reload AsmdefEx.cs ([cb5f05d](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/cb5f05da28a4c0fe0c259b87134e458d30b26a44)) 55 | * Add menu to delete compiler ([da70e3e](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/da70e3e93fda9f98a812e7887daabfcb79bf5eef)) 56 | * Add menu to install compiler ([5e56b46](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/5e56b468ad434b57044e0b6a89e16f29022f0705)) 57 | * support TLS 1.2 or later to install compiler (OS native) ([802151f](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/802151fa0f476bba4523fa018e2f175ad1bbb613)) 58 | 59 | # [1.0.0-preview.22](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.21...v1.0.0-preview.22) (2020-05-20) 60 | 61 | 62 | ### Bug Fixes 63 | 64 | * update docs ([65e7fd5](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/65e7fd57b940b31a0109b787fbdb41b60bc51cdd)), closes [#9](https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues/9) 65 | 66 | # [1.0.0-preview.21](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.20...v1.0.0-preview.21) (2020-02-18) 67 | 68 | 69 | ### Bug Fixes 70 | 71 | * log format ([0a253f8](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/0a253f8d7754a0085570ecf998781be93a882a21)) 72 | * multiple compile issue ([3ae0425](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/3ae042579f07357d2aafac8a96e88de477117bab)) 73 | * publish feature ([fff7dcf](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/fff7dcf4903c4d026a9069fe2d4641502a865b8a)) 74 | 75 | 76 | ### Features 77 | 78 | * new architecture ([ad58072](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/ad580728dee68637d0c2d63814967e2fc964f374)) 79 | * redesign portable mode ([6386e62](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/6386e624b1ba2c37bacb80384d6779a484df6f8b)) 80 | * remove portable mode ([e00ecdc](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/e00ecdc33e7e8ce81b42c838311bf1b7d1be6382)) 81 | 82 | # [1.0.0-preview.20](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.19...v1.0.0-preview.20) (2020-02-10) 83 | 84 | 85 | ### Bug Fixes 86 | 87 | * fix copying portable dll ([889c84f](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/889c84fd8ff4438c0215ab65a7ed943642ceac55)) 88 | * fix for windows ([4eaab54](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/4eaab54175a8425ceec1cf2682b743f0b8931dc2)) 89 | 90 | # [1.0.0-preview.19](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.18...v1.0.0-preview.19) (2020-02-10) 91 | 92 | 93 | ### Bug Fixes 94 | 95 | * resolve asmdef path correctly ([9461dad](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/9461dad3954418d963658dbd0d927e69c65e3104)) 96 | 97 | 98 | ### Features 99 | 100 | * set language version in csproj to latest ([07bbda4](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/07bbda41f2836face6f1b0a50dda86c359d4c9b2)) 101 | 102 | # [1.0.0-preview.19](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.18...v1.0.0-preview.19) (2020-02-10) 103 | 104 | 105 | ### Bug Fixes 106 | 107 | * resolve asmdef path correctly ([9461dad](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/9461dad3954418d963658dbd0d927e69c65e3104)) 108 | 109 | 110 | ### Features 111 | 112 | * set language version in csproj to latest ([07bbda4](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/07bbda41f2836face6f1b0a50dda86c359d4c9b2)) 113 | 114 | # [1.0.0-preview.19](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.18...v1.0.0-preview.19) (2020-02-10) 115 | 116 | 117 | ### Bug Fixes 118 | 119 | * resolve asmdef path correctly ([9461dad](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/9461dad3954418d963658dbd0d927e69c65e3104)) 120 | 121 | 122 | ### Features 123 | 124 | * set language version in csproj to latest ([07bbda4](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/07bbda41f2836face6f1b0a50dda86c359d4c9b2)) 125 | 126 | # [1.0.0-preview.18](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.17...v1.0.0-preview.18) (2020-02-06) 127 | 128 | 129 | ### Bug Fixes 130 | 131 | * fix file path problems ([8d9b88b](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/8d9b88b83dacb2584b05c3559e8056d51d80ff1a)) 132 | 133 | # [1.0.0-preview.17](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.16...v1.0.0-preview.17) (2020-02-06) 134 | 135 | 136 | ### Bug Fixes 137 | 138 | * fix file path on copying ([6c554ea](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/6c554ea57262b3f2bc482d49b36ffc460a54a582)) 139 | 140 | # [1.0.0-preview.16](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.15...v1.0.0-preview.16) (2020-02-06) 141 | 142 | 143 | ### Bug Fixes 144 | 145 | * guid conflict ([a2a33de](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/a2a33de7e644755fc0e85a8082655cf754bbe93d)) 146 | 147 | # [1.0.0-preview.15](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.14...v1.0.0-preview.15) (2020-01-30) 148 | 149 | 150 | ### Bug Fixes 151 | 152 | * support windows line-ending ([98f4299](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/98f4299129746c0a80b5fe9d890bff040eac5e38)) 153 | 154 | # [1.0.0-preview.14](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.13...v1.0.0-preview.14) (2020-01-30) 155 | 156 | 157 | ### Bug Fixes 158 | 159 | * update release workflow ([9026765](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/9026765c1d89801c5bedbbd03a2a0faaf984c331)) 160 | 161 | # [1.0.0-preview.13](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.12...v1.0.0-preview.13) (2020-01-30) 162 | 163 | 164 | ### Bug Fixes 165 | 166 | * fix asmdef settings for development ([ecda4e9](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/ecda4e95ee174e7828b6bbf738d6f423ae87bc87)) 167 | * fix inspector GUI ([69aaffe](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/69aaffe1649ff528cda6b9a2a707879ed874d14f)) 168 | * fix portable dll name ([a75d9bd](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/a75d9bd23d171d3c001362f1b487af08f8f8bafe)) 169 | * ignore unnecessary file copying ([a5acd99](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/a5acd990fbfe5041e74af33a9bf4afa93a099a7b)) 170 | 171 | 172 | ### Features 173 | 174 | * add develop menu ([0856e78](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/0856e78d7d8f35e9e8aec96c628eaae94040018e)) 175 | * add portable mode ([f72f635](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/f72f635d9ee7d188a121a9de8d9dfa80b53fafc5)) 176 | * install compiler on load ([7cee469](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/7cee4694f120c1b4338d4fcac5d821a5b0579fa9)) 177 | * reload published dll ([1391255](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/1391255bcc0cacb2448d940ea97dc2eeadcd2f4d)) 178 | * remove bootstrap ([69cf366](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/69cf3662bbbe0ed5b0a536c52041c4ee8dfe4e3d)) 179 | * remove portable script ([d4a9325](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/d4a9325cc6849088866b86b3d2b2802ca04dbe25)) 180 | * show portable version ([4121e4e](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/4121e4eae4bca07b21bfe059d5dfa3a81493ff2a)) 181 | 182 | # [1.0.0-preview.12](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.11...v1.0.0-preview.12) (2020-01-16) 183 | 184 | 185 | ### Bug Fixes 186 | 187 | * fix .npmignore ([cdde18c](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/cdde18cf9981ab8e55ffc9acf501b61f836bdae2)) 188 | 189 | # [1.0.0-preview.11](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.10...v1.0.0-preview.11) (2020-01-16) 190 | 191 | 192 | ### Bug Fixes 193 | 194 | * add development log ([bb7c365](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/bb7c365376f37117cb26c38b0a8e432528f22583)) 195 | * fix installer ([b707e84](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/b707e84409a72b5985438e8892014264fe74841a)) 196 | * fix publish command ([df7bdd1](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/df7bdd1718f12a5ae9735c838f000ff3b1c1a67f)) 197 | * unzip with 7z ([0db6bbd](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/0db6bbde2828d1ac608110b78ac85ec32ad5b37d)) 198 | 199 | 200 | ### Features 201 | 202 | * add 'OPEN_SESAME' symbol automatically ([8718833](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/8718833dedf81e4712b220b30e4be2017e38a750)) 203 | * add develop menu ([8893a1f](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/8893a1fa7423ec7887a51b3a0521ddd223b3c81f)) 204 | * portable mode ([2cfd2e0](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/2cfd2e0b376525a0fe8438b0bd022acaa3c19585)) 205 | * update OpenSesameCompiler to 3.4.0-beta.3 ([f8d9a1b](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/f8d9a1bc18324631c59cb5fea62d76a0c700f37c)) 206 | 207 | # [1.0.0-preview.10](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.9...v1.0.0-preview.10) (2020-01-09) 208 | 209 | 210 | ### Bug Fixes 211 | 212 | * cannot publish on 2019.3 ([29f1974](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/29f1974be0991aea6999733430d43ed4e52844de)) 213 | * cannot publish on windows ([bfb6801](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/bfb680185b4702561c9778f12b7e28c8a453606d)) 214 | * fail to download compiler from nuget ([f579a05](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/f579a05cecf33dcc34c8ab9ebd67b9c5b223bfe8)) 215 | * not found filename ([a4cf2a5](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/a4cf2a5dbdb22390c2e5f3757e335d2f659297ac)) 216 | * TlsException: Invalid certificate received from server. ([48dbff0](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/48dbff02899e2a319b9fa6a439e5e39731c4e346)), closes [#13](https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues/13) 217 | 218 | 219 | ### Features 220 | 221 | * add pre-compiler to init ([062892d](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/062892dc60b4f8ba3afc33f5099f99cc41a22be5)) 222 | * support 2019.3 ([134f304](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/134f3043f854111d9f8bed822b49a4dc4db5d690)) 223 | * support 2020.1 ([d2589b3](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/d2589b379e253fb0fbcbdc656706bb579cf66a12)) 224 | * support Windows ([de3bccb](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/de3bccb603ff4d5781610671463cc26bd028dd4b)), closes [#8](https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues/8) 225 | 226 | # [1.0.0-preview.9](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.8...v1.0.0-preview.9) (2020-01-06) 227 | 228 | 229 | ### Bug Fixes 230 | 231 | * fix special thanks ([c64bcc0](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/c64bcc0ee538f18c152b3af348fd6ee9f1884c97)) 232 | 233 | # [1.0.0-preview.8](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.7...v1.0.0-preview.8) (2020-01-06) 234 | 235 | 236 | ### Bug Fixes 237 | 238 | * update readme ([385241b](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/385241bb09eee284c5792e2fd337440b9ad7348c)) 239 | 240 | # [1.0.0-preview.7](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.6...v1.0.0-preview.7) (2020-01-06) 241 | 242 | 243 | ### Bug Fixes 244 | 245 | * update dll ([08f9e8e](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/08f9e8ed7a2caec065794c9c0aaff2a04f69d0fa)) 246 | 247 | # [1.0.0-preview.6](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.5...v1.0.0-preview.6) (2020-01-06) 248 | 249 | 250 | ### Bug Fixes 251 | 252 | * remove extra logging ([7093851](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/709385132cef6d543a9843fa5f0112d8b8c76c69)) 253 | 254 | # [1.0.0-preview.5](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.4...v1.0.0-preview.5) (2020-01-06) 255 | 256 | 257 | ### Bug Fixes 258 | 259 | * update dll for package ([d27a4d0](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/d27a4d0a564cdbd05c4a87f8f569e5c8874e1113)) 260 | 261 | # [1.0.0-preview.4](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.3...v1.0.0-preview.4) (2020-01-06) 262 | 263 | 264 | ### Features 265 | 266 | * add/remove scripting define symbols each assemblies ([101b587](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/101b587e0f70ebb0d655071d0b07d6d81d68c475)), closes [#12](https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues/12) 267 | * modify symbols in csproj ([47eef0e](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/47eef0e174881e4f841e2bb9080714f87a0cf231)) 268 | * refactor setting ([5e5e869](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/5e5e8696315694346cf2fcea4716eaa78ca756fd)) 269 | * use Microsoft.Net.Compilers to compile ([d9b4648](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/d9b464876df8308899e57297aebe2a0457de88f0)), closes [#11](https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues/11) 270 | 271 | # [1.0.0-preview.3](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.2...v1.0.0-preview.3) (2019-12-25) 272 | 273 | 274 | ### Bug Fixes 275 | 276 | * overwrite predefined target assemblies ([e062393](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/e0623934c7740a69467553738d072cc1428808ff)) 277 | 278 | 279 | ### Features 280 | 281 | * support 2019.3 ([d7fab1a](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/d7fab1a069df43f002c14a1de7471d39a193fe55)) 282 | 283 | # [1.0.0-preview.2](https://github.com/mob-sakai/OpenSesameCompilerForUnity/compare/v1.0.0-preview.1...v1.0.0-preview.2) (2019-12-25) 284 | 285 | 286 | ### Bug Fixes 287 | 288 | * default symbol is empty ([f951f15](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/f951f158f89786c06c9ad0effd2e2d73a143a7a3)) 289 | * fix readme links ([24d7680](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/24d7680c6fdaabecfb07aadce900104e3517258f)) 290 | * ignore Tests.meta to publish ([dac1aa6](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/dac1aa6ce0cbe62bbcb70b69945a52103d8fabb4)) 291 | * remove old languages on reload ([e5a04a4](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/e5a04a47a249d50f3fc511d67a6357e7c12e7bd5)) 292 | 293 | # 1.0.0-preview.1 (2019-12-25) 294 | 295 | 296 | ### Features 297 | 298 | * implement ([ac0360c](https://github.com/mob-sakai/OpenSesameCompilerForUnity/commit/ac0360c9cf9b47c66f2a21d1e65721472ede0be9)) 299 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d10e4c473453a4b1e9a317654fd0d920 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1fd6685219174f119ed8a257d7374d5 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/AsmdefEx.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text.RegularExpressions; 10 | using UnityEditor; 11 | using UnityEngine; 12 | using UnityEditor.Compilation; 13 | 14 | namespace Coffee.AsmdefEx 15 | { 16 | internal static class PackageSettings 17 | { 18 | public const string PackageId = "OpenSesame.Net.Compilers.3.4.0-beta.1"; 19 | } 20 | 21 | internal static class ReflectionExtensions 22 | { 23 | const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; 24 | 25 | static object Inst(this object self) 26 | { 27 | return (self is Type) ? null : self; 28 | } 29 | 30 | static Type Type(this object self) 31 | { 32 | return (self as Type) ?? self.GetType(); 33 | } 34 | 35 | public static object New(this Type self, params object[] args) 36 | { 37 | var types = args.Select(x => x.GetType()).ToArray(); 38 | return self.Type().GetConstructor(types) 39 | .Invoke(args); 40 | } 41 | 42 | public static object Call(this object self, string methodName, params object[] args) 43 | { 44 | var types = args.Select(x => x.GetType()).ToArray(); 45 | return self.Type().GetMethod(methodName, types) 46 | .Invoke(self.Inst(), args); 47 | } 48 | 49 | public static object Call(this object self, Type[] genericTypes, string methodName, params object[] args) 50 | { 51 | return self.Type().GetMethod(methodName, FLAGS) 52 | .MakeGenericMethod(genericTypes) 53 | .Invoke(self.Inst(), args); 54 | } 55 | 56 | public static object Get(this object self, string memberName, MemberInfo mi = null) 57 | { 58 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 59 | return mi is PropertyInfo 60 | ? (mi as PropertyInfo).GetValue(self.Inst(), new object[0]) 61 | : (mi as FieldInfo).GetValue(self.Inst()); 62 | } 63 | 64 | public static void Set(this object self, string memberName, object value, MemberInfo mi = null) 65 | { 66 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 67 | if (mi is PropertyInfo) 68 | (mi as PropertyInfo).SetValue(self.Inst(), value, new object[0]); 69 | else 70 | (mi as FieldInfo).SetValue(self.Inst(), value); 71 | } 72 | } 73 | 74 | internal class Settings 75 | { 76 | public bool IgnoreAccessChecks; 77 | public string ModifySymbols = ""; 78 | public string CustomCompiler = ""; 79 | 80 | public bool SholdChangeCompilerProcess 81 | { 82 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(ModifySymbols) || !string.IsNullOrEmpty(CustomCompiler); } 83 | } 84 | 85 | public bool UseCustomCompiler 86 | { 87 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(CustomCompiler); } 88 | } 89 | 90 | public static Settings GetAtPath(string path) 91 | { 92 | var setting = new Settings(); 93 | if (string.IsNullOrEmpty(path)) 94 | return setting; 95 | 96 | // If input path is directory, find asmdef file. 97 | if (Directory.Exists(path)) 98 | path = Directory.GetFiles(path, "*.asmdef") 99 | .Select(x => x.Replace(Environment.CurrentDirectory + Path.DirectorySeparatorChar, "")) 100 | .FirstOrDefault(); 101 | 102 | // Not find asmdef file. 103 | if (string.IsNullOrEmpty(path) || !File.Exists(path) || !File.Exists(path + ".meta")) 104 | return setting; 105 | 106 | try 107 | { 108 | var json = AssetImporter.GetAtPath(path).userData; 109 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 110 | } 111 | catch 112 | { 113 | } 114 | 115 | return setting; 116 | } 117 | 118 | public string ToJson() 119 | { 120 | return string.Format("{{" + 121 | "\"IgnoreAccessChecks\":{0}," + 122 | "\"ModifySymbols\":\"{1}\"," + 123 | "\"CustomCompiler\":\"{2}\"" + 124 | "}}", 125 | IgnoreAccessChecks ? "true" : "false", 126 | ModifySymbols ?? "", 127 | CustomCompiler ?? "" 128 | ); 129 | } 130 | 131 | public static Settings CreateFromJson(string json = "") 132 | { 133 | var setting = new Settings(); 134 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 135 | return setting; 136 | } 137 | 138 | static void GetSettingssFromJson(string json, out bool ignoreAccessChecks, out string modifySymbols, out string customCompiler) 139 | { 140 | ignoreAccessChecks = false; 141 | modifySymbols = ""; 142 | customCompiler = ""; 143 | if (string.IsNullOrEmpty(json)) 144 | return; 145 | 146 | ignoreAccessChecks = Regex.Match(json, "\"IgnoreAccessChecks\":\\s*(true|false)").Groups[1].Value == "true"; 147 | modifySymbols = Regex.Match(json, "\"ModifySymbols\":\\s*\"([^\"]*)\"").Groups[1].Value; 148 | customCompiler = Regex.Match(json, "\"CustomCompiler\":\\s*\"([^\"]*)\"").Groups[1].Value; 149 | } 150 | } 151 | 152 | internal static class CustomCompiler 153 | { 154 | static string s_InstallPath; 155 | const string k_LogHeader = "[CustomCompiler] "; 156 | 157 | static void Log(string format, params object[] args) 158 | { 159 | if (Core.LogEnabled) 160 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 161 | } 162 | 163 | public static string GetInstalledPath(string packageId = "") 164 | { 165 | if (!string.IsNullOrEmpty(s_InstallPath) && File.Exists(s_InstallPath)) 166 | return s_InstallPath; 167 | 168 | try 169 | { 170 | packageId = string.IsNullOrEmpty(packageId) ? PackageSettings.PackageId : packageId; 171 | s_InstallPath = Install(packageId); 172 | } 173 | catch (Exception ex) 174 | { 175 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + ex.Message, ex.InnerException)); 176 | } 177 | finally 178 | { 179 | EditorUtility.ClearProgressBar(); 180 | } 181 | 182 | return s_InstallPath; 183 | } 184 | 185 | static string Install(string packageId) 186 | { 187 | char sep = Path.DirectorySeparatorChar; 188 | string url = "https://globalcdn.nuget.org/packages/" + packageId.ToLower() + ".nupkg"; 189 | string downloadPath = ("Temp/" + Path.GetFileName(Path.GetTempFileName())).Replace('/', sep); 190 | string installPath = ("Library/" + packageId).Replace('/', sep); 191 | string cscToolExe = (installPath + "/tools/csc.exe").Replace('/', sep); 192 | 193 | // Custom compiler is already installed. 194 | if (File.Exists(cscToolExe)) 195 | { 196 | Log("Custom compiler '{0}' is already installed at {1}", packageId, cscToolExe); 197 | return cscToolExe; 198 | } 199 | 200 | if (Directory.Exists(installPath)) 201 | Directory.Delete(installPath, true); 202 | 203 | try 204 | { 205 | UnityEngine.Debug.LogFormat(k_LogHeader + "Install custom compiler '{0}'", packageId); 206 | 207 | // Download custom compiler package from nuget. 208 | { 209 | UnityEngine.Debug.LogFormat(k_LogHeader + "Download {0} from nuget: {1}", packageId, url); 210 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Download {0} from nuget", packageId), 0.2f); 211 | 212 | switch (Application.platform) 213 | { 214 | case RuntimePlatform.WindowsEditor: 215 | ExecuteCommand("PowerShell.exe", string.Format("curl -O {0} {1}", downloadPath, url)); 216 | break; 217 | case RuntimePlatform.OSXEditor: 218 | ExecuteCommand("curl", string.Format("-o {0} -L {1}", downloadPath, url)); 219 | break; 220 | case RuntimePlatform.LinuxEditor: 221 | ExecuteCommand("wget", string.Format("-O {0} {1}", downloadPath, url)); 222 | break; 223 | } 224 | } 225 | 226 | // Extract nuget package (unzip). 227 | { 228 | UnityEngine.Debug.LogFormat(k_LogHeader + "Extract {0} to {1} with 7z", downloadPath, installPath); 229 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Extract {0}", downloadPath), 0.4f); 230 | 231 | string appPath = EditorApplication.applicationContentsPath.Replace('/', sep); 232 | string args = string.Format("x {0} -o{1}", downloadPath, installPath); 233 | 234 | switch (Application.platform) 235 | { 236 | case RuntimePlatform.WindowsEditor: 237 | ExecuteCommand(appPath + "\\Tools\\7z.exe", args); 238 | break; 239 | case RuntimePlatform.OSXEditor: 240 | case RuntimePlatform.LinuxEditor: 241 | ExecuteCommand(appPath + "/Tools/7za", args); 242 | break; 243 | } 244 | } 245 | 246 | UnityEngine.Debug.LogFormat(k_LogHeader + "Custom compiler '{0}' has been installed in {1}.", packageId, installPath); 247 | } 248 | catch 249 | { 250 | throw new Exception(string.Format("Custom compiler '{0}' installation failed.", packageId)); 251 | } 252 | finally 253 | { 254 | EditorUtility.ClearProgressBar(); 255 | } 256 | 257 | if (File.Exists(cscToolExe)) 258 | return cscToolExe; 259 | 260 | throw new FileNotFoundException(string.Format("Custom compiler '{0}' is not found at {1}", packageId, cscToolExe)); 261 | } 262 | 263 | static void ExecuteCommand(string exe, string args) 264 | { 265 | UnityEngine.Debug.LogFormat(k_LogHeader + "Execute command: {0} {1}", exe, args); 266 | 267 | Process p = Process.Start(new ProcessStartInfo() 268 | { 269 | FileName = exe, 270 | Arguments = args, 271 | CreateNoWindow = true, 272 | UseShellExecute = false, 273 | RedirectStandardError = true, 274 | }); 275 | p.WaitForExit(); 276 | 277 | if (p.ExitCode != 0) 278 | { 279 | UnityEngine.Debug.LogErrorFormat(k_LogHeader + p.StandardError.ReadToEnd()); 280 | throw new Exception(); 281 | } 282 | } 283 | } 284 | 285 | [InitializeOnLoad] 286 | internal static class Core 287 | { 288 | public static bool LogEnabled { get; private set; } 289 | public static string k_LogHeader = "[AsmdefEx] "; 290 | 291 | static void Log(string format, params object[] args) 292 | { 293 | if (LogEnabled) 294 | LogEx(format, args); 295 | } 296 | 297 | public static void LogEx(string format, params object[] args) 298 | { 299 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 300 | } 301 | 302 | public static void Error(Exception e) 303 | { 304 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 305 | } 306 | 307 | public static object GetScriptAssembly(string assemblyName) 308 | { 309 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 310 | Type tCSharpLanguage = Type.GetType("UnityEditor.Scripting.Compilers.CSharpLanguage, UnityEditor"); 311 | return tEditorCompilationInterface.Call(new[] {tCSharpLanguage}, "GetScriptAssemblyForLanguage", assemblyName); 312 | } 313 | 314 | public static string[] ModifyDefines(IEnumerable defines, bool ignoreAccessChecks, string modifySymbols) 315 | { 316 | var symbols = modifySymbols.Split(';', ','); 317 | var add = symbols.Where(x => 0 < x.Length && !x.StartsWith("!")); 318 | var remove = symbols.Where(x => 1 < x.Length && x.StartsWith("!")).Select(x => x.Substring(1)); 319 | return defines 320 | .Union(add ?? Enumerable.Empty()) 321 | .Except(remove ?? Enumerable.Empty()) 322 | .Union(ignoreAccessChecks ? new[] {"IGNORE_ACCESS_CHECKS"} : Enumerable.Empty()) 323 | .Union(new[] {"ASMDEF_EX"}) 324 | .Distinct() 325 | .ToArray(); 326 | } 327 | 328 | public static void ModifyFiles(IEnumerable files, bool ignoreAccessChecks) 329 | { 330 | const string s_If = "#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 331 | const string s_EndIf = "#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 332 | 333 | // Add #if and #endif to all source files. 334 | foreach (var file in files) 335 | { 336 | var text = File.ReadAllText(file); 337 | Log("ModifyFiles: {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 338 | if (text.Contains(s_If) == ignoreAccessChecks) 339 | continue; 340 | 341 | var m = Regex.Match(text, "[\r\n]+"); 342 | if (!m.Success) 343 | continue; 344 | 345 | var nl = m.Value; 346 | if (ignoreAccessChecks) 347 | { 348 | text = s_If + nl + text + nl + s_EndIf; 349 | } 350 | else 351 | { 352 | text = text.Replace(s_If + nl, ""); 353 | text = text.Replace(nl + s_EndIf, ""); 354 | } 355 | 356 | Log("ModifyFiles: Write {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 357 | File.WriteAllText(file, text); 358 | } 359 | } 360 | 361 | public static void ChangeCompilerProcess(object compiler, Settings setting) 362 | { 363 | Type tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor"); 364 | Type tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor"); 365 | FieldInfo fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance); 366 | 367 | Log("Kill previous compiler process"); 368 | var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo; 369 | compiler.Call("Dispose"); 370 | 371 | // Convert response file for Mono to .Net. 372 | // - Add preferreduilang option (en-US) 373 | // - Change language version to 'latest' 374 | // - Change 'debug' to 'debug:portable' 375 | // - Change compiler switch prefix '-' to '/' 376 | string responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1"); 377 | bool isMono = compiler.GetType().Name == "MonoCSharpCompiler"; 378 | var text = File.ReadAllText(responseFile); 379 | text = Regex.Replace(text, "[\r\n]+", "\n"); 380 | text = Regex.Replace(text, "^-", "/", RegexOptions.Multiline); 381 | 382 | // Modify scripting define symbols. 383 | { 384 | Log("Modify scripting define symbols: {0}", responseFile); 385 | var defines = Regex.Matches(text, "^/define:(.*)$", RegexOptions.Multiline) 386 | .Cast() 387 | .Select(x => x.Groups[1].Value); 388 | 389 | text = Regex.Replace(text, "[\r\n]+/define:[^\r\n]+", ""); 390 | foreach (var d in ModifyDefines(defines, setting.IgnoreAccessChecks, setting.ModifySymbols)) 391 | { 392 | text += "\n/define:" + d; 393 | } 394 | } 395 | 396 | // Add/remove '#if IGNORE_ACCESS_CHECKS' and '#endif' preprocessor. 397 | var files = Regex.Matches(text, "^\"(.*)\"$", RegexOptions.Multiline) 398 | .Cast() 399 | .Select(x => x.Groups[1].Value) 400 | .Where(x => Path.GetExtension(x) == ".cs") 401 | .Where(x => Path.GetFileName(x) != "AsmdefEx.cs"); 402 | ModifyFiles(files, setting.IgnoreAccessChecks); 403 | 404 | // To access to non-publics in other assemblies, use custom compiler instead of default csc. 405 | if (setting.UseCustomCompiler) 406 | { 407 | text = Regex.Replace(text, "^/langversion:\\d+$", "/langversion:latest", RegexOptions.Multiline); 408 | text = Regex.Replace(text, "^/debug$", "/debug:portable", RegexOptions.Multiline); 409 | text += "\n/preferreduilang:en-US"; 410 | 411 | // Change exe file path. 412 | var cscToolExe = CustomCompiler.GetInstalledPath(setting.CustomCompiler); 413 | Log("Change csc tool exe to {0}", cscToolExe); 414 | if (Application.platform == RuntimePlatform.WindowsEditor) 415 | { 416 | psi.FileName = Path.GetFullPath(cscToolExe); 417 | psi.Arguments = "/shared /noconfig @" + responseFile; 418 | } 419 | else 420 | { 421 | psi.FileName = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/bin/mono"); 422 | psi.Arguments = cscToolExe + " /noconfig @" + responseFile; 423 | } 424 | } 425 | // Revert prefix symbols for mono compiler 426 | else if (isMono) 427 | { 428 | text = Regex.Replace(text, "^/", "-", RegexOptions.Multiline); 429 | } 430 | 431 | text = Regex.Replace(text, "\n", System.Environment.NewLine); 432 | File.WriteAllText(responseFile, text); 433 | 434 | Log("Restart compiler process: {0} {1}", psi.FileName, psi.Arguments); 435 | var program = tProgram.New(psi); 436 | program.Call("Start"); 437 | compiler.Set("process", program, fiProcess); 438 | } 439 | 440 | static void OnAssemblyCompilationStarted(string name) 441 | { 442 | try 443 | { 444 | string assemblyName = Path.GetFileNameWithoutExtension(name); 445 | string assemblyFilename = assemblyName + ".dll"; 446 | 447 | if (assemblyName != typeof(Core).Assembly.GetName().Name) 448 | return; 449 | 450 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 451 | var compilerTasks = tEditorCompilationInterface.Get("Instance").Get("compilationTask").Get("compilerTasks") as IDictionary; 452 | var scriptAssembly = compilerTasks.Keys.Cast().FirstOrDefault(x => (x.Get("Filename") as string) == assemblyFilename); 453 | 454 | // Should change compiler process for the assembly? 455 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 456 | var setting = Settings.GetAtPath(asmdefPath); 457 | if (!setting.SholdChangeCompilerProcess) 458 | return; 459 | 460 | // Create new compiler to recompile. 461 | Log("Assembly compilation started: {0} should be recompiled.", assemblyName); 462 | Core.ChangeCompilerProcess(compilerTasks[scriptAssembly], setting); 463 | } 464 | catch (Exception e) 465 | { 466 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 467 | } 468 | } 469 | 470 | static Core() 471 | { 472 | var assemblyName = typeof(Core).Assembly.GetName().Name; 473 | if (assemblyName == "Coffee.AsmdefEx") 474 | return; 475 | 476 | k_LogHeader = string.Format("[AsmdefEx ({0})] ", assemblyName); 477 | LogEnabled = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup) 478 | .Split(';', ',') 479 | .Any(x => x == "ASMDEF_EX_LOG"); 480 | 481 | Log("Start watching assembly '{0}' compilation.", typeof(Core).Assembly.GetName().Name); 482 | CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted; 483 | } 484 | } 485 | 486 | #if !ASMDEF_EX 487 | [InitializeOnLoad] 488 | internal class RecompileRequest 489 | { 490 | static RecompileRequest() 491 | { 492 | var assemblyName = typeof(RecompileRequest).Assembly.GetName().Name; 493 | if (assemblyName == "Coffee.AsmdefEx") 494 | return; 495 | 496 | // Should change compiler process for the assembly? 497 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 498 | var setting = Settings.GetAtPath(asmdefPath); 499 | if (!setting.SholdChangeCompilerProcess) 500 | return; 501 | 502 | if (Core.LogEnabled) 503 | UnityEngine.Debug.LogFormat("Request to recompile: {0} ({1})", assemblyName, asmdefPath); 504 | 505 | EditorApplication.delayCall += () => AssetDatabase.ImportAsset(asmdefPath); 506 | } 507 | } 508 | #endif 509 | } 510 | #endif 511 | -------------------------------------------------------------------------------- /Editor/AsmdefEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 95bb1b15c6246438e9223c5516ec2716 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/CSProjectModifier.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text.RegularExpressions; 3 | using UnityEditor; 4 | using UnityEditor.Compilation; 5 | 6 | 7 | namespace Coffee.AsmdefEx 8 | { 9 | internal class CSProjectModifier : AssetPostprocessor 10 | { 11 | static void Log(string format, params object[] args) 12 | { 13 | if (Core.LogEnabled) 14 | UnityEngine.Debug.LogFormat("[CSProjectModifier] " + format, args); 15 | } 16 | 17 | static string OnGeneratedCSProject(string path, string content) 18 | { 19 | var assemblyName = Path.GetFileNameWithoutExtension(path); 20 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 21 | var setting = Settings.GetAtPath(asmdefPath); 22 | if (string.IsNullOrEmpty(setting.ModifySymbols) && !setting.IgnoreAccessChecks) 23 | return content; 24 | 25 | var defines = Regex.Match(content, "(.*)").Groups[1].Value.Split(';', ','); 26 | defines = Core.ModifyDefines(defines, setting.IgnoreAccessChecks, setting.ModifySymbols); 27 | var defineText = string.Join(";", defines); 28 | 29 | Log("Script defines in {0}.csproj are modified:\n{1}", assemblyName, defineText); 30 | content = Regex.Replace(content, "(.*)", string.Format("{0}", defineText), RegexOptions.Multiline); 31 | 32 | // Use latest language version. 33 | if (setting.IgnoreAccessChecks) 34 | { 35 | content = Regex.Replace(content, ".*", "latest", RegexOptions.Multiline); 36 | } 37 | 38 | return content; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Editor/CSProjectModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 688658d1d63f445ef885f475bd6f8884 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Coffee.AsmdefEx.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Coffee.AsmdefEx", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [ 6 | "Editor" 7 | ], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": false, 13 | "defineConstraints": [ 14 | "!ASMDEF_EX_DISABLE" 15 | ] 16 | } -------------------------------------------------------------------------------- /Editor/Coffee.AsmdefEx.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd0e0929ccaf1421f876415e365825a5 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor/InspectorGUI.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEditorInternal; 5 | using UnityEngine; 6 | using System.Text.RegularExpressions; 7 | using UnityEditor.Compilation; 8 | using System; 9 | using System.Security.Cryptography; 10 | using System.Linq; 11 | 12 | namespace Coffee.AsmdefEx 13 | { 14 | [InitializeOnLoad] 15 | internal static class InspectorGUI 16 | { 17 | static string s_AssemblyNameToPublish; 18 | static GUIContent s_IgnoreAccessCheckText; 19 | static GUIContent s_EnableText; 20 | static GUIContent s_ModifySymbolsText; 21 | static GUIContent s_SettingsText; 22 | static GUIContent s_PublishText; 23 | static GUIContent s_ReloadText; 24 | static GUIContent s_HelpText; 25 | static bool s_OpenSettings = false; 26 | static Dictionary s_EnableAsmdefs = new Dictionary(); 27 | 28 | static void OnAssemblyCompilationFinished(string name, CompilerMessage[] messages) 29 | { 30 | try 31 | { 32 | // This assembly is requested to publish? 33 | string assemblyName = Path.GetFileNameWithoutExtension(name); 34 | if (s_AssemblyNameToPublish != assemblyName) 35 | return; 36 | 37 | s_AssemblyNameToPublish = null; 38 | Core.LogEx("Assembly compilation finished: {0} is requested to publish.", assemblyName); 39 | 40 | // No compilation error? 41 | if (messages.Any(x => x.type == CompilerMessageType.Error)) 42 | return; 43 | 44 | var scriptAssembly = Core.GetScriptAssembly(assemblyName); 45 | var originPath = scriptAssembly.Get("OriginPath") as string; 46 | 47 | // Publish a dll to parent directory. 48 | var dst = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(originPath)), assemblyName + ".dll"); 49 | var src = "Library/ScriptAssemblies/" + Path.GetFileName(dst); 50 | Core.LogEx("Publish assembly as dll: " + dst); 51 | CopyFileIfUpdated(Path.GetFullPath(src), Path.GetFullPath(dst)); 52 | 53 | EditorApplication.delayCall += () => AssetDatabase.ImportAsset(dst); 54 | } 55 | catch (Exception e) 56 | { 57 | Core.Error(e); 58 | } 59 | } 60 | 61 | public static void CopyFileIfUpdated(string src, string dst) 62 | { 63 | src = Path.GetFullPath(src); 64 | if (!File.Exists(src)) 65 | return; 66 | 67 | dst = Path.GetFullPath(dst); 68 | if (File.Exists(dst)) 69 | { 70 | using (var srcFs = new FileStream(src, FileMode.Open)) 71 | using (var dstFs = new FileStream(dst, FileMode.Open)) 72 | using (var md5 = new MD5CryptoServiceProvider()) 73 | { 74 | if (md5.ComputeHash(srcFs).SequenceEqual(md5.ComputeHash(dstFs))) 75 | return; 76 | } 77 | } 78 | 79 | var dir = Path.GetDirectoryName(dst); 80 | if (!Directory.Exists(dir)) 81 | Directory.CreateDirectory(dir); 82 | 83 | File.Copy(src, dst, true); 84 | } 85 | 86 | static InspectorGUI() 87 | { 88 | s_IgnoreAccessCheckText = new GUIContent("Ignore Access Checks", "Ignore accessibility checks on compiling to allow access to internals and privates in other assemblies."); 89 | s_ModifySymbolsText = new GUIContent("Modify Symbols", "When compiling this assembly, add or remove specific symbols separated with semicolons (;) or commas (,).\nSymbols starting with '!' will be removed.\n\ne.g. 'SYMBOL_TO_ADD;!SYMBOL_TO_REMOVE;...'"); 90 | s_EnableText = new GUIContent("Enable Asmdef Extension", "Enable asmdef extension for this assembly."); 91 | s_SettingsText = new GUIContent("Asmdef Extension", "Show extension settings for this assembly definition file."); 92 | s_PublishText = new GUIContent("Publish as dll", "Publish this assembly as dll to the parent directory."); 93 | s_ReloadText = new GUIContent("Reload AsmdefEx.cs", "Reload AsmdefEx.cs for this assembly."); 94 | s_HelpText = new GUIContent("Help", "Open AsmdefEx help page on browser."); 95 | 96 | Editor.finishedDefaultHeaderGUI += OnPostHeaderGUI; 97 | s_OpenSettings = EditorPrefs.GetBool("Coffee.AsmdefEx.InspectorGUI_OpenSettings", false); 98 | CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished; 99 | } 100 | 101 | static void OnPostHeaderGUI(Editor editor) 102 | { 103 | var importer = editor.target as AssemblyDefinitionImporter; 104 | if (!importer) 105 | return; 106 | 107 | GUILayout.Space(-EditorGUIUtility.singleLineHeight); 108 | 109 | bool settingChanged = false; 110 | Settings setting = Settings.CreateFromJson(importer.userData); 111 | using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false))) 112 | { 113 | GUILayout.Space(30); 114 | 115 | // Open settings. 116 | using (var ccs = new EditorGUI.ChangeCheckScope()) 117 | { 118 | s_OpenSettings = GUILayout.Toggle(s_OpenSettings, s_SettingsText, EditorStyles.miniButtonLeft, GUILayout.ExpandWidth(false)); 119 | if (ccs.changed) 120 | EditorPrefs.SetBool("Coffee.AsmdefEx.InspectorGUI_OpenSettings", s_OpenSettings); 121 | } 122 | 123 | // Open help. 124 | if (GUILayout.Button(s_HelpText, EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false))) 125 | { 126 | Application.OpenURL("https://github.com/mob-sakai/OpenSesameCompilerForUnity"); 127 | } 128 | } 129 | 130 | if (s_OpenSettings) 131 | { 132 | GUILayout.BeginVertical(EditorStyles.helpBox); 133 | 134 | // Enable. 135 | bool enabled = GetExtensionEnabled(importer.assetPath); 136 | using (var ccs = new EditorGUI.ChangeCheckScope()) 137 | { 138 | enabled = EditorGUILayout.ToggleLeft(s_EnableText, enabled); 139 | if (GetAssemblyName(importer.assetPath) != "Coffee.AsmdefEx" && ccs.changed) 140 | { 141 | EditorApplication.delayCall += () => SetExtensionEnabled(importer.assetPath, enabled); 142 | } 143 | } 144 | 145 | // Ignore Accessibility Checks. 146 | using (new EditorGUI.DisabledScope(!enabled)) 147 | using (var ccs = new EditorGUI.ChangeCheckScope()) 148 | { 149 | setting.IgnoreAccessChecks = EditorGUILayout.ToggleLeft(s_IgnoreAccessCheckText, setting.IgnoreAccessChecks); 150 | settingChanged |= ccs.changed; 151 | } 152 | 153 | // Modify symbols. 154 | using (new EditorGUI.DisabledScope(!enabled)) 155 | using (var ccs = new EditorGUI.ChangeCheckScope()) 156 | { 157 | setting.ModifySymbols = EditorGUILayout.DelayedTextField(s_ModifySymbolsText, setting.ModifySymbols); 158 | settingChanged |= ccs.changed; 159 | } 160 | 161 | GUILayout.Space(10); 162 | using (new GUILayout.VerticalScope(EditorStyles.helpBox)) 163 | { 164 | // Reload AsmdefEx.cs for this assembly. 165 | using (new EditorGUI.DisabledScope(!enabled)) 166 | { 167 | if (GUILayout.Button(s_ReloadText, EditorStyles.miniButton)) 168 | { 169 | EditorApplication.delayCall += () => SetExtensionEnabled(importer.assetPath, true); 170 | } 171 | } 172 | 173 | // Publish assembly as a dll. 174 | if (GUILayout.Button(s_PublishText, EditorStyles.miniButton)) 175 | { 176 | s_AssemblyNameToPublish = GetAssemblyName(importer.assetPath); 177 | Core.LogEx("Request to publish the assembly as dll: " + s_AssemblyNameToPublish); 178 | settingChanged = true; 179 | } 180 | } 181 | 182 | GUILayout.EndVertical(); 183 | } 184 | 185 | if (settingChanged) 186 | { 187 | importer.userData = setting.ToJson(); 188 | importer.SaveAndReimport(); 189 | } 190 | } 191 | 192 | static bool GetExtensionEnabled(string asmdefPath) 193 | { 194 | bool enabled; 195 | if (!s_EnableAsmdefs.TryGetValue(asmdefPath, out enabled)) 196 | { 197 | string dst = Path.GetDirectoryName(asmdefPath) + "/AsmdefEx.cs"; 198 | enabled = File.Exists(dst); 199 | s_EnableAsmdefs[asmdefPath] = enabled; 200 | } 201 | 202 | return enabled; 203 | } 204 | 205 | static void SetExtensionEnabled(string asmdefPath, bool enabled) 206 | { 207 | s_EnableAsmdefs[asmdefPath] = enabled; 208 | string dst = Path.GetDirectoryName(asmdefPath) + "/AsmdefEx.cs"; 209 | if (enabled) 210 | { 211 | string src = GenerateAsmdefEx(asmdefPath); 212 | 213 | // Already copied. 214 | if (File.Exists(dst)) 215 | { 216 | using (var md5 = MD5.Create()) 217 | using (var srcStream = File.OpenRead(src)) 218 | using (var dstStream = File.OpenRead(dst)) 219 | if (md5.ComputeHash(srcStream).SequenceEqual(md5.ComputeHash(dstStream))) 220 | return; 221 | } 222 | 223 | // Copy AsmdefEx.cs to assembly. 224 | File.Copy(src, dst, true); 225 | AssetDatabase.ImportAsset(dst); 226 | } 227 | else 228 | { 229 | // Delete AsmdefEx.cs from assembly. 230 | AssetDatabase.DeleteAsset(dst); 231 | } 232 | } 233 | 234 | static string GenerateAsmdefEx(string asmdefPath) 235 | { 236 | var source = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName("Coffee.AsmdefEx"); 237 | string src = Path.Combine(Path.GetDirectoryName(source), "AsmdefEx.cs"); 238 | 239 | var text = File.ReadAllText(src) 240 | .Replace( 241 | "namespace Coffee.AsmdefEx", 242 | "namespace __GENARATED_ASMDEF__." + GetAssemblyName(asmdefPath) 243 | ); 244 | 245 | var tmp = Path.GetTempFileName(); 246 | File.WriteAllText(tmp, text); 247 | 248 | return tmp; 249 | } 250 | 251 | static string GetAssemblyName(string asmdefPath = "") 252 | { 253 | var m = Regex.Match(File.ReadAllText(asmdefPath), "\"name\":\\s*\"([^\"]*)\""); 254 | return m.Success ? m.Groups[1].Value : ""; 255 | } 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /Editor/InspectorGUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c936c2801c1d846049c3ee988551170f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2019 mob-sakai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 06fbb8b0273704df2ac8ddc2671843ef 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Open Sesame Compiler For Unity 2 | === 3 | 4 | **:warning: NOTE: This project has been integrated into [CSharpCompilerSettingsForUnity](https://github.com/mob-sakai/CSharpCompilerSettingsForUnity). We are NOT continuing development in this repository. :warning:** 5 | 6 |



7 | 8 | A custom Roslyn compiler and editor extension to access internals/privates for Unity. 9 | In other words, you can access to **any internals/privates** in other assemblies, **without reflection**. 10 | 11 | Let's say, **"Open sesame!"** 12 | 13 | ![](https://user-images.githubusercontent.com/12690315/71837979-255d0880-30fb-11ea-99bc-3bb96b77cfa6.gif) 14 | 15 | ![](https://user-images.githubusercontent.com/12690315/70616819-a804bc00-1c52-11ea-8ea3-e24f94f6467d.gif) 16 | 17 | [![](https://img.shields.io/npm/v/com.coffee.open-sesame-compiler?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.coffee.open-sesame-compiler/) 18 | [![](https://img.shields.io/github/v/release/mob-sakai/OpenSesameCompilerForUnity?include_prereleases)](https://github.com/mob-sakai/OpenSesameCompilerForUnity/releases) 19 | [![](https://img.shields.io/github/release-date/mob-sakai/OpenSesameCompilerForUnity.svg)](https://github.com/mob-sakai/OpenSesameCompilerForUnity/releases) 20 | ![](https://img.shields.io/badge/unity-2018.3%20or%20later-green.svg) 21 | [![](https://img.shields.io/github/license/mob-sakai/OpenSesameCompilerForUnity.svg)](https://github.com/mob-sakai/OpenSesameCompilerForUnity/blob/upm/LICENSE.txt) 22 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com) 23 | [![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai) 24 | 25 | << [Description](#description) | [Installation](#installation) | [Usage](#usage) | [Contributing](#contributing) >> 26 | 27 | ### What's new? [See changelog ![](https://img.shields.io/github/release-date/mob-sakai/OpenSesameCompilerForUnity.svg?label=last%20updated)](https://github.com/mob-sakai/OpenSesameCompilerForUnity/blob/upm/CHANGELOG.md) 28 | ### Do you want to receive notifications for new releases? [Watch this repo ![](https://img.shields.io/github/watchers/mob-sakai/OpenSesameCompilerForUnity.svg?style=social&label=Watch)](https://github.com/mob-sakai/OpenSesameCompilerForUnity/subscription) 29 | ### Support me on GitHub! 30 | [![become_a_sponsor_on_github](https://user-images.githubusercontent.com/12690315/66942881-03686280-f085-11e9-9586-fc0b6011029f.png)](https://github.com/users/mob-sakai/sponsorship) 31 | 32 | 33 |



34 | ## Description 35 | 36 | > _Then Ali Baba climbed down and went to the door concealed among the bushes, and said, "Open, Sesame!" and it flew open._ 37 | 38 | This package allows to access to **any internals/privates** in other assemblies, **without reflection**. 39 | 40 | For details about `IgnoresAccessChecksToAttribute`, see 41 | [No InternalsVisibleTo, no problem – bypassing C# visibility rules with Roslyn](https://www.strathweb.com/2018/10/no-internalvisibleto-no-problem-bypassing-c-visibility-rules-with-roslyn/). 42 | 43 | 44 | #### Features 45 | 46 | * Easy to use 47 | * this package is out of the box. 48 | * Allow to access to any internal/private elements (types/members) in other assemblies, **without reflection** 49 | * Create instance 50 | * Get/set fields or properties 51 | * Call method 52 | * Create extension method that contains private access 53 | * etc. 54 | * Processes only `AssemblyDefinitionFile` you configured 55 | * Add/remove the scripting define symbols for each `AssemblyDefinitionFiles` 56 | * Support C#8 57 | * Support `.Net 3.5`, `.Net 4.x` and `.Net Standard 2.0` 58 | * `dotnet` is not required 59 | * Publish as dll 60 | * Published dll works **without this package**. 61 | * Portable mode 62 | * Without publishing, make the assembly available to access to internals/privates in other assemblies, even in projects that do not have this package installed. 63 | * The best option when distributing as a package. 64 | 65 | #### NOTE: Unsupported Features 66 | 67 | * Set/get value into readonly field 68 | * Use reflection 69 | * IDE support 70 | * Use [Csc-Manager](https://github.com/pCYSl5EDgo/Csc-Manager) to modify your [VisualStudio Code](https://code.visualstudio.com/download) and [C# extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp). 71 | * `csc-manager enable-vscode`: Show internals/privates in other assembly. 72 | * `csc-manager disable-vscode`: Hide them. 73 | 74 | 75 |



76 | ## Installation 77 | 78 | #### Requirement 79 | 80 | * Unity 2018.3 or later 81 | 82 | #### Using OpenUPM 83 | 84 | This package is available on [OpenUPM](https://openupm.com). 85 | You can install it via [openupm-cli](https://github.com/openupm/openupm-cli). 86 | ``` 87 | openupm add com.coffee.open-sesame-compiler 88 | ``` 89 | 90 | #### Using Git 91 | 92 | Find the `manifest.json` file in the `Packages` directory in your project and edit it to look like this: 93 | ```json 94 | { 95 | "dependencies": { 96 | "com.coffee.open-sesame-compiler": "https://github.com/mob-sakai/OpenSesameCompilerForUnity.git", 97 | ... 98 | }, 99 | } 100 | ``` 101 | To update the package, change suffix `#{version}` to the target version. 102 | 103 | * e.g. `"com.coffee.open-sesame-compiler": "https://github.com/mob-sakai/OpenSesameCompilerForUnity.git#1.0.0",` 104 | 105 | Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package. 106 | 107 | 108 | 109 |



110 | ## Usage 111 | 112 | 1. Select a `AssemblyDefinitionFile` in project view 113 | 2. Configure setting for the assembly in inspector view: 114 | ![](https://user-images.githubusercontent.com/12690315/73439891-bab68a00-4393-11ea-9928-a286c9c3e6e0.png) 115 | * **Open Sesame**: Use OpenSesameCompiler instead of default csc to compile this assembly. In other words, allow this assembly to access to internals/privates to other assemblies without reflection. 116 | * **Settings**: how/hide the detail settings for this assembly. 117 | * **Modify Symbols**: When compiling this assembly, add/remove semicolon separated symbols. Symbols starting with '!' will be removed. 118 | **NOTE: This feature is available even when 'Open Sesame' is disabled** 119 | * **Portable Mode**: Make this assembly available to access in internals/privates to other assemblies, even in projects that do not have `Open Sesame Compiler` package installed. 120 | * **Publish**: Publish this assembly as dll to the parent directory. 121 | * **Help**: Open help page on browser. 122 | 1. Enjoy! 123 | 124 | 125 | 126 |



127 | ## Demo 128 | 129 | 1. Clone demo branch in this repo and open it with Unity 2018.3 or later 130 | ``` 131 | git clone -b demo https://github.com/mob-sakai/OpenSesameCompilerForUnity.git 132 | ``` 133 | 2. The project has some inaccessible compilation errors 134 | ![](https://user-images.githubusercontent.com/12690315/71837690-6274cb00-30fa-11ea-949f-5f60b1a1dbcd.png) 135 | 3. Do not worry, they are proper errors. 136 | The demo project access to internals/privates: 137 | ```cs 138 | // EditorApplication.CallDelayed is an internal-static method in UnityEditor assembly. 139 | EditorApplication.CallDelayed(() => Debug.Log("delayed"), 1); 140 | ``` 141 | 4. Select `Assets/Tests/Coffee.OpenSesame.Test.asmdef` in project view and activate 'Open Sesame' in inspector view 142 | ![](https://user-images.githubusercontent.com/12690315/71837979-255d0880-30fb-11ea-99bc-3bb96b77cfa6.gif) 143 | 5. Run all edit mode tests in test runner view (`Windows > General > Test Runner`). 144 | The compilation error is gone, but some tests that depend on symbols will not pass. 145 | ![](https://user-images.githubusercontent.com/12690315/71838489-483bec80-30fc-11ea-9af4-83e2ddd7d894.png) 146 | ```cs 147 | [Test] 148 | public void DefineSymbols() 149 | { 150 | const string log = "OSC_TEST is defined."; 151 | LogAssert.Expect(LogType.Log, log); 152 | #if OSC_TEST // <- not defined! 153 | Debug.Log(log); 154 | #endif 155 | } 156 | 157 | [Test] 158 | public void RemoveSymbols() 159 | { 160 | const string log = "TRACE is not defined."; 161 | LogAssert.Expect(LogType.Log, log); 162 | #if !TRACE // <- defined automatically by Unity! 163 | Debug.Log(log); 164 | #endif 165 | } 166 | ``` 167 | 6. Enable `symbols` to modify scripting define symbols for this assembly. 168 | Then edit `Modify Symbols` to `OSC_TEST;!TRACE`. This means *"add `OSC_TEST` symbol and remove `TRACE` symbol for this assembly."* 169 | ![](https://user-images.githubusercontent.com/12690315/71839029-9a314200-30fd-11ea-8596-d1a6ea188741.png) 170 | 1. All tests pass! 171 | ![](https://user-images.githubusercontent.com/12690315/71839100-c2b93c00-30fd-11ea-86a7-a2f1aac0a4cc.png) 172 | 173 | For more details, see [the article 1 (Japanese)](https://qiita.com/mob-sakai/items/f3bbc0c45abc31ea7ac0) and [the article 2 (Japanese)](https://qiita.com/mob-sakai/items/a24780d68a6133be338f). 174 | 175 | 176 | 177 |



178 | ## Contributing 179 | 180 | ### Issues 181 | 182 | Issues are very valuable to this project. 183 | 184 | - Ideas are a valuable source of contributions others can make 185 | - Problems show where this project is lacking 186 | - With a question you show where contributors can improve the user experience 187 | 188 | ### Pull Requests 189 | 190 | Pull requests are, a great way to get your ideas into this repository. 191 | See [CONTRIBUTING.md](/../../blob/develop/CONTRIBUTING.md). 192 | 193 | ### Support 194 | 195 | This is an open source project that I am developing in my spare time. 196 | If you like it, please support me. 197 | With your support, I can spend more time on development. :) 198 | 199 | [![](https://user-images.githubusercontent.com/12690315/50731629-3b18b480-11ad-11e9-8fad-4b13f27969c1.png)](https://www.patreon.com/join/mob_sakai?) 200 | [![](https://user-images.githubusercontent.com/12690315/66942881-03686280-f085-11e9-9586-fc0b6011029f.png)](https://github.com/users/mob-sakai/sponsorship) 201 | 202 | 203 | 204 |



205 | ## License 206 | 207 | * MIT 208 | 209 | 210 | 211 | ## Author 212 | 213 | [mob-sakai](https://github.com/mob-sakai) 214 | [![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai) 215 | 216 | 217 | 218 | ## See Also 219 | 220 | * GitHub page : https://github.com/mob-sakai/OpenSesameCompilerForUnity 221 | * Releases : https://github.com/mob-sakai/OpenSesameCompilerForUnity/releases 222 | * Issue tracker : https://github.com/mob-sakai/OpenSesameCompilerForUnity/issues 223 | * Change log : https://github.com/mob-sakai/OpenSesameCompilerForUnity/blob/upm/CHANGELOG.md 224 | * [No InternalsVisibleTo, no problem – bypassing C# visibility rules with Roslyn](https://www.strathweb.com/2018/10/no-internalvisibleto-no-problem-bypassing-c-visibility-rules-with-roslyn/) 225 | * Nuget version: https://www.nuget.org/packages/OpenSesameCompiler 226 | * asmdefScriptingDefines([@pCYSl5EDgo](https://github.com/pCYSl5EDgo)) : https://github.com/pCYSl5EDgo/asmdefScriptingDefines 227 | * Csc-Manager([@pCYSl5EDgo](https://github.com/pCYSl5EDgo)) : https://github.com/pCYSl5EDgo/Csc-Manager 228 | 229 | 230 | ## Special Thanks 231 | 232 | * Special thanks to [@pCYSl5EDgo](https://github.com/pCYSl5EDgo), your ideas contributed to improve this package. 233 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 989779f9831f64c2fb9d0e39480b6ffa 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7eb1a6d5cb1d4b49b79c59fb7e651d60 3 | timeCreated: 1596029379 -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 53519a3bab5dd45f68665c8f5c55a776 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/AsmdefEx.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text.RegularExpressions; 10 | using UnityEditor; 11 | using UnityEngine; 12 | using UnityEditor.Compilation; 13 | 14 | namespace __GENARATED_ASMDEF__.Coffee.AsmdefEx.EditorTests 15 | { 16 | internal static class PackageSettings 17 | { 18 | public const string PackageId = "OpenSesame.Net.Compilers.3.4.0-beta.1"; 19 | } 20 | 21 | internal static class ReflectionExtensions 22 | { 23 | const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; 24 | 25 | static object Inst(this object self) 26 | { 27 | return (self is Type) ? null : self; 28 | } 29 | 30 | static Type Type(this object self) 31 | { 32 | return (self as Type) ?? self.GetType(); 33 | } 34 | 35 | public static object New(this Type self, params object[] args) 36 | { 37 | var types = args.Select(x => x.GetType()).ToArray(); 38 | return self.Type().GetConstructor(types) 39 | .Invoke(args); 40 | } 41 | 42 | public static object Call(this object self, string methodName, params object[] args) 43 | { 44 | var types = args.Select(x => x.GetType()).ToArray(); 45 | return self.Type().GetMethod(methodName, types) 46 | .Invoke(self.Inst(), args); 47 | } 48 | 49 | public static object Call(this object self, Type[] genericTypes, string methodName, params object[] args) 50 | { 51 | return self.Type().GetMethod(methodName, FLAGS) 52 | .MakeGenericMethod(genericTypes) 53 | .Invoke(self.Inst(), args); 54 | } 55 | 56 | public static object Get(this object self, string memberName, MemberInfo mi = null) 57 | { 58 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 59 | return mi is PropertyInfo 60 | ? (mi as PropertyInfo).GetValue(self.Inst(), new object[0]) 61 | : (mi as FieldInfo).GetValue(self.Inst()); 62 | } 63 | 64 | public static void Set(this object self, string memberName, object value, MemberInfo mi = null) 65 | { 66 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 67 | if (mi is PropertyInfo) 68 | (mi as PropertyInfo).SetValue(self.Inst(), value, new object[0]); 69 | else 70 | (mi as FieldInfo).SetValue(self.Inst(), value); 71 | } 72 | } 73 | 74 | internal class Settings 75 | { 76 | public bool IgnoreAccessChecks; 77 | public string ModifySymbols = ""; 78 | public string CustomCompiler = ""; 79 | 80 | public bool SholdChangeCompilerProcess 81 | { 82 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(ModifySymbols) || !string.IsNullOrEmpty(CustomCompiler); } 83 | } 84 | 85 | public bool UseCustomCompiler 86 | { 87 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(CustomCompiler); } 88 | } 89 | 90 | public static Settings GetAtPath(string path) 91 | { 92 | var setting = new Settings(); 93 | if (string.IsNullOrEmpty(path)) 94 | return setting; 95 | 96 | // If input path is directory, find asmdef file. 97 | if (Directory.Exists(path)) 98 | path = Directory.GetFiles(path, "*.asmdef") 99 | .Select(x => x.Replace(Environment.CurrentDirectory + Path.DirectorySeparatorChar, "")) 100 | .FirstOrDefault(); 101 | 102 | // Not find asmdef file. 103 | if (string.IsNullOrEmpty(path) || !File.Exists(path) || !File.Exists(path + ".meta")) 104 | return setting; 105 | 106 | try 107 | { 108 | var json = AssetImporter.GetAtPath(path).userData; 109 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 110 | } 111 | catch 112 | { 113 | } 114 | 115 | return setting; 116 | } 117 | 118 | public string ToJson() 119 | { 120 | return string.Format("{{" + 121 | "\"IgnoreAccessChecks\":{0}," + 122 | "\"ModifySymbols\":\"{1}\"," + 123 | "\"CustomCompiler\":\"{2}\"" + 124 | "}}", 125 | IgnoreAccessChecks ? "true" : "false", 126 | ModifySymbols ?? "", 127 | CustomCompiler ?? "" 128 | ); 129 | } 130 | 131 | public static Settings CreateFromJson(string json = "") 132 | { 133 | var setting = new Settings(); 134 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 135 | return setting; 136 | } 137 | 138 | static void GetSettingssFromJson(string json, out bool ignoreAccessChecks, out string modifySymbols, out string customCompiler) 139 | { 140 | ignoreAccessChecks = false; 141 | modifySymbols = ""; 142 | customCompiler = ""; 143 | if (string.IsNullOrEmpty(json)) 144 | return; 145 | 146 | ignoreAccessChecks = Regex.Match(json, "\"IgnoreAccessChecks\":\\s*(true|false)").Groups[1].Value == "true"; 147 | modifySymbols = Regex.Match(json, "\"ModifySymbols\":\\s*\"([^\"]*)\"").Groups[1].Value; 148 | customCompiler = Regex.Match(json, "\"CustomCompiler\":\\s*\"([^\"]*)\"").Groups[1].Value; 149 | } 150 | } 151 | 152 | internal static class CustomCompiler 153 | { 154 | static string s_InstallPath; 155 | const string k_LogHeader = "[CustomCompiler] "; 156 | 157 | static void Log(string format, params object[] args) 158 | { 159 | if (Core.LogEnabled) 160 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 161 | } 162 | 163 | public static string GetInstalledPath(string packageId = "") 164 | { 165 | if (!string.IsNullOrEmpty(s_InstallPath) && File.Exists(s_InstallPath)) 166 | return s_InstallPath; 167 | 168 | try 169 | { 170 | packageId = string.IsNullOrEmpty(packageId) ? PackageSettings.PackageId : packageId; 171 | s_InstallPath = Install(packageId); 172 | } 173 | catch (Exception ex) 174 | { 175 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + ex.Message, ex.InnerException)); 176 | } 177 | finally 178 | { 179 | EditorUtility.ClearProgressBar(); 180 | } 181 | 182 | return s_InstallPath; 183 | } 184 | 185 | static string Install(string packageId) 186 | { 187 | char sep = Path.DirectorySeparatorChar; 188 | string url = "https://globalcdn.nuget.org/packages/" + packageId.ToLower() + ".nupkg"; 189 | string downloadPath = ("Temp/" + Path.GetFileName(Path.GetTempFileName())).Replace('/', sep); 190 | string installPath = ("Library/" + packageId).Replace('/', sep); 191 | string cscToolExe = (installPath + "/tools/csc.exe").Replace('/', sep); 192 | 193 | // Custom compiler is already installed. 194 | if (File.Exists(cscToolExe)) 195 | { 196 | Log("Custom compiler '{0}' is already installed at {1}", packageId, cscToolExe); 197 | return cscToolExe; 198 | } 199 | 200 | if (Directory.Exists(installPath)) 201 | Directory.Delete(installPath, true); 202 | 203 | try 204 | { 205 | UnityEngine.Debug.LogFormat(k_LogHeader + "Install custom compiler '{0}'", packageId); 206 | 207 | // Download custom compiler package from nuget. 208 | { 209 | UnityEngine.Debug.LogFormat(k_LogHeader + "Download {0} from nuget: {1}", packageId, url); 210 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Download {0} from nuget", packageId), 0.2f); 211 | 212 | switch (Application.platform) 213 | { 214 | case RuntimePlatform.WindowsEditor: 215 | ExecuteCommand("PowerShell.exe", string.Format("curl -O {0} {1}", downloadPath, url)); 216 | break; 217 | case RuntimePlatform.OSXEditor: 218 | ExecuteCommand("curl", string.Format("-o {0} -L {1}", downloadPath, url)); 219 | break; 220 | case RuntimePlatform.LinuxEditor: 221 | ExecuteCommand("wget", string.Format("-O {0} {1}", downloadPath, url)); 222 | break; 223 | } 224 | } 225 | 226 | // Extract nuget package (unzip). 227 | { 228 | UnityEngine.Debug.LogFormat(k_LogHeader + "Extract {0} to {1} with 7z", downloadPath, installPath); 229 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Extract {0}", downloadPath), 0.4f); 230 | 231 | string appPath = EditorApplication.applicationContentsPath.Replace('/', sep); 232 | string args = string.Format("x {0} -o{1}", downloadPath, installPath); 233 | 234 | switch (Application.platform) 235 | { 236 | case RuntimePlatform.WindowsEditor: 237 | ExecuteCommand(appPath + "\\Tools\\7z.exe", args); 238 | break; 239 | case RuntimePlatform.OSXEditor: 240 | case RuntimePlatform.LinuxEditor: 241 | ExecuteCommand(appPath + "/Tools/7za", args); 242 | break; 243 | } 244 | } 245 | 246 | UnityEngine.Debug.LogFormat(k_LogHeader + "Custom compiler '{0}' has been installed in {1}.", packageId, installPath); 247 | } 248 | catch 249 | { 250 | throw new Exception(string.Format("Custom compiler '{0}' installation failed.", packageId)); 251 | } 252 | finally 253 | { 254 | EditorUtility.ClearProgressBar(); 255 | } 256 | 257 | if (File.Exists(cscToolExe)) 258 | return cscToolExe; 259 | 260 | throw new FileNotFoundException(string.Format("Custom compiler '{0}' is not found at {1}", packageId, cscToolExe)); 261 | } 262 | 263 | static void ExecuteCommand(string exe, string args) 264 | { 265 | UnityEngine.Debug.LogFormat(k_LogHeader + "Execute command: {0} {1}", exe, args); 266 | 267 | Process p = Process.Start(new ProcessStartInfo() 268 | { 269 | FileName = exe, 270 | Arguments = args, 271 | CreateNoWindow = true, 272 | UseShellExecute = false, 273 | RedirectStandardError = true, 274 | }); 275 | p.WaitForExit(); 276 | 277 | if (p.ExitCode != 0) 278 | { 279 | UnityEngine.Debug.LogErrorFormat(k_LogHeader + p.StandardError.ReadToEnd()); 280 | throw new Exception(); 281 | } 282 | } 283 | } 284 | 285 | [InitializeOnLoad] 286 | internal static class Core 287 | { 288 | public static bool LogEnabled { get; private set; } 289 | public static string k_LogHeader = "[AsmdefEx] "; 290 | 291 | static void Log(string format, params object[] args) 292 | { 293 | if (LogEnabled) 294 | LogEx(format, args); 295 | } 296 | 297 | public static void LogEx(string format, params object[] args) 298 | { 299 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 300 | } 301 | 302 | public static void Error(Exception e) 303 | { 304 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 305 | } 306 | 307 | public static object GetScriptAssembly(string assemblyName) 308 | { 309 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 310 | Type tCSharpLanguage = Type.GetType("UnityEditor.Scripting.Compilers.CSharpLanguage, UnityEditor"); 311 | return tEditorCompilationInterface.Call(new[] {tCSharpLanguage}, "GetScriptAssemblyForLanguage", assemblyName); 312 | } 313 | 314 | public static string[] ModifyDefines(IEnumerable defines, bool ignoreAccessChecks, string modifySymbols) 315 | { 316 | var symbols = modifySymbols.Split(';', ','); 317 | var add = symbols.Where(x => 0 < x.Length && !x.StartsWith("!")); 318 | var remove = symbols.Where(x => 1 < x.Length && x.StartsWith("!")).Select(x => x.Substring(1)); 319 | return defines 320 | .Union(add ?? Enumerable.Empty()) 321 | .Except(remove ?? Enumerable.Empty()) 322 | .Union(ignoreAccessChecks ? new[] {"IGNORE_ACCESS_CHECKS"} : Enumerable.Empty()) 323 | .Union(new[] {"ASMDEF_EX"}) 324 | .Distinct() 325 | .ToArray(); 326 | } 327 | 328 | public static void ModifyFiles(IEnumerable files, bool ignoreAccessChecks) 329 | { 330 | const string s_If = "#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 331 | const string s_EndIf = "#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 332 | 333 | // Add #if and #endif to all source files. 334 | foreach (var file in files) 335 | { 336 | var text = File.ReadAllText(file); 337 | Log("ModifyFiles: {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 338 | if (text.Contains(s_If) == ignoreAccessChecks) 339 | continue; 340 | 341 | var m = Regex.Match(text, "[\r\n]+"); 342 | if (!m.Success) 343 | continue; 344 | 345 | var nl = m.Value; 346 | if (ignoreAccessChecks) 347 | { 348 | text = s_If + nl + text + nl + s_EndIf; 349 | } 350 | else 351 | { 352 | text = text.Replace(s_If + nl, ""); 353 | text = text.Replace(nl + s_EndIf, ""); 354 | } 355 | 356 | Log("ModifyFiles: Write {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 357 | File.WriteAllText(file, text); 358 | } 359 | } 360 | 361 | public static void ChangeCompilerProcess(object compiler, Settings setting) 362 | { 363 | Type tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor"); 364 | Type tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor"); 365 | FieldInfo fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance); 366 | 367 | Log("Kill previous compiler process"); 368 | var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo; 369 | compiler.Call("Dispose"); 370 | 371 | // Convert response file for Mono to .Net. 372 | // - Add preferreduilang option (en-US) 373 | // - Change language version to 'latest' 374 | // - Change 'debug' to 'debug:portable' 375 | // - Change compiler switch prefix '-' to '/' 376 | string responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1"); 377 | bool isMono = compiler.GetType().Name == "MonoCSharpCompiler"; 378 | var text = File.ReadAllText(responseFile); 379 | text = Regex.Replace(text, "[\r\n]+", "\n"); 380 | text = Regex.Replace(text, "^-", "/", RegexOptions.Multiline); 381 | 382 | // Modify scripting define symbols. 383 | { 384 | Log("Modify scripting define symbols: {0}", responseFile); 385 | var defines = Regex.Matches(text, "^/define:(.*)$", RegexOptions.Multiline) 386 | .Cast() 387 | .Select(x => x.Groups[1].Value); 388 | 389 | text = Regex.Replace(text, "[\r\n]+/define:[^\r\n]+", ""); 390 | foreach (var d in ModifyDefines(defines, setting.IgnoreAccessChecks, setting.ModifySymbols)) 391 | { 392 | text += "\n/define:" + d; 393 | } 394 | } 395 | 396 | // Add/remove '#if IGNORE_ACCESS_CHECKS' and '#endif' preprocessor. 397 | var files = Regex.Matches(text, "^\"(.*)\"$", RegexOptions.Multiline) 398 | .Cast() 399 | .Select(x => x.Groups[1].Value) 400 | .Where(x => Path.GetExtension(x) == ".cs") 401 | .Where(x => Path.GetFileName(x) != "AsmdefEx.cs"); 402 | ModifyFiles(files, setting.IgnoreAccessChecks); 403 | 404 | // To access to non-publics in other assemblies, use custom compiler instead of default csc. 405 | if (setting.UseCustomCompiler) 406 | { 407 | text = Regex.Replace(text, "^/langversion:\\d+$", "/langversion:latest", RegexOptions.Multiline); 408 | text = Regex.Replace(text, "^/debug$", "/debug:portable", RegexOptions.Multiline); 409 | text += "\n/preferreduilang:en-US"; 410 | 411 | // Change exe file path. 412 | var cscToolExe = CustomCompiler.GetInstalledPath(setting.CustomCompiler); 413 | Log("Change csc tool exe to {0}", cscToolExe); 414 | if (Application.platform == RuntimePlatform.WindowsEditor) 415 | { 416 | psi.FileName = Path.GetFullPath(cscToolExe); 417 | psi.Arguments = "/shared /noconfig @" + responseFile; 418 | } 419 | else 420 | { 421 | psi.FileName = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/bin/mono"); 422 | psi.Arguments = cscToolExe + " /noconfig @" + responseFile; 423 | } 424 | } 425 | // Revert prefix symbols for mono compiler 426 | else if (isMono) 427 | { 428 | text = Regex.Replace(text, "^/", "-", RegexOptions.Multiline); 429 | } 430 | 431 | text = Regex.Replace(text, "\n", System.Environment.NewLine); 432 | File.WriteAllText(responseFile, text); 433 | 434 | Log("Restart compiler process: {0} {1}", psi.FileName, psi.Arguments); 435 | var program = tProgram.New(psi); 436 | program.Call("Start"); 437 | compiler.Set("process", program, fiProcess); 438 | } 439 | 440 | static void OnAssemblyCompilationStarted(string name) 441 | { 442 | try 443 | { 444 | string assemblyName = Path.GetFileNameWithoutExtension(name); 445 | string assemblyFilename = assemblyName + ".dll"; 446 | 447 | if (assemblyName != typeof(Core).Assembly.GetName().Name) 448 | return; 449 | 450 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 451 | var compilerTasks = tEditorCompilationInterface.Get("Instance").Get("compilationTask").Get("compilerTasks") as IDictionary; 452 | var scriptAssembly = compilerTasks.Keys.Cast().FirstOrDefault(x => (x.Get("Filename") as string) == assemblyFilename); 453 | 454 | // Should change compiler process for the assembly? 455 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 456 | var setting = Settings.GetAtPath(asmdefPath); 457 | if (!setting.SholdChangeCompilerProcess) 458 | return; 459 | 460 | // Create new compiler to recompile. 461 | Log("Assembly compilation started: {0} should be recompiled.", assemblyName); 462 | Core.ChangeCompilerProcess(compilerTasks[scriptAssembly], setting); 463 | } 464 | catch (Exception e) 465 | { 466 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 467 | } 468 | } 469 | 470 | static Core() 471 | { 472 | var assemblyName = typeof(Core).Assembly.GetName().Name; 473 | if (assemblyName == "Coffee.AsmdefEx") 474 | return; 475 | 476 | k_LogHeader = string.Format("[AsmdefEx ({0})] ", assemblyName); 477 | LogEnabled = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup) 478 | .Split(';', ',') 479 | .Any(x => x == "ASMDEF_EX_LOG"); 480 | 481 | Log("Start watching assembly '{0}' compilation.", typeof(Core).Assembly.GetName().Name); 482 | CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted; 483 | } 484 | } 485 | 486 | #if !ASMDEF_EX 487 | [InitializeOnLoad] 488 | internal class RecompileRequest 489 | { 490 | static RecompileRequest() 491 | { 492 | var assemblyName = typeof(RecompileRequest).Assembly.GetName().Name; 493 | if (assemblyName == "Coffee.AsmdefEx") 494 | return; 495 | 496 | // Should change compiler process for the assembly? 497 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 498 | var setting = Settings.GetAtPath(asmdefPath); 499 | if (!setting.SholdChangeCompilerProcess) 500 | return; 501 | 502 | if (Core.LogEnabled) 503 | UnityEngine.Debug.LogFormat("Request to recompile: {0} ({1})", assemblyName, asmdefPath); 504 | 505 | AssetDatabase.ImportAsset(asmdefPath); 506 | } 507 | } 508 | #endif 509 | } 510 | #endif 511 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/AsmdefEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf5c1c2ac214b4e00a9cb7ab22eaaa8e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/Coffee.AsmdefEx.EditorTests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Coffee.AsmdefEx.EditorTests", 3 | "references": [ 4 | "Coffee.AsmdefEx" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [ 10 | "Editor" 11 | ], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false, 14 | "overrideReferences": false, 15 | "precompiledReferences": [], 16 | "autoReferenced": false, 17 | "defineConstraints": [] 18 | } -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/Coffee.AsmdefEx.EditorTests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 087f873df2793447b9268d981f31422b 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: '{"IgnoreAccessChecks":true,"ModifySymbols":"OSC_TEST;!UNITY_5_3_OR_NEWER","CustomCompiler":""}' 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/EditorTests.cs: -------------------------------------------------------------------------------- 1 | #if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using NUnit.Framework; 6 | using UnityEditor.Scripting.ScriptCompilation; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using UnityEngine.TestTools; 10 | 11 | namespace Coffee.AsmdefEx.EditorTests 12 | { 13 | #if UNITY_EDITOR 14 | class ScriptDefineSymbolTest 15 | { 16 | [Test] 17 | public void DefineSymbols() 18 | { 19 | #if OSC_TEST 20 | string log = "OSC_TEST is defined."; 21 | #else 22 | string log = "OSC_TEST is not defined."; 23 | #endif 24 | Assert.AreEqual(log, "OSC_TEST is defined."); 25 | } 26 | 27 | [Test] 28 | public void RemoveSymbols() 29 | { 30 | #if UNITY_5_3_OR_NEWER 31 | string log = "UNITY_5_3_OR_NEWER is defined."; 32 | #else 33 | string log = "UNITY_5_3_OR_NEWER is not defined."; 34 | #endif 35 | Assert.AreEqual(log, "UNITY_5_3_OR_NEWER is not defined."); 36 | } 37 | } 38 | 39 | class UnityEditorTest 40 | { 41 | // [UnityTest] 42 | // public IEnumerator InternalMethod() 43 | // { 44 | // LogAssert.Expect(LogType.Log, "delayed"); 45 | // EditorApplication.CallDelayed(() => Debug.Log("delayed"), 1); 46 | // yield return null; 47 | 48 | // float startTime = Time.realtimeSinceStartup; 49 | // while ((Time.realtimeSinceStartup - startTime) < 1.1f) 50 | // { 51 | // yield return null; 52 | // } 53 | // } 54 | 55 | [Test] 56 | public void PrivateCreateInstance() 57 | { 58 | var tracker = new EditorGUIUtility.EditorLockTracker(); 59 | Assert.IsNotNull(tracker); 60 | } 61 | 62 | 63 | [Test] 64 | public void PrivateField() 65 | { 66 | var tracker = new EditorGUIUtility.EditorLockTracker(); 67 | tracker.m_IsLocked = true; 68 | Assert.AreEqual(tracker.isLocked, true); 69 | } 70 | 71 | [Test] 72 | public void PrivateProperty() 73 | { 74 | var tracker = new EditorGUIUtility.EditorLockTracker(); 75 | tracker.isLocked = true; 76 | Assert.AreEqual(tracker.isLocked, true); 77 | } 78 | 79 | [Test] 80 | public void PrivateEvent() 81 | { 82 | var tracker = new EditorGUIUtility.EditorLockTracker(); 83 | tracker.lockStateChanged.AddListener(locked => { Debug.Log($"locked: {locked}"); }); 84 | LogAssert.Expect(LogType.Log, "locked: True"); 85 | tracker.isLocked = true; 86 | } 87 | 88 | [Test] 89 | public void PrivateConstant() 90 | { 91 | Assert.AreEqual(EditorGUIUtility.EditorLockTracker.k_LockMenuText, "Lock"); 92 | } 93 | 94 | [Test] 95 | public void GenericAdd() 96 | { 97 | var list = new List(); 98 | list.Add(new EditorGUIUtility.EditorLockTracker()); 99 | 100 | Assert.AreEqual(list.Count, 1); 101 | } 102 | } 103 | #endif 104 | 105 | class ScriptAssemblyTests 106 | { 107 | [Test] 108 | public void GetScriptAssembly() 109 | { 110 | var assemblyName = typeof(ScriptAssemblyTests).Assembly.GetName().Name; 111 | ScriptAssembly assembly = Core.GetScriptAssembly(assemblyName) as ScriptAssembly; 112 | Assert.IsNotNull(assembly); 113 | Assert.AreEqual(assembly.Filename, $"{assemblyName}.dll"); 114 | } 115 | } 116 | 117 | class SymbolTests 118 | { 119 | [Test] 120 | public void IgnoreAccessChecksSymbol() 121 | { 122 | var defines = new[] {"SYM_A", "SYM_B", "SYM_C"}; 123 | var modified = Core.ModifyDefines(defines, true, ""); 124 | var expected = defines.Union(new[] {"IGNORE_ACCESS_CHECKS", "ASMDEF_EX"}); 125 | 126 | CollectionAssert.AreEqual(expected, modified); 127 | } 128 | 129 | [Test] 130 | public void AddSymbols() 131 | { 132 | var defines = new[] {"SYM_A", "SYM_B", "SYM_C"}; 133 | var modified = Core.ModifyDefines(defines, true, "SYM_ADD1;SYM_ADD2"); 134 | var expected = new[] {"SYM_A", "SYM_B", "SYM_C", "SYM_ADD1", "SYM_ADD2", "IGNORE_ACCESS_CHECKS", "ASMDEF_EX"}; 135 | 136 | CollectionAssert.AreEqual(expected, modified); 137 | } 138 | 139 | [Test] 140 | public void SubSymbols() 141 | { 142 | var defines = new[] {"SYM_A", "SYM_B", "SYM_C"}; 143 | var modified = Core.ModifyDefines(defines, false, "!SYM_B"); 144 | var expected = new[] {"SYM_A", "SYM_C", "ASMDEF_EX"}; 145 | 146 | CollectionAssert.AreEqual(expected, modified); 147 | } 148 | 149 | [Test] 150 | public void ModifySymbols() 151 | { 152 | var defines = new[] {"SYM_A", "SYM_B", "SYM_C"}; 153 | var modified = Core.ModifyDefines(defines, true, "SYM_ADD1;!SYM_B"); 154 | var expected = new[] {"SYM_A", "SYM_C", "SYM_ADD1", "IGNORE_ACCESS_CHECKS", "ASMDEF_EX"}; 155 | 156 | CollectionAssert.AreEqual(expected, modified); 157 | } 158 | } 159 | } 160 | #endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 161 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/EditorTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dceb7e6b190a74c8281f922287974ac4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/Menus.cs: -------------------------------------------------------------------------------- 1 | #if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 2 | using System.IO; 3 | using System.Linq; 4 | using UnityEditor; 5 | using UnityEditor.Compilation; 6 | 7 | namespace Coffee.AsmdefEx 8 | { 9 | internal class Menus : AssetPostprocessor 10 | { 11 | const string kEnableLoggingText = "Asmdef Ex/Enable Logging"; 12 | const string kEnableLoggingSymbol = "ASMDEF_EX_LOG"; 13 | const string kDeleteCompilerText = "Asmdef Ex/Delete Compiler"; 14 | const string kReloadText = "Asmdef Ex/Reload AsmdefEx.cs For Tests"; 15 | 16 | void OnPreprocessAsset() 17 | { 18 | // When AsmdefEx.cs is changed, sync the AsmdefEx.cs in tests. 19 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName("Coffee.AsmdefEx"); 20 | var sourcePath = Path.GetDirectoryName(asmdefPath).Replace('\\', '/') + "/AsmdefEx.cs"; 21 | 22 | if (sourcePath != assetImporter.assetPath) return; 23 | 24 | Menus.ReloadTests(); 25 | } 26 | 27 | [MenuItem(kEnableLoggingText, false)] 28 | static void EnableLogging() 29 | { 30 | SwitchSymbol(kEnableLoggingSymbol); 31 | } 32 | 33 | [MenuItem(kEnableLoggingText, true)] 34 | static bool EnableLogging_Valid() 35 | { 36 | Menu.SetChecked(kEnableLoggingText, HasSymbol(kEnableLoggingSymbol)); 37 | return true; 38 | } 39 | 40 | [MenuItem(kDeleteCompilerText, false)] 41 | static void DeleteCompiler() 42 | { 43 | var path = CustomCompiler.GetInstalledPath(); 44 | if (!string.IsNullOrEmpty(path)) 45 | FileUtil.DeleteFileOrDirectory(path); 46 | } 47 | 48 | [MenuItem(kReloadText, false)] 49 | public static void ReloadTests() 50 | { 51 | var editorTests = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName("Coffee.AsmdefEx.EditorTests"); 52 | Coffee.AsmdefEx.InspectorGUI.SetExtensionEnabled(editorTests, true); 53 | var runtimeTests = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName("Coffee.AsmdefEx.RuntimeTests"); 54 | Coffee.AsmdefEx.InspectorGUI.SetExtensionEnabled(runtimeTests, true); 55 | } 56 | 57 | static string[] GetSymbols() 58 | { 59 | return PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(';', ','); 60 | } 61 | 62 | static void SetSymbols(string[] symbols) 63 | { 64 | PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(";", symbols)); 65 | } 66 | 67 | static bool HasSymbol(string symbol) 68 | { 69 | return GetSymbols().Any(x => x == symbol); 70 | } 71 | 72 | static void SwitchSymbol(string symbol) 73 | { 74 | var symbols = GetSymbols(); 75 | SetSymbols(symbols.Any(x => x == symbol) 76 | ? symbols.Where(x => x != symbol).ToArray() 77 | : symbols.Concat(new[] {symbol}).ToArray() 78 | ); 79 | } 80 | } 81 | } 82 | #endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 83 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.EditorTests/Menus.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 807594eed5bc14f42b0011b8220f9e2f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4275198404f5d4e598c3e9c6a35c4105 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/AsmdefEx.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text.RegularExpressions; 10 | using UnityEditor; 11 | using UnityEngine; 12 | using UnityEditor.Compilation; 13 | 14 | namespace __GENARATED_ASMDEF__.Coffee.AsmdefEx.RuntimeTests 15 | { 16 | internal static class PackageSettings 17 | { 18 | public const string PackageId = "OpenSesame.Net.Compilers.3.4.0-beta.1"; 19 | } 20 | 21 | internal static class ReflectionExtensions 22 | { 23 | const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; 24 | 25 | static object Inst(this object self) 26 | { 27 | return (self is Type) ? null : self; 28 | } 29 | 30 | static Type Type(this object self) 31 | { 32 | return (self as Type) ?? self.GetType(); 33 | } 34 | 35 | public static object New(this Type self, params object[] args) 36 | { 37 | var types = args.Select(x => x.GetType()).ToArray(); 38 | return self.Type().GetConstructor(types) 39 | .Invoke(args); 40 | } 41 | 42 | public static object Call(this object self, string methodName, params object[] args) 43 | { 44 | var types = args.Select(x => x.GetType()).ToArray(); 45 | return self.Type().GetMethod(methodName, types) 46 | .Invoke(self.Inst(), args); 47 | } 48 | 49 | public static object Call(this object self, Type[] genericTypes, string methodName, params object[] args) 50 | { 51 | return self.Type().GetMethod(methodName, FLAGS) 52 | .MakeGenericMethod(genericTypes) 53 | .Invoke(self.Inst(), args); 54 | } 55 | 56 | public static object Get(this object self, string memberName, MemberInfo mi = null) 57 | { 58 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 59 | return mi is PropertyInfo 60 | ? (mi as PropertyInfo).GetValue(self.Inst(), new object[0]) 61 | : (mi as FieldInfo).GetValue(self.Inst()); 62 | } 63 | 64 | public static void Set(this object self, string memberName, object value, MemberInfo mi = null) 65 | { 66 | mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0]; 67 | if (mi is PropertyInfo) 68 | (mi as PropertyInfo).SetValue(self.Inst(), value, new object[0]); 69 | else 70 | (mi as FieldInfo).SetValue(self.Inst(), value); 71 | } 72 | } 73 | 74 | internal class Settings 75 | { 76 | public bool IgnoreAccessChecks; 77 | public string ModifySymbols = ""; 78 | public string CustomCompiler = ""; 79 | 80 | public bool SholdChangeCompilerProcess 81 | { 82 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(ModifySymbols) || !string.IsNullOrEmpty(CustomCompiler); } 83 | } 84 | 85 | public bool UseCustomCompiler 86 | { 87 | get { return IgnoreAccessChecks || !string.IsNullOrEmpty(CustomCompiler); } 88 | } 89 | 90 | public static Settings GetAtPath(string path) 91 | { 92 | var setting = new Settings(); 93 | if (string.IsNullOrEmpty(path)) 94 | return setting; 95 | 96 | // If input path is directory, find asmdef file. 97 | if (Directory.Exists(path)) 98 | path = Directory.GetFiles(path, "*.asmdef") 99 | .Select(x => x.Replace(Environment.CurrentDirectory + Path.DirectorySeparatorChar, "")) 100 | .FirstOrDefault(); 101 | 102 | // Not find asmdef file. 103 | if (string.IsNullOrEmpty(path) || !File.Exists(path) || !File.Exists(path + ".meta")) 104 | return setting; 105 | 106 | try 107 | { 108 | var json = AssetImporter.GetAtPath(path).userData; 109 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 110 | } 111 | catch 112 | { 113 | } 114 | 115 | return setting; 116 | } 117 | 118 | public string ToJson() 119 | { 120 | return string.Format("{{" + 121 | "\"IgnoreAccessChecks\":{0}," + 122 | "\"ModifySymbols\":\"{1}\"," + 123 | "\"CustomCompiler\":\"{2}\"" + 124 | "}}", 125 | IgnoreAccessChecks ? "true" : "false", 126 | ModifySymbols ?? "", 127 | CustomCompiler ?? "" 128 | ); 129 | } 130 | 131 | public static Settings CreateFromJson(string json = "") 132 | { 133 | var setting = new Settings(); 134 | GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler); 135 | return setting; 136 | } 137 | 138 | static void GetSettingssFromJson(string json, out bool ignoreAccessChecks, out string modifySymbols, out string customCompiler) 139 | { 140 | ignoreAccessChecks = false; 141 | modifySymbols = ""; 142 | customCompiler = ""; 143 | if (string.IsNullOrEmpty(json)) 144 | return; 145 | 146 | ignoreAccessChecks = Regex.Match(json, "\"IgnoreAccessChecks\":\\s*(true|false)").Groups[1].Value == "true"; 147 | modifySymbols = Regex.Match(json, "\"ModifySymbols\":\\s*\"([^\"]*)\"").Groups[1].Value; 148 | customCompiler = Regex.Match(json, "\"CustomCompiler\":\\s*\"([^\"]*)\"").Groups[1].Value; 149 | } 150 | } 151 | 152 | internal static class CustomCompiler 153 | { 154 | static string s_InstallPath; 155 | const string k_LogHeader = "[CustomCompiler] "; 156 | 157 | static void Log(string format, params object[] args) 158 | { 159 | if (Core.LogEnabled) 160 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 161 | } 162 | 163 | public static string GetInstalledPath(string packageId = "") 164 | { 165 | if (!string.IsNullOrEmpty(s_InstallPath) && File.Exists(s_InstallPath)) 166 | return s_InstallPath; 167 | 168 | try 169 | { 170 | packageId = string.IsNullOrEmpty(packageId) ? PackageSettings.PackageId : packageId; 171 | s_InstallPath = Install(packageId); 172 | } 173 | catch (Exception ex) 174 | { 175 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + ex.Message, ex.InnerException)); 176 | } 177 | finally 178 | { 179 | EditorUtility.ClearProgressBar(); 180 | } 181 | 182 | return s_InstallPath; 183 | } 184 | 185 | static string Install(string packageId) 186 | { 187 | char sep = Path.DirectorySeparatorChar; 188 | string url = "https://globalcdn.nuget.org/packages/" + packageId.ToLower() + ".nupkg"; 189 | string downloadPath = ("Temp/" + Path.GetFileName(Path.GetTempFileName())).Replace('/', sep); 190 | string installPath = ("Library/" + packageId).Replace('/', sep); 191 | string cscToolExe = (installPath + "/tools/csc.exe").Replace('/', sep); 192 | 193 | // Custom compiler is already installed. 194 | if (File.Exists(cscToolExe)) 195 | { 196 | Log("Custom compiler '{0}' is already installed at {1}", packageId, cscToolExe); 197 | return cscToolExe; 198 | } 199 | 200 | if (Directory.Exists(installPath)) 201 | Directory.Delete(installPath, true); 202 | 203 | try 204 | { 205 | UnityEngine.Debug.LogFormat(k_LogHeader + "Install custom compiler '{0}'", packageId); 206 | 207 | // Download custom compiler package from nuget. 208 | { 209 | UnityEngine.Debug.LogFormat(k_LogHeader + "Download {0} from nuget: {1}", packageId, url); 210 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Download {0} from nuget", packageId), 0.2f); 211 | 212 | switch (Application.platform) 213 | { 214 | case RuntimePlatform.WindowsEditor: 215 | ExecuteCommand("PowerShell.exe", string.Format("curl -O {0} {1}", downloadPath, url)); 216 | break; 217 | case RuntimePlatform.OSXEditor: 218 | ExecuteCommand("curl", string.Format("-o {0} -L {1}", downloadPath, url)); 219 | break; 220 | case RuntimePlatform.LinuxEditor: 221 | ExecuteCommand("wget", string.Format("-O {0} {1}", downloadPath, url)); 222 | break; 223 | } 224 | } 225 | 226 | // Extract nuget package (unzip). 227 | { 228 | UnityEngine.Debug.LogFormat(k_LogHeader + "Extract {0} to {1} with 7z", downloadPath, installPath); 229 | EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Extract {0}", downloadPath), 0.4f); 230 | 231 | string appPath = EditorApplication.applicationContentsPath.Replace('/', sep); 232 | string args = string.Format("x {0} -o{1}", downloadPath, installPath); 233 | 234 | switch (Application.platform) 235 | { 236 | case RuntimePlatform.WindowsEditor: 237 | ExecuteCommand(appPath + "\\Tools\\7z.exe", args); 238 | break; 239 | case RuntimePlatform.OSXEditor: 240 | case RuntimePlatform.LinuxEditor: 241 | ExecuteCommand(appPath + "/Tools/7za", args); 242 | break; 243 | } 244 | } 245 | 246 | UnityEngine.Debug.LogFormat(k_LogHeader + "Custom compiler '{0}' has been installed in {1}.", packageId, installPath); 247 | } 248 | catch 249 | { 250 | throw new Exception(string.Format("Custom compiler '{0}' installation failed.", packageId)); 251 | } 252 | finally 253 | { 254 | EditorUtility.ClearProgressBar(); 255 | } 256 | 257 | if (File.Exists(cscToolExe)) 258 | return cscToolExe; 259 | 260 | throw new FileNotFoundException(string.Format("Custom compiler '{0}' is not found at {1}", packageId, cscToolExe)); 261 | } 262 | 263 | static void ExecuteCommand(string exe, string args) 264 | { 265 | UnityEngine.Debug.LogFormat(k_LogHeader + "Execute command: {0} {1}", exe, args); 266 | 267 | Process p = Process.Start(new ProcessStartInfo() 268 | { 269 | FileName = exe, 270 | Arguments = args, 271 | CreateNoWindow = true, 272 | UseShellExecute = false, 273 | RedirectStandardError = true, 274 | }); 275 | p.WaitForExit(); 276 | 277 | if (p.ExitCode != 0) 278 | { 279 | UnityEngine.Debug.LogErrorFormat(k_LogHeader + p.StandardError.ReadToEnd()); 280 | throw new Exception(); 281 | } 282 | } 283 | } 284 | 285 | [InitializeOnLoad] 286 | internal static class Core 287 | { 288 | public static bool LogEnabled { get; private set; } 289 | public static string k_LogHeader = "[AsmdefEx] "; 290 | 291 | static void Log(string format, params object[] args) 292 | { 293 | if (LogEnabled) 294 | LogEx(format, args); 295 | } 296 | 297 | public static void LogEx(string format, params object[] args) 298 | { 299 | UnityEngine.Debug.LogFormat(k_LogHeader + format, args); 300 | } 301 | 302 | public static void Error(Exception e) 303 | { 304 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 305 | } 306 | 307 | public static object GetScriptAssembly(string assemblyName) 308 | { 309 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 310 | Type tCSharpLanguage = Type.GetType("UnityEditor.Scripting.Compilers.CSharpLanguage, UnityEditor"); 311 | return tEditorCompilationInterface.Call(new[] {tCSharpLanguage}, "GetScriptAssemblyForLanguage", assemblyName); 312 | } 313 | 314 | public static string[] ModifyDefines(IEnumerable defines, bool ignoreAccessChecks, string modifySymbols) 315 | { 316 | var symbols = modifySymbols.Split(';', ','); 317 | var add = symbols.Where(x => 0 < x.Length && !x.StartsWith("!")); 318 | var remove = symbols.Where(x => 1 < x.Length && x.StartsWith("!")).Select(x => x.Substring(1)); 319 | return defines 320 | .Union(add ?? Enumerable.Empty()) 321 | .Except(remove ?? Enumerable.Empty()) 322 | .Union(ignoreAccessChecks ? new[] {"IGNORE_ACCESS_CHECKS"} : Enumerable.Empty()) 323 | .Union(new[] {"ASMDEF_EX"}) 324 | .Distinct() 325 | .ToArray(); 326 | } 327 | 328 | public static void ModifyFiles(IEnumerable files, bool ignoreAccessChecks) 329 | { 330 | const string s_If = "#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 331 | const string s_EndIf = "#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY."; 332 | 333 | // Add #if and #endif to all source files. 334 | foreach (var file in files) 335 | { 336 | var text = File.ReadAllText(file); 337 | Log("ModifyFiles: {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 338 | if (text.Contains(s_If) == ignoreAccessChecks) 339 | continue; 340 | 341 | var m = Regex.Match(text, "[\r\n]+"); 342 | if (!m.Success) 343 | continue; 344 | 345 | var nl = m.Value; 346 | if (ignoreAccessChecks) 347 | { 348 | text = s_If + nl + text + nl + s_EndIf; 349 | } 350 | else 351 | { 352 | text = text.Replace(s_If + nl, ""); 353 | text = text.Replace(nl + s_EndIf, ""); 354 | } 355 | 356 | Log("ModifyFiles: Write {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If)); 357 | File.WriteAllText(file, text); 358 | } 359 | } 360 | 361 | public static void ChangeCompilerProcess(object compiler, Settings setting) 362 | { 363 | Type tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor"); 364 | Type tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor"); 365 | FieldInfo fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance); 366 | 367 | Log("Kill previous compiler process"); 368 | var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo; 369 | compiler.Call("Dispose"); 370 | 371 | // Convert response file for Mono to .Net. 372 | // - Add preferreduilang option (en-US) 373 | // - Change language version to 'latest' 374 | // - Change 'debug' to 'debug:portable' 375 | // - Change compiler switch prefix '-' to '/' 376 | string responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1"); 377 | bool isMono = compiler.GetType().Name == "MonoCSharpCompiler"; 378 | var text = File.ReadAllText(responseFile); 379 | text = Regex.Replace(text, "[\r\n]+", "\n"); 380 | text = Regex.Replace(text, "^-", "/", RegexOptions.Multiline); 381 | 382 | // Modify scripting define symbols. 383 | { 384 | Log("Modify scripting define symbols: {0}", responseFile); 385 | var defines = Regex.Matches(text, "^/define:(.*)$", RegexOptions.Multiline) 386 | .Cast() 387 | .Select(x => x.Groups[1].Value); 388 | 389 | text = Regex.Replace(text, "[\r\n]+/define:[^\r\n]+", ""); 390 | foreach (var d in ModifyDefines(defines, setting.IgnoreAccessChecks, setting.ModifySymbols)) 391 | { 392 | text += "\n/define:" + d; 393 | } 394 | } 395 | 396 | // Add/remove '#if IGNORE_ACCESS_CHECKS' and '#endif' preprocessor. 397 | var files = Regex.Matches(text, "^\"(.*)\"$", RegexOptions.Multiline) 398 | .Cast() 399 | .Select(x => x.Groups[1].Value) 400 | .Where(x => Path.GetExtension(x) == ".cs") 401 | .Where(x => Path.GetFileName(x) != "AsmdefEx.cs"); 402 | ModifyFiles(files, setting.IgnoreAccessChecks); 403 | 404 | // To access to non-publics in other assemblies, use custom compiler instead of default csc. 405 | if (setting.UseCustomCompiler) 406 | { 407 | text = Regex.Replace(text, "^/langversion:\\d+$", "/langversion:latest", RegexOptions.Multiline); 408 | text = Regex.Replace(text, "^/debug$", "/debug:portable", RegexOptions.Multiline); 409 | text += "\n/preferreduilang:en-US"; 410 | 411 | // Change exe file path. 412 | var cscToolExe = CustomCompiler.GetInstalledPath(setting.CustomCompiler); 413 | Log("Change csc tool exe to {0}", cscToolExe); 414 | if (Application.platform == RuntimePlatform.WindowsEditor) 415 | { 416 | psi.FileName = Path.GetFullPath(cscToolExe); 417 | psi.Arguments = "/shared /noconfig @" + responseFile; 418 | } 419 | else 420 | { 421 | psi.FileName = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/bin/mono"); 422 | psi.Arguments = cscToolExe + " /noconfig @" + responseFile; 423 | } 424 | } 425 | // Revert prefix symbols for mono compiler 426 | else if (isMono) 427 | { 428 | text = Regex.Replace(text, "^/", "-", RegexOptions.Multiline); 429 | } 430 | 431 | text = Regex.Replace(text, "\n", System.Environment.NewLine); 432 | File.WriteAllText(responseFile, text); 433 | 434 | Log("Restart compiler process: {0} {1}", psi.FileName, psi.Arguments); 435 | var program = tProgram.New(psi); 436 | program.Call("Start"); 437 | compiler.Set("process", program, fiProcess); 438 | } 439 | 440 | static void OnAssemblyCompilationStarted(string name) 441 | { 442 | try 443 | { 444 | string assemblyName = Path.GetFileNameWithoutExtension(name); 445 | string assemblyFilename = assemblyName + ".dll"; 446 | 447 | if (assemblyName != typeof(Core).Assembly.GetName().Name) 448 | return; 449 | 450 | Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor"); 451 | var compilerTasks = tEditorCompilationInterface.Get("Instance").Get("compilationTask").Get("compilerTasks") as IDictionary; 452 | var scriptAssembly = compilerTasks.Keys.Cast().FirstOrDefault(x => (x.Get("Filename") as string) == assemblyFilename); 453 | 454 | // Should change compiler process for the assembly? 455 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 456 | var setting = Settings.GetAtPath(asmdefPath); 457 | if (!setting.SholdChangeCompilerProcess) 458 | return; 459 | 460 | // Create new compiler to recompile. 461 | Log("Assembly compilation started: {0} should be recompiled.", assemblyName); 462 | Core.ChangeCompilerProcess(compilerTasks[scriptAssembly], setting); 463 | } 464 | catch (Exception e) 465 | { 466 | UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException)); 467 | } 468 | } 469 | 470 | static Core() 471 | { 472 | var assemblyName = typeof(Core).Assembly.GetName().Name; 473 | if (assemblyName == "Coffee.AsmdefEx") 474 | return; 475 | 476 | k_LogHeader = string.Format("[AsmdefEx ({0})] ", assemblyName); 477 | LogEnabled = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup) 478 | .Split(';', ',') 479 | .Any(x => x == "ASMDEF_EX_LOG"); 480 | 481 | Log("Start watching assembly '{0}' compilation.", typeof(Core).Assembly.GetName().Name); 482 | CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted; 483 | } 484 | } 485 | 486 | #if !ASMDEF_EX 487 | [InitializeOnLoad] 488 | internal class RecompileRequest 489 | { 490 | static RecompileRequest() 491 | { 492 | var assemblyName = typeof(RecompileRequest).Assembly.GetName().Name; 493 | if (assemblyName == "Coffee.AsmdefEx") 494 | return; 495 | 496 | // Should change compiler process for the assembly? 497 | var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); 498 | var setting = Settings.GetAtPath(asmdefPath); 499 | if (!setting.SholdChangeCompilerProcess) 500 | return; 501 | 502 | if (Core.LogEnabled) 503 | UnityEngine.Debug.LogFormat("Request to recompile: {0} ({1})", assemblyName, asmdefPath); 504 | 505 | AssetDatabase.ImportAsset(asmdefPath); 506 | } 507 | } 508 | #endif 509 | } 510 | #endif 511 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/AsmdefEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae9598e236a1e4825bda3c7635962827 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/Coffee.AsmdefEx.RuntimeTests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Coffee.AsmdefEx.RuntimeTests", 3 | "references": [ 4 | "Coffee.AsmdefEx.RuntimeTests.InternalLibrary" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": false, 15 | "defineConstraints": [] 16 | } -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/Coffee.AsmdefEx.RuntimeTests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 974e59f26f91f4eb8a228c55f7ce1829 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: '{"IgnoreAccessChecks":true,"ModifySymbols":"OSC_TEST;!UNITY_5_3_OR_NEWER","CustomCompiler":""}' 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/InternalLibrary.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b6313079dbb148ed92be43e7026e7db 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/InternalLibrary/Coffee.AsmdefEx.RuntimeTests.InternalLibrary.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Coffee.AsmdefEx.RuntimeTests.InternalLibrary", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": false, 11 | "defineConstraints": [] 12 | } -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/InternalLibrary/Coffee.AsmdefEx.RuntimeTests.InternalLibrary.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 971b667dca8434a2e8c92859c2a22da5 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: '{"IgnoreAccessChecks":false,"ModifySymbols":"","CustomCompiler":"","GenerateXmlDoc":true}' 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/InternalLibrary/InternalLibrary.cs: -------------------------------------------------------------------------------- 1 | namespace Coffee.AsmdefEx.RuntimeTests.InternalLibrary 2 | { 3 | /// 4 | /// Internal Class 5 | /// 6 | internal class InternalClass 7 | { 8 | /// 9 | /// private String Field 10 | /// 11 | private string privateStringField = "privateStringField"; 12 | 13 | /// 14 | /// private Static String Field 15 | /// 16 | private static string privateStaticStringField = "privateStaticStringField"; 17 | 18 | /// 19 | /// Public Static Method 20 | /// 21 | public static string PublicStaticMethod() 22 | { 23 | return "PublicStaticMethod"; 24 | } 25 | 26 | /// 27 | /// Private Static Method 28 | /// 29 | private static string PrivateStaticMethod() 30 | { 31 | return "PrivateStaticMethod"; 32 | } 33 | 34 | /// 35 | /// Public Method 36 | /// 37 | public string PublicMethod() 38 | { 39 | return "PublicMethod"; 40 | } 41 | 42 | /// 43 | /// Private Method 44 | /// 45 | private string PrivateMethod() 46 | { 47 | return "PrivateMethod"; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/InternalLibrary/InternalLibrary.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1767126199d1400498e7393812a2b05 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/RuntimeTests.cs: -------------------------------------------------------------------------------- 1 | #if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 2 | using System.Collections.Generic; 3 | using NUnit.Framework; 4 | using Coffee.AsmdefEx.RuntimeTests.InternalLibrary; 5 | 6 | namespace Coffee.AsmdefEx.RuntimeTests 7 | { 8 | class ScriptDefineSymbolTest 9 | { 10 | [Test] 11 | public void DefineSymbols() 12 | { 13 | #if OSC_TEST 14 | string log = "OSC_TEST is defined."; 15 | #else 16 | string log = "OSC_TEST is not defined."; 17 | #endif 18 | Assert.AreEqual(log, "OSC_TEST is defined."); 19 | } 20 | 21 | [Test] 22 | public void RemoveSymbols() 23 | { 24 | #if UNITY_5_3_OR_NEWER 25 | string log = "UNITY_5_3_OR_NEWER is defined."; 26 | #else 27 | string log = "UNITY_5_3_OR_NEWER is not defined."; 28 | #endif 29 | Assert.AreEqual(log, "UNITY_5_3_OR_NEWER is not defined."); 30 | } 31 | } 32 | 33 | class RuntimeTest 34 | { 35 | [Test] 36 | public void ListPool() 37 | { 38 | List list = UnityEngine.UI.ListPool.Get(); 39 | list.Add(1); 40 | list.Clear(); 41 | UnityEngine.UI.ListPool.Release(list); 42 | } 43 | } 44 | 45 | public class AnotherInternalLibrary 46 | { 47 | [Test] 48 | public void InternalClass_privateStringField() 49 | { 50 | Assert.AreEqual(new InternalClass().privateStringField, "privateStringField"); 51 | } 52 | 53 | [Test] 54 | public void InternalClass_PublicMethod() 55 | { 56 | Assert.AreEqual(new InternalClass().PublicMethod(), "PublicMethod"); 57 | } 58 | 59 | [Test] 60 | public void InternalClass_PrivateMethod() 61 | { 62 | Assert.AreEqual(new InternalClass().PrivateMethod(), "PrivateMethod"); 63 | } 64 | 65 | [Test] 66 | public void InternalClass_privateStaticStringField() 67 | { 68 | Assert.AreEqual(InternalClass.privateStaticStringField, "privateStaticStringField"); 69 | } 70 | 71 | [Test] 72 | public void InternalClass_PublicStaticMethod() 73 | { 74 | Assert.AreEqual(InternalClass.PublicStaticMethod(), "PublicStaticMethod"); 75 | } 76 | 77 | [Test] 78 | public void InternalClass_PrivateStaticMethod() 79 | { 80 | Assert.AreEqual(InternalClass.PrivateStaticMethod(), "PrivateStaticMethod"); 81 | } 82 | } 83 | } 84 | #endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY. 85 | -------------------------------------------------------------------------------- /Tests/AsmdefEx.RuntimeTests/RuntimeTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d8ff929775687e4bba76baf4b19861a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.coffee.open-sesame-compiler", 3 | "displayName": "Open Sesame Compiler", 4 | "description": "A Roslyn compiler to access internals/privates. In other words, you can access to any internals/privates in other assemblies, without reflection. Let's say, \"Open sesame!\"", 5 | "version": "1.0.0-preview.26", 6 | "unity": "2018.3", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/mob-sakai/OpenSesameCompilerForUnity.git" 11 | }, 12 | "author": "mob-sakai (https://github.com/mob-sakai)", 13 | "dependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: addc9b96859e241f98476ec0c32d52c7 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------