Created unity project

This commit is contained in:
2024-12-07 20:55:50 +01:00
parent 539250d964
commit 54fe327198
13758 changed files with 865324 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf

View File

@@ -0,0 +1,5 @@
{
"timestamp": 1708506923,
"signature": "BFXO8Pvm6vPITeDwdxb9p0uahZX8+i7lfwocAhZkQVDxvW2qqd+2SB0nnnmeTy0fkJMI2QROY3h5HwrWanMOj9b5L5uYfUOBU8hBnRZ3oD8nsoTUyj22esqRhuAVMfBkbcqOsG1YtwLZ1pJOFjJW8VY+TMKwstXAoMKC46YADs+wqxVpRH/LMwABbpAHBLSZbguEPfEXr/fQjZ5hKCcMgrEZQ4+sU7moO4rxFx7rKcnCAuM/G9HzqNyJl6ATQ1DYA/WBTN5jV5bgbM85AwAaAxeut9rc+pLeKu6Y0fn05jcuRxq8SX7QuZAGQkQxrGEc8QblMDc+/zbz8VQ841766wuj3WXZDhBdU1bpzYdtP6CZBoZ3sDNdKGdFBPmxY+n1+izPljKugKbJHXxE1JycsUO7arNTj+LCJsqGuM50N0N43y/5UCQ5QYq4nMsehOC21ts1mskuhHIkpe5w9oXr9P1Qpnmv0m6PYk4lA7il/5B63O/dQvjcuEdGinhtrQKg",
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
}

View File

@@ -0,0 +1,278 @@
# Code Editor Package for Rider
## [3.0.28] - 2024-02-20
- fix RIDER-103933 "PlayerSettings.suppressCommonWarnings" is not supported in Unity 2019.4.40f
- fix https://github.com/JetBrains/resharper-unity/issues/2431 and [RIDER-104221](https://youtrack.jetbrains.com/issue/RIDER-104221)
## [3.0.27] - 2023-11-30
- Restore the ability to select Rider installation from the custom location
- Fix possible extra project regeneration on moving focus from Rider to Unity
- Improve performance of code generation for very large projects
## [3.0.26] - 2023-10-04
- https://github.com/JetBrains/resharper-unity/issues/2421
- https://github.com/JetBrains/resharper-unity/issues/2422
## [3.0.25] - 2023-08-18
- unification of functionality to search JetBrains installations and open solution and file in Rider
## [3.0.22] - 2023-05-2
- RIDER-82999 Unity's plugin SyncAll does not regenerate project files, and instead does basically nothing.
- #2401 Compilation issue with Unity 2021.3.0f1
## [3.0.21] - 2023-04-18
[RIDER-92424](https://youtrack.jetbrains.com/issue/RIDER-92424) JetBrains Rider Editor 3.0.20 package Update for Unity, Cause's Rider to Slows to a Crawl after updating
[RIDER-92419](https://youtrack.jetbrains.com/issue/RIDER-92419) JetBrains Rider Editor 3.0.20 for Unity has duplicate assemblies loaded into runtime
## [3.0.20] - 2023-04-05
- fix loading Rider integration EditorPlugin on first switch of External Editor to Rider, see [RIDER-91185](https://youtrack.jetbrains.com/issue/RIDER-91185)
- Keep the the PackageManager in sync with the Rider changes made to the manifest.json, it should help with [RIDER-77343](https://youtrack.jetbrains.com/issue/RIDER-77343)
- Support CompilerOptions.RoslynAdditionalFilePaths and CompilerOptions.AnalyzerConfigPath
## [3.0.18] - 2023-01-09
- [RIDER-74818](https://youtrack.jetbrains.com/issue/RIDER-74818) Unity doesn't get to play mode if Editor is not running and user starts debug or profiling
- Improve performance of project generation - avoid using Directory.Exists
- avoid doing ProjectGeneration twice on the first start-up
## [3.0.17] - 2022-12-01
- Avoid adding asset project parts to both editor and player projects, fixes the following issues:
- [RIDER-75500](https://youtrack.jetbrains.com/issue/RIDER-75500) Local package references completions shows duplicate entries if player projects are generated
- [RIDER-73795](https://youtrack.jetbrains.com/issue/RIDER-73795) Conversion to guid is not offered for assemblies with generated player projects
- [RIDER-71238](https://youtrack.jetbrains.com/issue/RIDER-71238) No usages can be found for the assembly if player projects are generated
## [3.0.16] - 2022-09-09
- Update the changelog
- Add folders to the generated csproj files
- Avoid extra RequestScriptReload call on the first start
- Fix shader support for folders in packages, but outside asmdef
## [3.0.15] - 2022-05-24
- Cleanup cache after project generation to reduce memory consumption
- Performance optimization
- RIDER-76126 Rider package should generate an empty csproj for empty Unity project
- RIDER-77206 Unity 2020.1.3 'PlayerSettings' does not contain a definition for 'suppressCommonWarnings
## [3.0.14] - 2022-04-21
- Move Rider package persisted state to Library, to avoid vcs collisions or adding it specifically to gitignore
## [3.0.13] - 2022-03-24
- fix RIDER-69927 "Test not run" status is shown for the test suite when running unit tests for Unity project
- fix RIDER-74676 Unity plugin "JetBrainseRider Editor" completely breaks <= 2019.1.9
- fix RIDER-71503 Unity Hang on "Domain Unload", caused by dispose of FileSystemWatcher
## [3.0.12] - 2022-01-28
- Fix bug, which was introduced in 3.0.10: New script was not added to the csproj, because cached list of assemblies was used.
## [3.0.10] - 2021-12-09
- Fix presentation of the TargetFramework in the csproj
- Fix: Auto-generated solution doesn't compile when code overrides virtual functions in other assemblies
- Fix RIDER-72234 Avoid full project generation, when only content of assembly was changed
- Fix RIDER-71985 Building large Unity projects randomly fails
- Fix RIDER-72174 Looking for Rider installed by dotUltimate installer
## [3.0.9] - 2021-11-09
- Fix path for Roslyn analyser supplied with a package
- Minimal requirement for roslyn analyzer scope is Unity 2020.3.6f1 and above
## [3.0.8] - 2021-11-08
- Technical release
## [3.0.7] - 2021-05-07
- RIDER-60815 Simplify extensions lists for Rider package
- Fix csc.rsp `-nullable+` / `-nullable-` parsing https://github.com/van800/com.unity.ide.rider/issues/7
- Support `-warnaserror`/`-warnaserror-:`/`-warnaserror+:` in csc.rsp
## [3.0.6] - 2021-04-06
- Fix bug: For Unity 2021.1+ Switching external editor from VS => Rider won't create the connection between Unity and Rider.
- When PlayerSettings.suppressCommonWarnings is true, it is reflected in the generated csproj with NoWarn "0169", "0649"
- By default include T4 templates in the generated solution (RIDER-37159)
- RIDER-60554 Unity crash in case of project without Unity Test Framework Package.
- RIDER-60445 Fix presentation of Rider external editor, when it is installed in a custom location.
- Improve project files generation performance
- RIDER-60508 Project Generation for projects without any cs files - add reference to UnityEditor/UnityEngine, so that Rider would detect Unity path and version and provide rich features for shader file.
## [3.0.5] - 2021-02-25
- More stable in case of possible Rider product code change, improve test. Allows using "Rider for Unreal" with Unity projects (https://youtrack.jetbrains.com/issue/RIDER-51203)
- Remove implicit dependency to Test-Framework package
- Fix "Unreachable code detected" warning (https://youtrack.jetbrains.com/issue/RIDER-57930)
## [3.0.4] - 2021-01-26
- Use LangVersion provided by Unity for generated csproj
- Improve documentation
- Support nullable provided in csc,rsp
- Avoid doing work in Unity secondary processes in UNITY_2021_1_OR_NEWER with UnityEditor.MPE.ProcessLevel.Secondary
## [3.0.3] - 2020-11-18
- Update License
- Avoid connecting Rider from secondary UnityEditor instances
- Fix RIDER-53082 - Generate csproj without cs files, when there are any assets inside
## [3.0.2] - 2020-10-27
- Speedup ProjectGeneration
- Fix RIDER-51958. Callbacks OnGeneratedCSProjectFiles would not work, but show a Warning instead.
- Remove release configuration
- Call RequestScriptReload, when External Editor is changed in Unity.
## [3.0.1] - 2020-10-02
- RIDER-46658 Rider does not run PlayMode tests when ValueSource is combined with parameterized TestFixture
- RIDER-49947 Invoking `PlayerSettings.SetScriptingDefineSymbolsForGroup()` does not update definitions in Rider.
- Add static entrypoint `Packages.Rider.Editor.RiderScriptEditor.SyncSolution` to allow generating solution from commandline.
## [2.0.7] - 2020-08-18
- Improve performance
- Add support for asmdef Root Namespace in .csproj generation
- ProjectGeneration for custom roslyn analysers https://docs.unity3d.com/2020.2/Documentation/Manual/roslyn-analyzers.html
- Switch target platform in Unity would regenerate csproj files (https://github.com/JetBrains/resharper-unity/issues/1740)
## [2.0.6] - 2020-08-10
- Improve performance
- Add support for asmdef Root Namespace in .csproj generation
- ProjectGeneration for custom roslyn analysers https://docs.unity3d.com/2020.2/Documentation/Manual/roslyn-analyzers.html
- Switch target platform in Unity would regenerate csproj files (https://github.com/JetBrains/resharper-unity/issues/1740)
## [2.0.5] - 2020-05-27
- Fix Regression in 2.0.3: In Unity 2019.2.9 on Mac, changing csproj and calling AssetDatabase.Refresh is not regenerating csproj.
- Regenerate projects on changes in manifest.json and Project Settings (EditorOnlyScriptingUserSettings.json) (#51)
- Fix: Assembly references to package assemblies break IDE projects.
- Fix: Reporting test duration.
## [2.0.2] - 2020-03-18
- fix bug in searching Rider path on MacOS
## [2.0.1] - 2020-03-05
- Speed improvements,
- ProjectTypeGuids for unity-generated project
- Improve UI for Project Generation settings
- Changes in csc.rsp would cause project-generation
- Remove NoWarn 0169 from generated csproj
- Support custom JetBrains Toolbox installation location
## [1.2.1] - 2019-12-09
- Load optimised EditorPlugin version compiled to net 461, with fallback to previous version.
- On ExternalEditor settings page: reorder Generate all ... after Extensions handled
- Better presentation for Rider of some version in ExternalEditors list
- Initial support for Code Coverage with dotCover plugin in Rider
- Added support for Player Project generation
## [1.1.4] - 2019-11-21
- Fix warning - unreachable code
## [1.1.3] - 2019-10-17
- Update External Editor, when new toolbox build was installed
- Add xaml to default list of extensions to include in csproj
- Avoid initializing Rider package in secondary Unity process, which does Asset processing
- Reflect multiple csc.rsp arguments to generated csproj files: https://github.com/JetBrains/resharper-unity/issues/1337
- Setting, which allowed to override LangVersion removed in favor of langversion in csc.rsp
- Environment.NewLine is used in generated project files instead of Windows line separator.
## [1.1.2] - 2019-09-18
performance optimizations:
- avoid multiple evaluations
- avoid reflection in DisableSyncSolutionOnceCallBack
- project generation optimization
fixes:
- avoid compilation error with incompatible `Test Framework` package
## [1.1.1] - 2019-08-26
parse nowarn in csc.rsp
warning, when Unity was started from Rider, but external editor was different
improved unit test support
workaround to avoid Unity internal project-generation (fix #28)
## [1.1.0] - 2019-07-02
new setting to manage list of extensions to be opened with Rider
avoid breaking everything on any unhandled exception in RiderScriptEditor cctor
hide Rider settings, when different Editor is selected
dynamically load only newer rider plugins
path detection (work on unix symlinks)
speed up for project generation
lots of bug fixing
## [1.0.8] - 2019-05-20
Fix NullReferenceException when External editor was pointing to non-existing Rider everything was broken by null-ref.
## [1.0.7] - 2019-05-16
Initial migration steps from rider plugin to package.
Fix OSX check and opening of files.
## [1.0.6] - 2019-04-30
Ensure asset database is refreshed when generating csproj and solution files.
## [1.0.5] - 2019-04-27
Add support for generating all csproj files.
## [1.0.4] - 2019-04-18
Fix relative package paths.
Fix opening editor on mac.
## [1.0.3] - 2019-04-12
Fixing null reference issue for callbacks to Asset pipeline.
## [1.0.2] - 2019-01-01
### This is the first release of *Unity Package rider_editor*.
Using the newly created api to integrate Rider with Unity.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8645aa9c3c74fb34ba9499e14fb332b5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
# Contributing
## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement)
By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions.
## Once you have a change ready following these ground rules. Simply make a pull request

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5e83f8baac96eaa47bdd9ca781cd2002
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,4 @@
# Code Editor Package for Rider
This package is not intended to be modified by users.
Nor does it provide any api intended to be included in user projects.

View File

@@ -0,0 +1,2 @@
* [About JetBrains Rider Editor](index.md)
* [Using the JetBrains Rider Editor package](using-the-jetbrains-rider-editor-package.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,32 @@
# About JetBrains Rider Editor
The JetBrains Rider editor package integrates support for the [JetBrains Rider](https://www.jetbrains.com/rider/) .NET Integrated Development Environment (IDE), into the Unity Editor. This package provides an end-point for Rider to call different Unity APIs and to generate .csproj and .sln files, which Rider uses to implement support for Unity in its [plug-in](https://github.com/JetBrains/resharper-unity).
This package ensures that IDE features like autocomplete suggestions and flagging dependency conflicts work in Rider. It uses .cproj and .sln files which store information about your project such as:
* Versioning information
* Build files
* Platform requirements
* Web server or database settings
Not all code in Unity is directly visible to code editors, particularly when using packages. This is because packages dont provide their own .csproj files, and Unity doesnt create them for installed packages by default. This means that IDE features like autocomplete suggestions and flagging dependency conflicts do not work with code in these packages. The purpose of this package is to produce the .csproj files that make these features possible by default when you use Rider.
## Installation
As of Unity version 2019.2, this package comes as a part of the default Unity installation. If you are updating your project from an older version of Unity, you might need to install this package via the Package Manager.
## Requirements
This version of the JetBrains Rider editor package is compatible with the following versions of the Unity Editor:
* 2019.2.6 or later
To use this package, you must have the following third-party products installed:
* JetBrains Rider version 2019.3 or newer
For more information about the Rider IDE, see the [JetBrains Rider documentation](https://www.jetbrains.com/rider/documentation/).
### Submitting issues
This package is maintained by JetBrains and Unity. Submit issues to the [JetBrains/resharper-unity/issues GitHub page](https://github.com/JetBrains/resharper-unity/issues). Unity intends for this package to become accessible to the public on GitHub in the future.

View File

@@ -0,0 +1,55 @@
# Using the JetBrains Rider Editor package
To use the package, go to **Edit &gt; Preferences &gt; External Tools**, click on the **External Script Editor** dropdown menu and select your version of **Rider**. When you select this option, the window reloads.
After the window reloads, new settings that control production of .csproj files become available.
![](images/preferences-settings-external-tools-window.png) <br/>
*External Tools tab in the Preferences window*
## Commandline endpoints
Q: Generate sln/csproj files for CI?
A: `Unity -batchmode -quit -projectPath ProjectPath -executeMethod Packages.Rider.Editor.RiderScriptEditor.SyncSolution`
Q: Generate sln/csproj and open External Editor?
A: `Unity -batchmode -quit -projectPath ProjectPath -executeMethod Packages.Rider.Editor.RiderScriptEditor.SyncSolutionAndOpenExternalEditor`
## Package preferences
|**Property:** |**Description:** |
|:---|:---|
|__Extensions handled__| This field lists the file extensions that open in JetBrains Rider. This field contains a variety of extensions by default. |
|__Generate .csproj files for:__ | Each setting in this list enables or disables production of .csproj files for a different type of package. The **Regenerate project files** button updates existing .csproj files and creates the necessary new ones based on the settings you choose. These settings control whether to generate .csproj files for any installed packages. For more information on how to install packages, see the [Adding and removing packages documentation](https://docs.unity3d.com/Manual/upm-ui-actions.html). |
|__&nbsp;&nbsp;&nbsp;&nbsp;Embedded &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package that appears under your projects Packages folder is an embedded package. An embedded package is not necessarily built-in; you can create your own packages and embed them inside your project. This setting is enabled by default. For more information on embedded packages, see the [Embedded dependencies documentation](https://docs.unity3d.com/Manual/upm-embed.html). |
|__&nbsp;&nbsp;&nbsp;&nbsp;Local &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package that you install from a local repository stored on your machine, but from outside of your Unity project. This setting is enabled by default. |
|__&nbsp;&nbsp;&nbsp;&nbsp;Registry &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package that you install from either the official Unity registry or a custom registry. Packages in the Unity registry are available to install directly from the Package Manager. For more information about the Unity package registry, see the [Package Registry section of the Unity Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@1.8/manual/index.html#PackManRegistry). For information on creating and using custom registries in addition to the Unity registry, see the [Scoped package registries documentation](https://docs.unity3d.com/Manual/upm-scoped.html). |
|__&nbsp;&nbsp;&nbsp;&nbsp;Git &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package you install directly from a Git repository using a URL. |
|__&nbsp;&nbsp;&nbsp;&nbsp;Built-in &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package that is already installed as part of the default Unity installation. |
|__&nbsp;&nbsp;&nbsp;&nbsp;Tarball &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package you install from a GZip tarball archive on the local machine, outside of your Unity project. |
|__&nbsp;&nbsp;&nbsp;&nbsp;Unknown &nbsp;&nbsp;&nbsp;&nbsp;packages__ | Any package which Unity cannot determine an origin for. This could be because the package doesnt list its origin, or that Unity doesnt recognize the origin listed. |
|__Player projects__ | For each player project, generate an additional .csproj file named 'originalProjectName.Player.csproj'. This allows different project types to have their code included in Riders systems, such as assembly definitions or testing suites. |
This package also adds a second tab under **Preferences** named **Rider**, pictured below.
![](images/preferences-rider-tab.png)
<br/>*Rider tab in the Preferences window*
> [!NOTE]
> The Logging Level menu does not control the level of Unity's logging, only the level of log messages that Rider package logs in its own log file. For more information on controlling Unity's logging level, see the [Stack Trace Logging section of the Console Window documentation](https://docs.unity3d.com/Manual/Console.html#StackTraceLogging).
|**Property:** |**Description:** |
|:---|:---|
|__**Pass Console to Rider**__| If **Pass Console to Rider** is enabled, Rider can access data that Unity sends to the Unity Console and display it within its own environment instead. |
|__**Log file**__ | The **Log file** field contains an **Open log** button. Select this button to open the log file inside the Rider IDE. This button is unavailable when **Logging Level** is set to **OFF**. |
|__Logging Level__ | The **Logging Level** menu controls how detailed are the Rider package logs. Those logs may be used for troubleshooting communication between Rider and Unity. Rider package logs all messages of the type you select as well as any messages of a more severe type. For example, if you choose **WARN**, then Rider logs all **ERROR** and **FATAL** messages as well as **WARN** messages. The message types are listed below in order of severity, with **FATAL** as the most severe type of message and **TRACE** as the least severe. |
|__**OFF**__ | Rider does not produce any logs. |
|__**FATAL__ | Logs information relating to serious problems that cause the application to crash. This setting produces the smallest logs. |
|__**ERROR**__ | Logs information about errors that prevent some functionality from working, but dont cause the application to fail (for example, a failed database connection). |
|__**WARN**__ | Logs information about possible problems, or any unusual behaviour. Warnings dont indicate that something has gone wrong, but that Unity detects something that might potentially cause an issue if not investigated. |
|__**INFO**__ | Logs information about normal operation of the application, such as a successful database connection attempt. |
|__**VERBOSE**__ | Logs detailed but not exhaustive information about your code. This setting is helpful for checking how your code executes or providing diagnostic information for other developers. |
|__**TRACE**__ | Logs as much information about the application as possible. This can create a very large and detailed log, so its good practice to only use it when attempting to find the cause of a specific issue with your code. |

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Unity Technologies Copyright (c) 2019 JetBrains s.r.o. All rights reserved.
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5598b14661b5f4c43bed757f34b6d172
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9129183a42052cd43b9c284d6dbd541e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b393f6b29a9ee84c803af1ab4944b71
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System;
using System.Linq;
using JetBrains.Rider.PathLocator;
using Packages.Rider.Editor.Util;
using Unity.CodeEditor;
namespace Packages.Rider.Editor
{
internal interface IDiscovery
{
CodeEditor.Installation[] PathCallback();
}
internal class Discovery : IDiscovery
{
public static readonly RiderPathLocator RiderPathLocator;
public static readonly RiderFileOpener RiderFileOpener;
static Discovery()
{
var env = new RiderLocatorEnvironment();
RiderPathLocator = new RiderPathLocator(env);
RiderFileOpener = new RiderFileOpener(env);
}
public CodeEditor.Installation[] PathCallback()
{
// still we want to search for installations, when Preferences is opened
var res = RiderPathLocator.GetAllRiderPaths()
.Select(riderInfo => new CodeEditor.Installation
{
Path = riderInfo.Path,
Name = riderInfo.Presentation
})
.ToList();
var editorPath = RiderScriptEditor.CurrentEditor;
if (RiderScriptEditor.IsRiderOrFleetInstallation(editorPath) &&
!res.Any(a => a.Path == editorPath) &&
FileSystemUtil.EditorPathExists(editorPath))
{
// External editor manually set from custom location
var info = new RiderPathLocator.RiderInfo(RiderPathLocator, editorPath, false);
var installation = new CodeEditor.Installation
{
Path = info.Path,
Name = info.Presentation
};
res.Add(installation);
}
return res.ToArray();
}
}
internal class RiderLocatorEnvironment : IRiderLocatorEnvironment
{
public OS CurrentOS
{
get
{
switch (UnityEngine.SystemInfo.operatingSystemFamily)
{
case UnityEngine.OperatingSystemFamily.Windows:
return OS.Windows;
case UnityEngine.OperatingSystemFamily.MacOSX:
return OS.MacOSX;
case UnityEngine.OperatingSystemFamily.Linux:
return OS.Linux;
default:
return OS.Other;
}
}
}
public T FromJson<T>(string json)
{
return (T)UnityEngine.JsonUtility.FromJson(json, typeof(T));
}
public void Verbose(string message, Exception e = null)
{
// only writes to Editor.log
Console.WriteLine(message);
if (e != null)
Console.WriteLine(e);
}
public void Info(string message, Exception e = null)
{
UnityEngine.Debug.Log(message);
if (e != null)
UnityEngine.Debug.Log(e);
}
public void Warn(string message, Exception e = null)
{
UnityEngine.Debug.LogWarning(message);
if (e != null)
UnityEngine.Debug.LogWarning(e);
}
public void Error(string message, Exception e = null)
{
UnityEngine.Debug.LogError(message);
if (e != null)
UnityEngine.Debug.LogException(e);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dab656c79e1985c40b31faebcda44442
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Debug = UnityEngine.Debug;
namespace Packages.Rider.Editor
{
internal static class EditorPluginInterop
{
private static string EditorPluginAssemblyNamePrefix = "JetBrains.Rider.Unity.Editor.Plugin.";
public static readonly string EditorPluginAssemblyName = $"{EditorPluginAssemblyNamePrefix}Net46.Repacked";
public static readonly string EditorPluginAssemblyNameFallback = $"{EditorPluginAssemblyNamePrefix}Full.Repacked";
private static string ourEntryPointTypeName = "JetBrains.Rider.Unity.Editor.PluginEntryPoint";
private static Assembly ourEditorPluginAssembly;
public static Assembly EditorPluginAssembly
{
get
{
if (ourEditorPluginAssembly != null)
return ourEditorPluginAssembly;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
ourEditorPluginAssembly = assemblies.FirstOrDefault(a =>
{
try
{
return a.GetName().Name.StartsWith(EditorPluginAssemblyNamePrefix); // some user assemblies may fail here
}
catch (Exception)
{
// ignored
}
return default;
});
return ourEditorPluginAssembly;
}
}
private static void DisableSyncSolutionOnceCallBack()
{
// RiderScriptableSingleton.Instance.CsprojProcessedOnce = true;
// Otherwise EditorPlugin regenerates all on every AppDomain reload
var assembly = EditorPluginAssembly;
if (assembly == null) return;
var type = assembly.GetType("JetBrains.Rider.Unity.Editor.Utils.RiderScriptableSingleton");
if (type == null) return;
var baseType = type.BaseType;
if (baseType == null) return;
var instance = baseType.GetProperty("Instance");
if (instance == null) return;
var instanceVal = instance.GetValue(null);
var member = type.GetProperty("CsprojProcessedOnce");
if (member==null) return;
member.SetValue(instanceVal, true);
}
public static string LogPath
{
get
{
try
{
var assembly = EditorPluginAssembly;
if (assembly == null) return null;
var type = assembly.GetType(ourEntryPointTypeName);
if (type == null) return null;
var field = type.GetField("LogPath", BindingFlags.NonPublic | BindingFlags.Static);
if (field == null) return null;
return field.GetValue(null) as string;
}
catch (Exception)
{
Debug.Log("Unable to do OpenFile to Rider from dll, fallback to com.unity.ide.rider implementation.");
}
return null;
}
}
public static bool OpenFileDllImplementation(string path, int line, int column)
{
var openResult = false;
// reflection for fast OpenFileLineCol, when Rider is started and protocol connection is established
try
{
var assembly = EditorPluginAssembly;
if (assembly == null) return false;
var type = assembly.GetType(ourEntryPointTypeName);
if (type == null) return false;
var field = type.GetField("OpenAssetHandler", BindingFlags.NonPublic | BindingFlags.Static);
if (field == null) return false;
var handlerInstance = field.GetValue(null);
var method = handlerInstance.GetType()
.GetMethod("OnOpenedAsset", new[] {typeof(string), typeof(int), typeof(int)});
if (method == null) return false;
var assetFilePath = path;
if (!string.IsNullOrEmpty(path))
assetFilePath = Path.GetFullPath(path);
openResult = (bool) method.Invoke(handlerInstance, new object[] {assetFilePath, line, column});
}
catch (Exception e)
{
Debug.Log("Unable to do OpenFile to Rider from dll, fallback to com.unity.ide.rider implementation.");
Debug.LogException(e);
}
return openResult;
}
public static bool EditorPluginIsLoadedFromAssets(Assembly assembly)
{
if (assembly == null)
return false;
var location = assembly.Location;
var currentDir = Directory.GetCurrentDirectory();
return location.StartsWith(currentDir, StringComparison.InvariantCultureIgnoreCase);
}
internal static void InitEntryPoint(Assembly assembly)
{
try
{
var version = RiderScriptEditorData.instance.editorBuildNumber;
if (version != null)
{
if (version.Major < 192)
DisableSyncSolutionOnceCallBack(); // is require for Rider prior to 2019.2
}
else
DisableSyncSolutionOnceCallBack();
var type = assembly.GetType("JetBrains.Rider.Unity.Editor.AfterUnity56.EntryPoint");
if (type == null)
type = assembly.GetType("JetBrains.Rider.Unity.Editor.UnitTesting.EntryPoint"); // oldRider
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
catch (TypeInitializationException ex)
{
Debug.LogException(ex);
if (ex.InnerException != null)
Debug.LogException(ex.InnerException);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9bd02a3a916be64c9b47b1305149423
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
fileFormatVersion: 2
guid: ea3ec41b33345cd4f9298a51abdaa198
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 1
validateReferences: 0
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: x86_64
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
namespace Packages.Rider.Editor
{
internal enum LoggingLevel
{
/// <summary>
/// Do not use it in logging. Only in config to disable logging.
/// </summary>
OFF,
/// <summary>For errors that lead to application failure</summary>
FATAL,
/// <summary>For errors that must be shown in Exception Browser</summary>
ERROR,
/// <summary>Suspicious situations but not errors</summary>
WARN,
/// <summary>Regular level for important events</summary>
INFO,
/// <summary>Additional info for debbuging</summary>
VERBOSE,
/// <summary>Methods &amp; callstacks tracing, more than verbose</summary>
TRACE,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71bb46b59a9a7a346bbab1e185c723df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using UnityEditor;
using UnityEngine;
namespace Packages.Rider.Editor
{
internal static class PluginSettings
{
public static LoggingLevel SelectedLoggingLevel
{
get => (LoggingLevel) EditorPrefs.GetInt("Rider_SelectedLoggingLevel", 0);
private set => EditorPrefs.SetInt("Rider_SelectedLoggingLevel", (int) value);
}
public static bool LogEventsCollectorEnabled
{
get => EditorPrefs.GetBool("Rider_LogEventsCollectorEnabled", true);
private set => EditorPrefs.SetBool("Rider_LogEventsCollectorEnabled", value);
}
/// <summary>
/// Preferences menu layout
/// </summary>
/// <remarks>
/// Contains all 3 toggles: Enable/Disable; Debug On/Off; Writing Launch File On/Off
/// </remarks>
[SettingsProvider]
private static SettingsProvider RiderPreferencesItem()
{
if (!RiderScriptEditor.IsRiderOrFleetInstallation(RiderScriptEditor.CurrentEditor))
return null;
if (!RiderScriptEditorData.instance.shouldLoadEditorPlugin)
return null;
var provider = new SettingsProvider("Preferences/Rider", SettingsScope.User)
{
label = "Rider",
keywords = new[] { "Rider" },
guiHandler = (searchContext) =>
{
EditorGUIUtility.labelWidth = 200f;
EditorGUILayout.BeginVertical();
GUILayout.BeginVertical();
LogEventsCollectorEnabled =
EditorGUILayout.Toggle(new GUIContent("Pass Console to Rider:"), LogEventsCollectorEnabled);
GUILayout.EndVertical();
GUILayout.Label("");
if (!string.IsNullOrEmpty(EditorPluginInterop.LogPath))
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Log file:");
var previous = GUI.enabled;
GUI.enabled = previous && SelectedLoggingLevel != LoggingLevel.OFF;
var button = GUILayout.Button(new GUIContent("Open log"));
if (button)
{
// would use Rider if `log` is on the list of extensions, otherwise would use editor configured in the OS
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(EditorPluginInterop.LogPath, 0);
}
GUI.enabled = previous;
GUILayout.EndHorizontal();
}
var loggingMsg =
@"Sets the amount of Rider Debug output. If you are about to report an issue, please select Verbose logging level and attach Unity console output to the issue.";
SelectedLoggingLevel =
(LoggingLevel) EditorGUILayout.EnumPopup(new GUIContent("Logging Level:", loggingMsg),
SelectedLoggingLevel);
EditorGUILayout.HelpBox(loggingMsg, MessageType.None);
const string url = "https://github.com/JetBrains/resharper-unity";
if (LinkButton(url))
Application.OpenURL(url);;
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
var assembly = EditorPluginInterop.EditorPluginAssembly;
if (assembly != null)
{
var version = assembly.GetName().Version;
GUILayout.Label("Plugin version: " + version, new GUIStyle(GUI.skin.label)
{
margin = new RectOffset(4, 4, 4, 4),
});
}
GUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
};
return provider;
}
public static bool LinkButton(string url)
{
var bClicked = GUILayout.Button(url, RiderStyles.LinkLabelStyle);
var rect = GUILayoutUtility.GetLastRect();
rect.width = RiderStyles.LinkLabelStyle.CalcSize(new GUIContent(url)).x;
EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link);
return bClicked;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1bfe12aa306c0c74db4f4f1a1a0ae5ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: aa290bd9a165a0543a4bf85ac73914bc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using Unity.CodeEditor;
using UnityEditor;
namespace Packages.Rider.Editor.PostProcessors
{
internal class RiderAssetPostprocessor: AssetPostprocessor
{
public static bool OnPreGeneratingCSProjectFiles()
{
var path = RiderScriptEditor.GetEditorRealPath(CodeEditor.CurrentEditorInstallation);
if (RiderScriptEditor.IsRiderOrFleetInstallation(path))
return !ProjectGeneration.ProjectGeneration.isRiderProjectGeneration;
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45471ad7b8c1f964da5e3c07d57fbf4f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 313cbe17019f1934397f91069831062c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEditor.PackageManager;
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal class AssemblyNameProvider : IAssemblyNameProvider
{
private readonly Dictionary<string, PackageInfo> m_PackageInfoCache = new Dictionary<string, PackageInfo>();
private readonly Dictionary<string, ResponseFileData> m_ResponseFilesCache = new Dictionary<string, ResponseFileData>();
ProjectGenerationFlag m_ProjectGenerationFlag = (ProjectGenerationFlag)EditorPrefs.GetInt("unity_project_generation_flag", 3);
public string[] ProjectSupportedExtensions => EditorSettings.projectGenerationUserExtensions;
public string ProjectGenerationRootNamespace => EditorSettings.projectGenerationRootNamespace;
private Assembly[] m_AllEditorAssemblies;
private Assembly[] m_AllPlayerAssemblies;
private Assembly[] m_AllAssemblies;
public ProjectGenerationFlag ProjectGenerationFlag
{
get => m_ProjectGenerationFlag;
private set
{
EditorPrefs.SetInt("unity_project_generation_flag", (int)value);
m_ProjectGenerationFlag = value;
}
}
public string GetAssemblyNameFromScriptPath(string path)
{
return CompilationPipeline.GetAssemblyNameFromScriptPath(path);
}
public Assembly[] GetAllAssemblies()
{
if (m_AllEditorAssemblies == null)
{
m_AllEditorAssemblies = GetAssembliesByType(AssembliesType.Editor);
m_AllAssemblies = m_AllEditorAssemblies;
}
if (ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.PlayerAssemblies))
{
if (m_AllPlayerAssemblies == null)
{
m_AllPlayerAssemblies = GetAssembliesByType(AssembliesType.Player);
m_AllAssemblies = new Assembly[m_AllEditorAssemblies.Length + m_AllPlayerAssemblies.Length];
Array.Copy(m_AllEditorAssemblies, m_AllAssemblies, m_AllEditorAssemblies.Length);
Array.Copy(m_AllPlayerAssemblies, 0, m_AllAssemblies, m_AllEditorAssemblies.Length, m_AllPlayerAssemblies.Length);
}
}
return m_AllAssemblies;
}
private static Assembly[] GetAssembliesByType(AssembliesType type)
{
// This is a very expensive Unity call...
var compilationPipelineAssemblies = CompilationPipeline.GetAssemblies(type);
var assemblies = new Assembly[compilationPipelineAssemblies.Length];
var i = 0;
foreach (var compilationPipelineAssembly in compilationPipelineAssemblies)
{
// The CompilationPipeline's assemblies have an output path of Libraries/ScriptAssemblies
// TODO: It might be worth using the app's copy of Assembly and updating output path when we need it
// But that requires tracking editor and player assemblies separately
var outputPath = type == AssembliesType.Editor
? $@"Temp\Bin\Debug\{compilationPipelineAssembly.name}\"
: $@"Temp\Bin\Debug\{compilationPipelineAssembly.name}\Player\";
assemblies[i] = new Assembly(
compilationPipelineAssembly.name,
outputPath,
compilationPipelineAssembly.sourceFiles,
compilationPipelineAssembly.defines,
compilationPipelineAssembly.assemblyReferences,
compilationPipelineAssembly.compiledAssemblyReferences,
compilationPipelineAssembly.flags,
compilationPipelineAssembly.compilerOptions
#if UNITY_2020_2_OR_NEWER
, compilationPipelineAssembly.rootNamespace
#endif
);
i++;
}
return assemblies;
}
public Assembly GetNamedAssembly(string name)
{
foreach (var assembly in GetAllAssemblies())
{
if (assembly.name == name)
return assembly;
}
return null;
}
public string GetProjectName(string name, string[] defines)
{
if (!ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.PlayerAssemblies))
return name;
return !defines.Contains("UNITY_EDITOR") ? name + ".Player" : name;
}
public IEnumerable<string> GetAllAssetPaths()
{
return AssetDatabase.GetAllAssetPaths();
}
private static string GetPackageRootDirectoryName(string assetPath)
{
const string packagesPrefix = "packages/";
if (!assetPath.StartsWith(packagesPrefix, StringComparison.OrdinalIgnoreCase))
{
return null;
}
var followupSeparator = assetPath.IndexOf('/', packagesPrefix.Length);
// Note that we return the first path segment without modifying/normalising case!
return followupSeparator == -1 ? assetPath : assetPath.Substring(0, followupSeparator);
}
public PackageInfo GetPackageInfoForAssetPath(string assetPath)
{
var packageName = GetPackageRootDirectoryName(assetPath);
if (packageName == null)
{
return null;
}
// Assume the package name casing is consistent. If it's not, we'll fall back to an uppercase variant that's
// saved in the same dictionary. This gives us cheaper case sensitive matching, with a fallback if our assumption
// is incorrect
if (m_PackageInfoCache.TryGetValue(packageName, out var cachedPackageInfo))
return cachedPackageInfo;
var packageNameUpper = packageName.ToUpperInvariant();
if (m_PackageInfoCache.TryGetValue(packageNameUpper, out cachedPackageInfo))
return cachedPackageInfo;
var result = PackageInfo.FindForAssetPath(packageName);
m_PackageInfoCache[packageName] = result;
m_PackageInfoCache[packageNameUpper] = result;
return result;
}
public void ResetCaches()
{
m_PackageInfoCache.Clear();
m_ResponseFilesCache.Clear();
m_AllEditorAssemblies = null;
m_AllPlayerAssemblies = null;
}
public bool IsInternalizedPackagePath(string path)
{
if (string.IsNullOrEmpty(path))
{
return false;
}
var packageInfo = GetPackageInfoForAssetPath(path);
if (packageInfo == null)
{
return false;
}
var packageSource = packageInfo.source;
switch (packageSource)
{
case PackageSource.Embedded:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.Embedded);
case PackageSource.Registry:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.Registry);
case PackageSource.BuiltIn:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.BuiltIn);
case PackageSource.Unknown:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.Unknown);
case PackageSource.Local:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.Local);
case PackageSource.Git:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.Git);
#if UNITY_2019_3_OR_NEWER
case PackageSource.LocalTarball:
return !ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.LocalTarBall);
#endif
}
return false;
}
public ResponseFileData ParseResponseFile(string responseFilePath, string projectDirectory,
ApiCompatibilityLevel apiCompatibilityLevel)
{
var key = responseFilePath + ":" + (int) apiCompatibilityLevel;
if (!m_ResponseFilesCache.TryGetValue(key, out var responseFileData))
{
var systemReferenceDirectories =
CompilationPipeline.GetSystemAssemblyDirectories(apiCompatibilityLevel);
responseFileData = CompilationPipeline.ParseResponseFile(
responseFilePath,
projectDirectory,
systemReferenceDirectories
);
m_ResponseFilesCache.Add(key, responseFileData);
}
return responseFileData;
}
public IEnumerable<string> GetRoslynAnalyzerPaths()
{
return PluginImporter.GetAllImporters()
.Where(i => !i.isNativePlugin && AssetDatabase.GetLabels(i).SingleOrDefault(l => l == "RoslynAnalyzer") != null)
.Select(i => i.assetPath);
}
public void ToggleProjectGeneration(ProjectGenerationFlag preference)
{
if (ProjectGenerationFlag.HasFlag(preference))
{
ProjectGenerationFlag ^= preference;
}
else
{
ProjectGenerationFlag |= preference;
}
}
public void ResetProjectGenerationFlag()
{
ProjectGenerationFlag = ProjectGenerationFlag.None;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 56c8c6e437b14f8e9a91e9832c11bc1a
timeCreated: 1580717719

View File

@@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Security;
using System.Text;
using Packages.Rider.Editor.Util;
namespace Packages.Rider.Editor.ProjectGeneration {
class FileIOProvider : IFileIO
{
public bool Exists(string path)
{
return File.Exists(path);
}
public TextReader GetReader(string path)
{
return new StreamReader(path);
}
public string ReadAllText(string path)
{
return File.ReadAllText(path);
}
public void WriteAllText(string path, string content)
{
File.WriteAllText(path, content, Encoding.UTF8);
LastWriteTracker.UpdateLastWriteIfNeeded(path);
}
public string EscapedRelativePathFor(string file, string rootDirectoryFullPath)
{
// We have to normalize the path, because the PackageManagerRemapper assumes
// dir seperators will be os specific.
var absolutePath = Path.GetFullPath(file.NormalizePath());
var path = SkipPathPrefix(absolutePath, rootDirectoryFullPath);
return SecurityElement.Escape(path);
}
private static string SkipPathPrefix(string path, string prefix)
{
var root = prefix[prefix.Length - 1] == Path.DirectorySeparatorChar
? prefix
: prefix + Path.DirectorySeparatorChar;
return path.StartsWith(root, StringComparison.Ordinal)
? path.Substring(root.Length)
: path;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6ba838b1348d5e46a7eaacd1646c1d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace Packages.Rider.Editor.ProjectGeneration {
class GUIDProvider : IGUIDGenerator
{
public string ProjectGuid(string name)
{
return SolutionGuidGenerator.GuidForProject(name);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8cfde1a59fb35574189691a9de1df93b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Compilation;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal interface IAssemblyNameProvider
{
string[] ProjectSupportedExtensions { get; }
string ProjectGenerationRootNamespace { get; }
ProjectGenerationFlag ProjectGenerationFlag { get; }
string GetAssemblyNameFromScriptPath(string path);
string GetProjectName(string name, string[] defines);
bool IsInternalizedPackagePath(string path);
Assembly[] GetAllAssemblies();
Assembly GetNamedAssembly(string name);
IEnumerable<string> GetAllAssetPaths();
UnityEditor.PackageManager.PackageInfo GetPackageInfoForAssetPath(string assetPath);
ResponseFileData ParseResponseFile(string responseFilePath, string projectDirectory, ApiCompatibilityLevel systemReferenceDirectories);
IEnumerable<string> GetRoslynAnalyzerPaths();
void ToggleProjectGeneration(ProjectGenerationFlag preference);
void ResetCaches();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5eea837708474d7e9c1cb4b2eca0213f
timeCreated: 1580717710

View File

@@ -0,0 +1,17 @@
using System.IO;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal interface IFileIO
{
bool Exists(string path);
TextReader GetReader(string path);
string ReadAllText(string path);
void WriteAllText(string path, string content);
// rootDirectoryFullPath is assumed to be the result of Path.GetFullPath
// Passing the directory with a trailing slash (Path.DirectorySeparatorChar) will avoid an allocation
string EscapedRelativePathFor(string path, string rootDirectoryFullPath);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1bdab5b8331b4506bf4eae379235c053
timeCreated: 1580717666

View File

@@ -0,0 +1,7 @@
namespace Packages.Rider.Editor.ProjectGeneration
{
internal interface IGUIDGenerator
{
string ProjectGuid(string name);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8c7e8e301f8b4c30bbf9db502d637f0f
timeCreated: 1580717700

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal interface IGenerator
{
bool SyncIfNeeded(IEnumerable<string> affectedFiles, IEnumerable<string> reimportedFiles, bool checkProjectFiles = false);
void Sync();
bool HasSolutionBeenGenerated();
string SolutionFile();
IAssemblyNameProvider AssemblyNameProvider { get; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39cb9ab8a3b2452cbf58ffbea841d203
timeCreated: 1580717654

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal static class LastWriteTracker
{
internal static bool HasLastWriteTimeChanged()
{
if (!IsUnityCompatible()) return false;
// any external changes of sln/csproj should cause their regeneration
// Directory.GetCurrentDirectory(), "*.csproj", "*.sln"
var files = new List<FileInfo>();
var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
files.AddRange(directoryInfo.GetFiles("*.csproj"));
files.Add(new FileInfo(Path.Combine(directoryInfo.FullName, directoryInfo.Name + ".sln")));
return files.Any(a => a.LastWriteTime > RiderScriptEditorPersistedState.instance.LastWrite);
}
internal static void UpdateLastWriteIfNeeded(string path)
{
if (!IsUnityCompatible()) return;
var fileInfo = new FileInfo(path);
if (fileInfo.Directory == null)
return;
var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
if (fileInfo.Directory.FullName.Equals(directoryInfo.FullName, StringComparison.OrdinalIgnoreCase) &&
(fileInfo.Extension.Equals(".csproj", StringComparison.OrdinalIgnoreCase)
|| fileInfo.Name.Equals(directoryInfo.Name + ".sln", StringComparison.OrdinalIgnoreCase)))
{
RiderScriptEditorPersistedState.instance.LastWrite = fileInfo.LastWriteTime;
}
}
internal static bool IsUnityCompatible()
{
#if UNITY_2020_1_OR_NEWER
return true;
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7019e230344c48d4b81602e2e978e5de
timeCreated: 1645608955

View File

@@ -0,0 +1,41 @@
using System.IO;
#if UNITY_2020_1_OR_NEWER
using UnityEditor.PackageManager;
#endif
namespace Packages.Rider.Editor.ProjectGeneration
{
internal static class PackageManagerTracker
{
private static bool HasManifestJsonLastWriteTimeChanged()
{
if (!LastWriteTracker.IsUnityCompatible()) return false;
var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
var manifestFile = new FileInfo(Path.Combine(directoryInfo.FullName, "Packages/manifest.json"));
if (manifestFile.Exists)
{
// for the manifest.json, we store the LastWriteTime here
var res = manifestFile.LastWriteTime > RiderScriptEditorPersistedState.instance.ManifestJsonLastWrite;
if (res) RiderScriptEditorPersistedState.instance.ManifestJsonLastWrite = manifestFile.LastWriteTime;
return res;
}
return false;
}
/// <summary>
/// If the manifest.json was changed outside Unity and Rider calls Unity to Refresh, we should call PM to Refresh its state also
/// </summary>
/// <param name="checkProjectFiles"></param>
internal static void SyncIfNeeded(bool checkProjectFiles)
{
#if UNITY_2020_1_OR_NEWER
if (checkProjectFiles && HasManifestJsonLastWriteTimeChanged())
{
Client.Resolve();
}
#endif
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 32e50e97779a4753a461190076119a99
timeCreated: 1676882821

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7078f19173ceac84fb9e29b9f6175201
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System;
namespace Packages.Rider.Editor.ProjectGeneration
{
[Flags]
enum ProjectGenerationFlag
{
None = 0,
Embedded = 1,
Local = 2,
Registry = 4,
Git = 8,
BuiltIn = 16,
Unknown = 32,
PlayerAssemblies = 64,
LocalTarBall = 128,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 78af99d0156944f293b020b49a6830c2
timeCreated: 1580820569

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using UnityEditor.Compilation;
using UnityEngine;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal class ProjectPart
{
public string Name { get; }
public string OutputPath { get; }
public Assembly Assembly { get; }
public List<string> AdditionalAssets { get; }
public string[] SourceFiles { get; }
public string RootNamespace { get; }
public Assembly[] AssemblyReferences { get; }
public string[] CompiledAssemblyReferences { get; }
public string[] Defines { get; }
public ScriptCompilerOptions CompilerOptions { get; }
public ProjectPart(string name, Assembly assembly, List<string> additionalAssets)
{
Name = name;
Assembly = assembly;
AdditionalAssets = additionalAssets;
OutputPath = assembly != null ? assembly.outputPath : "Temp/Bin/Debug";
SourceFiles = assembly != null ? assembly.sourceFiles : Array.Empty<string>();
#if UNITY_2020_2_OR_NEWER
RootNamespace = assembly != null ? assembly.rootNamespace : string.Empty;
#else
RootNamespace = UnityEditor.EditorSettings.projectGenerationRootNamespace;
#endif
AssemblyReferences = assembly != null ? assembly.assemblyReferences : Array.Empty<Assembly>();
CompiledAssemblyReferences = assembly != null ? assembly.compiledAssemblyReferences : Array.Empty<string>();
Defines = assembly != null ? assembly.defines : Array.Empty<string>();
CompilerOptions = assembly != null ? assembly.compilerOptions : new ScriptCompilerOptions();
}
public List<ResponseFileData> GetResponseFileData(IAssemblyNameProvider assemblyNameProvider, string projectDirectory)
{
if (Assembly == null)
return new List<ResponseFileData>();
var data = new List<ResponseFileData>();
foreach (var responseFile in Assembly.compilerOptions.ResponseFiles)
{
var responseFileData = assemblyNameProvider.ParseResponseFile(responseFile, projectDirectory, Assembly.compilerOptions.ApiCompatibilityLevel);
foreach (var error in responseFileData.Errors)
Debug.Log($"{responseFile} Parse Error : {error}");
data.Add(responseFileData);
}
return data;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0691c2fe40564a64b3a9b7372c5eca2a
timeCreated: 1604050230

View File

@@ -0,0 +1,23 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace Packages.Rider.Editor.ProjectGeneration
{
internal static class SolutionGuidGenerator
{
public static string GuidForProject(string projectName)
{
return ComputeGuidHashFor(projectName + "salt");
}
private static string ComputeGuidHashFor(string input)
{
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(Encoding.Default.GetBytes(input));
return new Guid(hash).ToString();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3e4e7fdc19414089a0fb43e43b1bdae1
timeCreated: 1580717740

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 354fde95fe0643b09509e5fcee350b33
timeCreated: 1580716670

View File

@@ -0,0 +1,10 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Unity.Rider.Editor")]
[assembly: InternalsVisibleTo("Unity.Rider.EditorTests")]
[assembly: InternalsVisibleTo("Unity.PackageValidationSuite.Editor")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: AssemblyVersion("3.0.7")]

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8472c6472e6d4301873871a9e8fcf952
timeCreated: 1580716711

View File

@@ -0,0 +1,95 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Rider.Editor.Util;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Packages.Rider.Editor
{
internal class RiderInitializer
{
public void Initialize(string editorPath)
{
var assembly = EditorPluginInterop.EditorPluginAssembly;
if (EditorPluginInterop.EditorPluginIsLoadedFromAssets(assembly))
{
Debug.LogError($"Please delete {assembly.Location}. Unity 2019.2+ loads it directly from Rider installation. To disable this, open Rider's settings, search and uncheck 'Automatically install and update Rider's Unity editor plugin'.");
return;
}
if (assembly != null) // already loaded RIDER-92419
{
return;
}
// for debugging rider editor plugin
if (RiderPathUtil.IsRiderDevEditor(editorPath))
{
LoadEditorPluginForDevEditor(editorPath);
}
else
{
var relPath = "../../plugins/rider-unity/EditorPlugin";
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)
relPath = "Contents/plugins/rider-unity/EditorPlugin";
var baseDir = Path.Combine(editorPath, relPath);
var dllFile = new FileInfo(Path.Combine(baseDir, $"{EditorPluginInterop.EditorPluginAssemblyName}.dll"));
if (!dllFile.Exists)
dllFile = new FileInfo(Path.Combine(baseDir,
$"{EditorPluginInterop.EditorPluginAssemblyNameFallback}.dll"));
if (dllFile.Exists)
{
var bytes = File.ReadAllBytes(dllFile.FullName);
assembly = AppDomain.CurrentDomain.Load(bytes); // doesn't lock assembly on disk
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log($"Rider EditorPlugin loaded from {dllFile.FullName}");
EditorPluginInterop.InitEntryPoint(assembly);
}
else
{
Debug.Log($"Unable to find Rider EditorPlugin {dllFile.FullName} for Unity ");
}
}
}
private static void LoadEditorPluginForDevEditor(string editorPath)
{
var file = new FileInfo(editorPath);
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)
file = new FileInfo(Path.Combine(editorPath, "rider-dev.bat"));
if (!file.Exists)
{
Debug.Log($"Unable to determine path to EditorPlugin from {file}");
return;
}
var dllPath = File.ReadLines(file.FullName).FirstOrDefault();
if (dllPath == null)
{
Debug.Log($"Unable to determine path to EditorPlugin from {file}");
return;
}
var dllFile = new FileInfo(dllPath);
if (!dllFile.Exists)
{
Debug.Log($"Unable to find Rider EditorPlugin {dllPath} for Unity ");
return;
}
var assembly = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(dllFile.FullName));
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log($"Rider EditorPlugin loaded from {dllFile.FullName}");
EditorPluginInterop.InitEntryPoint(assembly);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5a0cc9645f0e2d4fb816156dcf3f4dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,454 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using JetBrains.Rider.PathLocator;
using Packages.Rider.Editor.ProjectGeneration;
using Packages.Rider.Editor.Util;
using Unity.CodeEditor;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
using OperatingSystemFamily = UnityEngine.OperatingSystemFamily;
namespace Packages.Rider.Editor
{
[InitializeOnLoad]
internal class RiderScriptEditor : IExternalCodeEditor
{
IDiscovery m_Discoverability;
static IGenerator m_ProjectGeneration;
RiderInitializer m_Initiliazer = new RiderInitializer();
static RiderScriptEditor m_RiderScriptEditor;
static RiderScriptEditor()
{
try
{
// todo: make ProjectGeneration lazy
var projectGeneration = new ProjectGeneration.ProjectGeneration();
m_RiderScriptEditor = new RiderScriptEditor(new Discovery(), projectGeneration);
// preserve the order here, otherwise on startup, project generation Sync would happen multiple times
CodeEditor.Register(m_RiderScriptEditor);
InitializeInternal(CurrentEditor);
// end of "preserve the order here"
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private static void ShowWarningOnUnexpectedScriptEditor(string path)
{
// Show warning, when Unity was started from Rider, but external editor is different https://github.com/JetBrains/resharper-unity/issues/1127
try
{
var args = Environment.GetCommandLineArgs();
var commandlineParser = new CommandLineParser(args);
if (commandlineParser.Options.ContainsKey("-riderPath"))
{
var originRiderPath = commandlineParser.Options["-riderPath"];
var originRealPath = GetEditorRealPath(originRiderPath);
var originVersion = Discovery.RiderPathLocator.GetBuildNumber(originRealPath);
var version = Discovery.RiderPathLocator.GetBuildNumber(path);
if (originVersion != null && originVersion != version)
{
Debug.LogWarning("Unity was started by a version of Rider that is not the current default external editor. Advanced integration features cannot be enabled.");
Debug.Log($"Unity was started by Rider {originVersion}, but external editor is set to: {path}");
}
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
internal static string GetEditorRealPath(string path)
{
if (string.IsNullOrEmpty(path))
return path;
if (!FileSystemUtil.EditorPathExists(path))
return path;
if (SystemInfo.operatingSystemFamily != OperatingSystemFamily.Windows)
{
var realPath = FileSystemUtil.GetFinalPathName(path);
// case of snap installation
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Linux)
{
if (new FileInfo(path).Name.ToLowerInvariant() == "rider" &&
new FileInfo(realPath).Name.ToLowerInvariant() == "snap")
{
var snapInstallPath = "/snap/rider/current/bin/rider.sh";
if (new FileInfo(snapInstallPath).Exists)
return snapInstallPath;
}
}
// in case of symlink
return realPath;
}
return new FileInfo(path).FullName;
}
public RiderScriptEditor(IDiscovery discovery, IGenerator projectGeneration)
{
m_Discoverability = discovery;
m_ProjectGeneration = projectGeneration;
}
public void OnGUI()
{
GUILayout.BeginHorizontal();
var style = GUI.skin.label;
var text = "Customize handled extensions in";
EditorGUILayout.LabelField(text, style, GUILayout.Width(style.CalcSize(new GUIContent(text)).x));
if (PluginSettings.LinkButton("Project Settings | Editor | Additional extensions to include"))
{
SettingsService.OpenProjectSettings("Project/Editor"); // how do I focus "Additional extensions to include"?
}
GUILayout.EndHorizontal();
EditorGUILayout.LabelField("Generate .csproj files for:");
EditorGUI.indentLevel++;
SettingsButton(ProjectGenerationFlag.Embedded, "Embedded packages", "");
SettingsButton(ProjectGenerationFlag.Local, "Local packages", "");
SettingsButton(ProjectGenerationFlag.Registry, "Registry packages", "");
SettingsButton(ProjectGenerationFlag.Git, "Git packages", "");
SettingsButton(ProjectGenerationFlag.BuiltIn, "Built-in packages", "");
#if UNITY_2019_3_OR_NEWER
SettingsButton(ProjectGenerationFlag.LocalTarBall, "Local tarball", "");
#endif
SettingsButton(ProjectGenerationFlag.Unknown, "Packages from unknown sources", "");
SettingsButton(ProjectGenerationFlag.PlayerAssemblies, "Player projects", "For each player project generate an additional csproj with the name 'project-player.csproj'");
RegenerateProjectFiles();
EditorGUI.indentLevel--;
}
void RegenerateProjectFiles()
{
var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(new GUILayoutOption[] {}));
rect.width = 252;
if (GUI.Button(rect, "Regenerate project files"))
{
m_ProjectGeneration.Sync();
}
}
void SettingsButton(ProjectGenerationFlag preference, string guiMessage, string toolTip)
{
var prevValue = m_ProjectGeneration.AssemblyNameProvider.ProjectGenerationFlag.HasFlag(preference);
var newValue = EditorGUILayout.Toggle(new GUIContent(guiMessage, toolTip), prevValue);
if (newValue != prevValue)
{
m_ProjectGeneration.AssemblyNameProvider.ToggleProjectGeneration(preference);
}
}
public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles,
string[] importedFiles)
{
m_ProjectGeneration.SyncIfNeeded(addedFiles.Union(deletedFiles).Union(movedFiles).Union(movedFromFiles),
importedFiles);
}
public void SyncAll()
{
m_ProjectGeneration.Sync();
}
[UsedImplicitly]
public static void SyncSolution() // generate-the-sln-file-via-script-or-command-line
{
m_ProjectGeneration.Sync();
}
[UsedImplicitly] // called from Rider EditorPlugin with reflection
public static void SyncIfNeeded(bool checkProjectFiles)
{
AssetDatabase.Refresh();
m_ProjectGeneration.SyncIfNeeded(new string[] { }, new string[] { }, checkProjectFiles);
}
[UsedImplicitly]
public static void SyncSolutionAndOpenExternalEditor()
{
m_ProjectGeneration.Sync();
CodeEditor.CurrentEditor.OpenProject();
}
/// <summary>
/// In 2020.x is called each time ExternalEditor is changed
/// In 2021.x+ is called each time ExternalEditor is changed and also on each appdomain reload
/// </summary>
/// <param name="editorInstallationPath"></param>
public void Initialize(string editorInstallationPath)
{
var prevEditorVersion = RiderScriptEditorData.instance.prevEditorBuildNumber.ToVersion();
RiderScriptEditorData.instance.Invalidate(editorInstallationPath, true);
// previous editor did not have EditorPlugin
// just load the EditorPlugin
if (EditorPluginInterop.EditorPluginAssembly == null)
{
InitializeInternal(editorInstallationPath);
return;
}
// previous editor was Rider with a different version
// need to load new Editor plugin
if (prevEditorVersion != null && prevEditorVersion != RiderScriptEditorData.instance.editorBuildNumber.ToVersion()) // in Unity 2019.3 any change in preference causes `Initialize` call
{
#if UNITY_2019_3_OR_NEWER
EditorUtility.RequestScriptReload(); // EditorPlugin would get loaded
#else
UnityEditorInternal.InternalEditorUtility.RequestScriptReload();
#endif
}
}
private static void InitializeInternal(string currentEditorPath)
{
var path = GetEditorRealPath(currentEditorPath);
if (IsRiderOrFleetInstallation(path))
{
var installations = new HashSet<RiderPathLocator.RiderInfo>();
if (RiderScriptEditorData.instance.installations != null)
{
foreach (var info in RiderScriptEditorData.instance.installations)
{
installations.Add(info);
}
}
if (!RiderScriptEditorData.instance.initializedOnce || !FileSystemUtil.EditorPathExists(path))
{
foreach (var item in Discovery.RiderPathLocator.GetAllRiderPaths())
{
installations.Add(item);
}
// is likely outdated
if (installations.All(a => GetEditorRealPath(a.Path) != path))
{
if (Discovery.RiderPathLocator.GetIsToolbox(path)) // is toolbox 1.x - update
{
var toolboxInstallations = installations.Where(a => a.IsToolbox).ToArray();
if (toolboxInstallations.Any())
{
var newEditor = toolboxInstallations.OrderBy(a => a.BuildNumber).Last().Path;
CodeEditor.SetExternalScriptEditor(newEditor);
path = newEditor;
}
else if (installations.Any())
{
var newEditor = installations.OrderBy(a => a.BuildNumber).Last().Path;
CodeEditor.SetExternalScriptEditor(newEditor);
path = newEditor;
}
}
else if (installations.Any()) // is non toolbox 1.x
{
if (!FileSystemUtil.EditorPathExists(path)) // previously used rider was removed
{
var newEditor = installations.OrderBy(a => a.BuildNumber).Last().Path;
CodeEditor.SetExternalScriptEditor(newEditor);
path = newEditor;
}
else // notify
{
var newEditorName = installations.OrderBy(a => a.BuildNumber).Last().Presentation;
Debug.LogWarning($"Consider updating External Editor in Unity to {newEditorName}.");
}
}
}
ShowWarningOnUnexpectedScriptEditor(path);
RiderScriptEditorData.instance.initializedOnce = true;
}
if (FileSystemUtil.EditorPathExists(path) && installations.All(a => a.Path != path)) // custom location
{
var info = new RiderPathLocator.RiderInfo(Discovery.RiderPathLocator, path, Discovery.RiderPathLocator.GetIsToolbox(path));
installations.Add(info);
}
RiderScriptEditorData.instance.installations = installations.ToArray();
RiderScriptEditorData.instance.Init();
m_RiderScriptEditor.CreateSolutionIfDoesntExist();
if (RiderScriptEditorData.instance.shouldLoadEditorPlugin)
{
m_RiderScriptEditor.m_Initiliazer.Initialize(path);
}
// can't switch to non-deprecated api, because UnityEditor.Build.BuildPipelineInterfaces.processors is internal
#pragma warning disable 618
EditorUserBuildSettings.activeBuildTargetChanged += () =>
#pragma warning restore 618
{
RiderScriptEditorData.instance.hasChanges = true;
};
}
}
public bool OpenProject(string path, int line, int column)
{
var projectGeneration = (ProjectGeneration.ProjectGeneration) m_ProjectGeneration;
// Assets - Open C# Project passes empty path here
if (path != "" && !projectGeneration.HasValidExtension(path))
{
return false;
}
if (!IsUnityScript(path))
{
m_ProjectGeneration.SyncIfNeeded(affectedFiles: new string[] { }, new string[] { });
var fastOpenResult = EditorPluginInterop.OpenFileDllImplementation(path, line, column);
if (fastOpenResult)
return true;
}
var slnFile = GetSolutionFile(path);
return Discovery.RiderFileOpener.OpenFile(CurrentEditor, slnFile, path, line, column);
}
private string GetSolutionFile(string path)
{
if (IsUnityScript(path))
{
return Path.Combine(GetBaseUnityDeveloperFolder(), "Projects/CSharp/Unity.CSharpProjects.gen.sln");
}
var solutionFile = m_ProjectGeneration.SolutionFile();
if (File.Exists(solutionFile))
{
return solutionFile;
}
return "";
}
static bool IsUnityScript(string path)
{
if (UnityEditor.Unsupported.IsDeveloperBuild())
{
var baseFolder = GetBaseUnityDeveloperFolder().Replace("\\", "/");
var lowerPath = path.ToLowerInvariant().Replace("\\", "/");
if (lowerPath.Contains((baseFolder + "/Runtime").ToLowerInvariant())
|| lowerPath.Contains((baseFolder + "/Editor").ToLowerInvariant()))
{
return true;
}
}
return false;
}
static string GetBaseUnityDeveloperFolder()
{
return Directory.GetParent(EditorApplication.applicationPath).Parent.Parent.FullName;
}
public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation)
{
installation = default;
if (string.IsNullOrEmpty(editorPath)) return false;
if (FileSystemUtil.EditorPathExists(editorPath) && IsRiderOrFleetInstallation(editorPath))
{
if (RiderScriptEditorData.instance.installations == null) // the case when other CodeEditor is set from the very Unity start
{
RiderScriptEditorData.instance.installations = Discovery.RiderPathLocator.GetAllRiderPaths();
}
var realPath = GetEditorRealPath(editorPath);
var editor = RiderScriptEditorData.instance.installations.FirstOrDefault(a => GetEditorRealPath(a.Path) == realPath);
if (editor.Path != null)
{
installation = new CodeEditor.Installation
{
Name = editor.Presentation,
Path = editor.Path
};
return true;
}
installation = new CodeEditor.Installation
{
Name = "Rider (custom location)",
Path = editorPath
};
return true;
}
return false;
}
public static bool IsRiderOrFleetInstallation(string path)
{
if (IsAssetImportWorkerProcess())
return false;
#if UNITY_2021_1_OR_NEWER
if (UnityEditor.MPE.ProcessService.level == UnityEditor.MPE.ProcessLevel.Secondary)
return false;
#elif UNITY_2020_2_OR_NEWER
if (UnityEditor.MPE.ProcessService.level == UnityEditor.MPE.ProcessLevel.Slave)
return false;
#elif UNITY_2020_1_OR_NEWER
if (Unity.MPE.ProcessService.level == Unity.MPE.ProcessLevel.UMP_SLAVE)
return false;
#endif
if (string.IsNullOrEmpty(path))
return false;
return ExecutableStartsWith(path, "rider") || ExecutableStartsWith(path, "fleet");
}
public static bool ExecutableStartsWith(string path, string input)
{
var fileInfo = new FileInfo(path);
var filename = fileInfo.Name;
return filename.StartsWith(input, StringComparison.OrdinalIgnoreCase);
}
private static bool IsAssetImportWorkerProcess()
{
#if UNITY_2020_2_OR_NEWER
return UnityEditor.AssetDatabase.IsAssetImportWorkerProcess();
#elif UNITY_2019_3_OR_NEWER
return UnityEditor.Experimental.AssetDatabaseExperimental.IsAssetImportWorkerProcess();
#else
return false;
#endif
}
public static string CurrentEditor // works fast, doesn't validate if executable really exists
=> EditorPrefs.GetString("kScriptsDefaultApp");
public CodeEditor.Installation[] Installations => m_Discoverability.PathCallback();
private void CreateSolutionIfDoesntExist()
{
if (!m_ProjectGeneration.HasSolutionBeenGenerated())
{
m_ProjectGeneration.Sync();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4095d72f77fbb64ea39b8b3ca246622
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
using System;
using System.Linq;
using JetBrains.Rider.PathLocator;
using Packages.Rider.Editor.Util;
using Rider.Editor.Util;
using UnityEditor;
using UnityEngine;
namespace Packages.Rider.Editor
{
internal class RiderScriptEditorData : ScriptableSingleton<RiderScriptEditorData>
{
// activeBuildTargetChanged has changed
// making it true by default would cause multiple Sync projects on the startup
[SerializeField] internal bool hasChanges;
[SerializeField] internal bool shouldLoadEditorPlugin;
[SerializeField] internal bool initializedOnce;
[SerializeField] internal SerializableVersion editorBuildNumber;
[SerializeField] internal SerializableVersion prevEditorBuildNumber;
[SerializeField] internal RiderPathLocator.RiderInfo[] installations;
[SerializeField] internal string[] activeScriptCompilationDefines;
public void Init()
{
if (editorBuildNumber == null)
{
Invalidate(RiderScriptEditor.CurrentEditor);
}
}
public void InvalidateSavedCompilationDefines()
{
activeScriptCompilationDefines = EditorUserBuildSettings.activeScriptCompilationDefines;
}
public bool HasChangesInCompilationDefines()
{
if (activeScriptCompilationDefines == null)
return false;
return !EditorUserBuildSettings.activeScriptCompilationDefines.SequenceEqual(activeScriptCompilationDefines);
}
public void Invalidate(string editorInstallationPath, bool shouldInvalidatePrevEditorBuildNumber = false)
{
var riderBuildNumber = Discovery.RiderPathLocator.GetBuildNumber(editorInstallationPath);
editorBuildNumber = riderBuildNumber.ToSerializableVersion();
if (shouldInvalidatePrevEditorBuildNumber)
prevEditorBuildNumber = editorBuildNumber;
if (riderBuildNumber == null) // if we fail to parse for some reason
shouldLoadEditorPlugin = true;
shouldLoadEditorPlugin = riderBuildNumber >= new Version("191.7141.156");
if (RiderPathUtil.IsRiderDevEditor(editorInstallationPath))
{
shouldLoadEditorPlugin = true;
editorBuildNumber = new SerializableVersion(new Version("999.999.999.999"));
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f079e3afd077fb94fa2bda74d6409499
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using System;
using UnityEditor;
using UnityEngine;
namespace Packages.Rider.Editor
{
#if UNITY_2020_1_OR_NEWER // API doesn't exist in 2019.4
[FilePath("Library/com.unity.ide.rider/PersistedState.asset", FilePathAttribute.Location.ProjectFolder)]
#endif
internal class RiderScriptEditorPersistedState : ScriptableSingleton<RiderScriptEditorPersistedState>
{
[SerializeField] private long lastWriteTicks;
[SerializeField] private long manifestJsonLastWriteTicks;
public DateTime? LastWrite
{
get => DateTime.FromBinary(lastWriteTicks);
set
{
if (!value.HasValue) return;
lastWriteTicks = value.Value.ToBinary();
Save(true);
}
}
public DateTime? ManifestJsonLastWrite
{
get => DateTime.FromBinary(manifestJsonLastWriteTicks);
set
{
if (!value.HasValue) return;
manifestJsonLastWriteTicks = value.Value.ToBinary();
Save(true);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc3a27147f944790916176e2172ad506
timeCreated: 1645618940

View File

@@ -0,0 +1,23 @@
using UnityEditor;
using UnityEngine;
namespace Packages.Rider.Editor
{
internal static class RiderStyles
{
static RiderStyles()
{
LinkLabelStyle = new GUIStyle(EditorStyles.linkLabel)
{
padding = GUI.skin.label.padding,
margin = GUI.skin.label.margin
};
LinkLabelStyle.padding.left = 0;
LinkLabelStyle.padding.right = 0;
LinkLabelStyle.margin.left = 0;
LinkLabelStyle.margin.right = 0;
}
public static readonly GUIStyle LinkLabelStyle;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 56f347f155204ffebacb6ed6f4a4e65f
timeCreated: 1617893911

View File

@@ -0,0 +1,16 @@
using JetBrains.Annotations;
using UnityEditor;
namespace JetBrains.Rider.Unity.Editor
{
// Do not rename this class while you don't rename startup command for dotTrace profiler
[UsedImplicitly]
internal static class StartUpMethodExecutor
{
[UsedImplicitly]
public static void EnterPlayMode()
{
EditorApplication.isPlaying = true;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e7c145f2cd3c411ca7f50ebc5f5a6d24
timeCreated: 1670946079

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a52391bc44c477f40a547ed4ef3b9560
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
#if TEST_FRAMEWORK
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEditor;
namespace Packages.Rider.Editor.UnitTesting
{
internal class CallbackData : ScriptableSingleton<CallbackData>
{
/// <summary>
/// identifies that tests were started from Rider
/// </summary>
public bool isRider;
[UsedImplicitly] // Is used by Rider Unity plugin by reflection
public static event EventHandler Changed = (sender, args) => { };
internal void RaiseChangedEvent()
{
Changed(null, EventArgs.Empty);
}
[UsedImplicitly] // Is used by Rider Unity plugin by reflection
public List<TestEvent> events = new List<TestEvent>();
[UsedImplicitly] // Is used by Rider Unity plugin by reflection
public void Clear()
{
events.Clear();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 010246a07de7cb34185a2a7b1c1fad59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
#if TEST_FRAMEWORK
using UnityEditor;
using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine;
namespace Packages.Rider.Editor.UnitTesting
{
[InitializeOnLoad]
internal static class CallbackInitializer
{
static CallbackInitializer()
{
if (CallbackData.instance.isRider)
ScriptableObject.CreateInstance<TestRunnerApi>().RegisterCallbacks(ScriptableObject.CreateInstance<TestsCallback>(), 0);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa1c6b1a353ab464782fc1e7c051eb02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
using JetBrains.Annotations;
using UnityEngine;
#if TEST_FRAMEWORK
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.TestTools.TestRunner.Api;
#else
using System;
#endif
namespace Packages.Rider.Editor.UnitTesting
{
/// <summary>
/// Is called by Rider Unity plugin via reflections
/// </summary>
[UsedImplicitly]
public static class RiderTestRunner
{
#if TEST_FRAMEWORK
private static readonly TestsCallback Callback = ScriptableObject.CreateInstance<TestsCallback>();
private static string _sessionGuid;
#endif
/// <summary>
/// Is called by Rider Unity plugin via reflections
/// </summary>
/// <param name="sessionId"></param>
/// <param name="testMode"></param>
/// <param name="assemblyNames"></param>
/// <param name="testNames"></param>
/// <param name="categoryNames"></param>
/// <param name="groupNames"></param>
/// <param name="buildTarget"></param>
/// <param name="callbacksHandlerCodeBase"></param>
/// <param name="callbacksHandlerTypeName"></param>
/// <param name="callbacksHandlerDependencies"></param>
[UsedImplicitly]
public static void RunTestsWithSyncCallbacks(string sessionId, int testMode, string[] assemblyNames,
string[] testNames, string[] categoryNames, string[] groupNames, int? buildTarget,
string callbacksHandlerCodeBase, string callbacksHandlerTypeName, string[] callbacksHandlerDependencies)
{
#if !TEST_FRAMEWORK
Debug.LogError("Update Test Framework package to v.1.1.8+ to run tests from Rider.");
throw new NotSupportedException("Incompatible `Test Framework` package in Unity. Update to v.1.1.8+");
#else
SyncTestRunEventsHandler.instance.InitRun(sessionId, callbacksHandlerCodeBase, callbacksHandlerTypeName, callbacksHandlerDependencies);
RunTests(testMode, assemblyNames, testNames, categoryNames, groupNames, buildTarget);
#endif
}
/// <summary>
/// Is called by Rider Unity plugin via reflections
/// </summary>
/// <param name="testMode"></param>
/// <param name="assemblyNames"></param>
/// <param name="testNames"></param>
/// <param name="categoryNames"></param>
/// <param name="groupNames"></param>
/// <param name="buildTarget"></param>
[UsedImplicitly]
public static void RunTests(int testMode, string[] assemblyNames, string[] testNames, string[] categoryNames, string[] groupNames, int? buildTarget)
{
#if !TEST_FRAMEWORK
Debug.LogError("Update Test Framework package to v.1.1.8+ to run tests from Rider.");
throw new NotSupportedException("Incompatible `Test Framework` package in Unity. Update to v.1.1.8+");
#else
CallbackData.instance.isRider = true;
var api = ScriptableObject.CreateInstance<TestRunnerApi>();
var settings = new ExecutionSettings();
var filter = new Filter
{
assemblyNames = assemblyNames,
testNames = testNames,
categoryNames = categoryNames,
groupNames = groupNames,
targetPlatform = (BuildTarget?) buildTarget
};
if (testMode > 0) // for future use - test-framework would allow running both Edit and Play test at once
{
filter.testMode = (TestMode) testMode;
}
api.RetrieveTestList(filter.testMode, adaptor =>
{
// start tests if there any, otherwise send a RunFinished signal // see RIDER-91705
if (adaptor.Children.Any(a => a.IsTestAssembly && assemblyNames.Contains(Path.GetFileNameWithoutExtension(a.Name))))
{
settings.filters = new[]
{
filter
};
_sessionGuid = api.Execute(settings);
api.UnregisterCallbacks(Callback); // avoid multiple registrations
api.RegisterCallbacks(Callback); // receive information about when the test suite and individual tests starts and stops.
}
else
{
CallbackData.instance.isRider = false;
CallbackData.instance.events.Add(
new TestEvent(EventType.RunFinished, "", "", "", 0, NUnit.Framework.Interfaces.TestStatus.Inconclusive, ""));
CallbackData.instance.RaiseChangedEvent();
}
});
#endif
}
[UsedImplicitly]
internal static void CancelTestRun()
{
#if !TEST_FRAMEWORK
Debug.LogError("Update Test Framework package to v.1.1.8+ to run tests from Rider.");
throw new NotSupportedException("Incompatible `Test Framework` package in Unity. Update to v.1.1.8+");
#else
var methodInfo = typeof(TestRunnerApi).GetMethod("CancelTestRun");
if (methodInfo == null)
methodInfo = typeof(TestRunnerApi).GetMethod("CancelTestRun", BindingFlags.Static | BindingFlags.NonPublic);
methodInfo.Invoke(null, new object[] { _sessionGuid });
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c3b27069cb3ddf42ba1260eeefcdd1c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
#if TEST_FRAMEWORK
using NUnit.Framework.Interfaces;
using Packages.Rider.Editor.UnitTesting;
using UnityEngine.TestRunner;
[assembly: TestRunCallback(typeof(SyncTestRunCallback))]
namespace Packages.Rider.Editor.UnitTesting
{
internal class SyncTestRunCallback : ITestRunCallback
{
public void RunStarted(ITest testsToRun)
{
}
public void RunFinished(ITestResult testResults)
{
SyncTestRunEventsHandler.instance.OnRunFinished();
}
public void TestStarted(ITest test)
{
if (!test.IsSuite)
SyncTestRunEventsHandler.instance.OnTestStarted(GenerateId(test));
}
public void TestFinished(ITestResult result)
{
if (!result.Test.IsSuite)
SyncTestRunEventsHandler.instance.OnTestFinished();
}
// https://jetbrains.team/p/net/code/dotnet-libs/files/f04cde7d1dd70ee13bf5532e30f929b9b5ed08a4/ReSharperTestRunner/src/Adapters/TestRunner.Adapters.NUnit3/RemoteTaskDepot.cs?tab=source&line=129
private static string GenerateId(ITest node)
{
// ES: Parameterized tests defined in a parametrized test fixture, though
// constructed for a particular test fixture with the given parameter, have identical fullname that does
// not include parameters of parent testfixture (name of the without parameters is used instead).
// This leads to 'Test with {id} id is already running' message.
var typeName = node.GetType().Name;
if (typeName == "ParameterizedMethod" ||
typeName == "GenericMethod")
return $"{node.Parent.FullName}.{node.Name}";
return node.FullName;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58ab3828fb407c742a48b82bc5983a87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,148 @@
#if TEST_FRAMEWORK
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Packages.Rider.Editor.UnitTesting
{
internal class SyncTestRunEventsHandler : ScriptableSingleton<SyncTestRunEventsHandler>
{
[SerializeField] private string m_SessionId;
[SerializeField] private string m_HandlerCodeBase;
[SerializeField] private string m_HandlerTypeName;
[SerializeField] private string[] m_HandlerDependencies;
[SerializeField] private bool m_RunInitialized;
private object m_Handler;
private MethodInfo m_OnSessionStartedMethodInfo;
private MethodInfo m_OnTestStartedMethodInfo;
private MethodInfo m_OnTestFinishedMethodInfo;
private MethodInfo m_OnSessionFinishedMethodInfo;
internal void InitRun(string sessionId, string handlerCodeBase, string handlerTypeName, string[] handlerDependencies)
{
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log("Rider Test Runner: initializing sync callbacks handler: " +
$"sessionId={sessionId}, " +
$"codeBase={handlerCodeBase}, " +
$"typeName={handlerTypeName}, " +
$"dependencies={(handlerDependencies == null ? "" : string.Join("; ", handlerDependencies))}");
m_SessionId = sessionId;
m_HandlerCodeBase = handlerCodeBase;
m_HandlerTypeName = handlerTypeName;
m_HandlerDependencies = handlerDependencies;
m_RunInitialized = true;
CreateHandlerInstance();
SafeInvokeHandlerMethod(m_OnSessionStartedMethodInfo, Array.Empty<object>());
}
private void OnEnable()
{
if (m_RunInitialized)
CreateHandlerInstance();
}
internal void OnTestStarted(string testId)
{
if (m_RunInitialized)
SafeInvokeHandlerMethod(m_OnTestStartedMethodInfo, new object[] {testId});
}
internal void OnTestFinished()
{
if (m_RunInitialized)
SafeInvokeHandlerMethod(m_OnTestFinishedMethodInfo, Array.Empty<object>());
}
internal void OnRunFinished()
{
if (!m_RunInitialized)
return;
SafeInvokeHandlerMethod(m_OnSessionFinishedMethodInfo, Array.Empty<object>());
CleanUp();
m_RunInitialized = false;
}
private void SafeInvokeHandlerMethod(MethodInfo methodInfo, object[] args)
{
try
{
methodInfo?.Invoke(m_Handler, args);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void CreateHandlerInstance()
{
try
{
if (m_HandlerDependencies != null)
foreach (var dependency in m_HandlerDependencies)
{
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log($"Rider Test Runner: loading assembly from {dependency}");
Assembly.LoadFrom(dependency);
}
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log($"Rider Test Runner: loading assembly from {m_HandlerCodeBase}");
var assembly = Assembly.LoadFrom(m_HandlerCodeBase);
var type = assembly.GetType(m_HandlerTypeName);
if (type == null)
{
Debug.LogError($"Rider Test Runner: type '{m_HandlerTypeName}' not found in assembly '{assembly.FullName}'");
return;
}
if (PluginSettings.SelectedLoggingLevel >= LoggingLevel.TRACE)
Debug.Log($"Rider Test Runner: creating instance of type '{type.AssemblyQualifiedName}'");
m_Handler = Activator.CreateInstance(type, m_SessionId);
m_OnSessionStartedMethodInfo = type.GetMethod("OnSessionStarted", BindingFlags.Instance | BindingFlags.Public);
if (m_OnSessionStartedMethodInfo == null)
{
Debug.LogError($"Rider Test Runner: OnSessionStarted method not found in type='{type.AssemblyQualifiedName}'");
return;
}
m_OnTestStartedMethodInfo = type.GetMethod("OnTestStarted", BindingFlags.Instance | BindingFlags.Public);
if (m_OnTestStartedMethodInfo == null)
{
Debug.LogError($"Rider Test Runner: OnTestStarted method not found in type='{type.AssemblyQualifiedName}'");
return;
}
m_OnTestFinishedMethodInfo = type.GetMethod("OnTestFinished", BindingFlags.Instance | BindingFlags.Public);
if (m_OnTestFinishedMethodInfo == null)
{
Debug.LogError($"Rider Test Runner: OnTestFinished method not found in type='{type.AssemblyQualifiedName}'");
return;
}
m_OnSessionFinishedMethodInfo = type.GetMethod("OnSessionFinished", BindingFlags.Instance | BindingFlags.Public);
if (m_OnSessionFinishedMethodInfo == null)
Debug.LogError($"Rider Test Runner: OnSessionFinished method not found in type='{type.AssemblyQualifiedName}'");
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void CleanUp()
{
m_Handler = null;
m_OnSessionStartedMethodInfo = null;
m_OnSessionFinishedMethodInfo = null;
m_OnTestStartedMethodInfo = null;
m_OnTestFinishedMethodInfo = null;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48483563a64de3a4e8690122762055f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
#if TEST_FRAMEWORK
using System;
using NUnit.Framework.Interfaces;
namespace Packages.Rider.Editor.UnitTesting
{
/// <summary>
/// Is used by Rider Unity plugin by reflection
/// </summary>
[Serializable]
internal enum EventType { TestStarted, TestFinished, RunFinished, RunStarted } // do not reorder
/// <summary>
/// Is used by Rider Unity plugin by reflection
/// </summary>
[Serializable]
internal class TestEvent
{
public EventType type;
public string id;
public string assemblyName;
public string output;
public TestStatus testStatus;
public double duration;
public string parentId;
public TestEvent(EventType type, string id, string assemblyName, string output, double duration, TestStatus testStatus, string parentID)
{
this.type = type;
this.id = id;
this.assemblyName = assemblyName;
this.output = output;
this.testStatus = testStatus;
this.duration = duration;
parentId = parentID;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9413c47b3a14a64e8810ce76d1a6032
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
#if TEST_FRAMEWORK
using System;
using System.Linq;
using System.Text;
using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine;
namespace Packages.Rider.Editor.UnitTesting
{
internal class TestsCallback : ScriptableObject, IErrorCallbacks
{
public void RunFinished(ITestResultAdaptor result)
{
CallbackData.instance.isRider = false;
CallbackData.instance.events.Add(
new TestEvent(EventType.RunFinished, "", "","", 0, ParseTestStatus(result.TestStatus), ""));
CallbackData.instance.RaiseChangedEvent();
}
public void RunStarted(ITestAdaptor testsToRun)
{
CallbackData.instance.events.Add(
new TestEvent(EventType.RunStarted, "", "","", 0, NUnit.Framework.Interfaces.TestStatus.Passed, ""));
CallbackData.instance.RaiseChangedEvent();
}
public void TestStarted(ITestAdaptor result)
{
// RIDER-69927 "Test not run" status is shown for the test suite when running unit tests for Unity project
var method = result.Method ?? result.Children.Select(a=>a.Method).FirstOrDefault(b => b != null);
if (method == null) return;
CallbackData.instance.events.Add(
new TestEvent(EventType.TestStarted, GenerateId(result), method.TypeInfo.Assembly.GetName().Name, "", 0, NUnit.Framework.Interfaces.TestStatus.Passed, GenerateId(result.Parent)));
CallbackData.instance.RaiseChangedEvent();
}
public void TestFinished(ITestResultAdaptor result)
{
var method = result.Test.Method ?? result.Children.Select(a=>a.Test.Method).FirstOrDefault(b => b != null);
if (method == null) return;
CallbackData.instance.events.Add(
new TestEvent(EventType.TestFinished, GenerateId(result.Test), method.TypeInfo.Assembly.GetName().Name, ExtractOutput(result), (result.EndTime-result.StartTime).Milliseconds, ParseTestStatus(result.TestStatus), GenerateId(result.Test.Parent)));
CallbackData.instance.RaiseChangedEvent();
}
public void OnError(string message)
{
CallbackData.instance.isRider = false;
CallbackData.instance.events.Add(
new TestEvent(EventType.RunFinished, "", "",message, 0, NUnit.Framework.Interfaces.TestStatus.Failed, ""));
CallbackData.instance.RaiseChangedEvent();
}
// see explanation in https://jetbrains.team/p/net/code/dotnet-libs/files/f04cde7d1dd70ee13bf5532e30f929b9b5ed08a4/ReSharperTestRunner/src/Adapters/TestRunner.Adapters.NUnit3/RemoteTaskDepot.cs?tab=source&line=129
private static string GenerateId(ITestAdaptor node)
{
// ES: Parameterized tests defined in a parametrized test fixture, though
// constructed for a particular test fixture with the given parameter, have identical fullname that does
// not include parameters of parent testfixture (name of the without parameters is used instead).
// This leads to 'Test with {id} id is already running' message.
if (node.TypeInfo == null)
return $"{node.Parent.FullName}.{node.Name}";
return node.FullName;
}
private static NUnit.Framework.Interfaces.TestStatus ParseTestStatus(TestStatus testStatus)
{
return (NUnit.Framework.Interfaces.TestStatus)Enum.Parse(typeof(NUnit.Framework.Interfaces.TestStatus), testStatus.ToString());
}
private static string ExtractOutput(ITestResultAdaptor testResult)
{
var stringBuilder = new StringBuilder();
if (testResult.Message != null)
{
stringBuilder.AppendLine("Message: ");
stringBuilder.AppendLine(testResult.Message);
}
if (!string.IsNullOrEmpty(testResult.Output))
{
stringBuilder.AppendLine("Output: ");
stringBuilder.AppendLine(testResult.Output);
}
if (!string.IsNullOrEmpty(testResult.StackTrace))
{
stringBuilder.AppendLine("Stacktrace: ");
stringBuilder.AppendLine(testResult.StackTrace);
}
var result = stringBuilder.ToString();
if (result.Length > 0)
return result;
return testResult.Output ?? string.Empty;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58aa570dbe0761f43b25ff6c2265bbe2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5e726086cd652f82087d59d67d2c24cd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
namespace Packages.Rider.Editor.Util
{
internal class CommandLineParser
{
public Dictionary<string, string> Options = new Dictionary<string, string>();
public CommandLineParser(string[] args)
{
var i = 0;
while (i < args.Length)
{
var arg = args[i];
if (!arg.StartsWith("-"))
{
i++;
continue;
}
string value = null;
if (i + 1 < args.Length && !args[i + 1].StartsWith("-"))
{
value = args[i + 1];
i++;
}
if (!(Options.ContainsKey(arg)))
{
Options.Add(arg, value);
}
i++;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 154ace4bd16de9f4e84052ac257786d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using JetBrains.Annotations;
using UnityEngine;
namespace Packages.Rider.Editor.Util
{
internal static class FileSystemUtil
{
[NotNull]
public static string GetFinalPathName([NotNull] string path)
{
if (path == null) throw new ArgumentNullException("path");
// up to MAX_PATH. MAX_PATH on Linux currently 4096, on Mac OS X 1024
// doc: http://man7.org/linux/man-pages/man3/realpath.3.html
var sb = new StringBuilder(8192);
var result = LibcNativeInterop.realpath(path, sb);
if (result == IntPtr.Zero)
{
throw new Win32Exception($"{path} was not resolved.");
}
return new FileInfo(sb.ToString()).FullName;
}
public static string FileNameWithoutExtension(string path)
{
if (string.IsNullOrEmpty(path))
{
return "";
}
var indexOfDot = -1;
var indexOfSlash = 0;
for (var i = path.Length - 1; i >= 0; i--)
{
if (indexOfDot == -1 && path[i] == '.')
{
indexOfDot = i;
}
if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\')
{
indexOfSlash = i + 1;
break;
}
}
if (indexOfDot == -1)
{
indexOfDot = path.Length;
}
return path.Substring(indexOfSlash, indexOfDot - indexOfSlash);
}
public static bool EditorPathExists(string editorPath)
{
return SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX && new DirectoryInfo(editorPath).Exists
|| SystemInfo.operatingSystemFamily != OperatingSystemFamily.MacOSX && new FileInfo(editorPath).Exists;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bdbd564a9fdad0b738e76d030cad1204
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Packages.Rider.Editor.Util
{
internal static class LibcNativeInterop
{
[DllImport("libc", SetLastError = true)]
public static extern IntPtr realpath(string path, StringBuilder resolved_path);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 071c17858dc6c47ada7b2a1f1ded5402
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using JetBrains.Annotations;
using Packages.Rider.Editor;
using Unity.CodeEditor;
// ReSharper disable once CheckNamespace
namespace JetBrains.Rider.Unity.Editor
{
/// <summary>
/// Is called via commandline from Rider Notification after checking out from source control.
/// </summary>
[UsedImplicitly]
public static class RiderMenu
{
/// <summary>
/// Is called via commandline from Rider Notification after checking out from source control.
/// </summary>
[UsedImplicitly]
public static void MenuOpenProject()
{
if (RiderScriptEditor.IsRiderOrFleetInstallation(RiderScriptEditor.CurrentEditor))
{
// Force the project files to be sync
CodeEditor.CurrentEditor.SyncAll();
// Load Project
CodeEditor.CurrentEditor.OpenProject();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8860c53ca4073d4f92c403e709c12ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
using System.IO;
namespace Rider.Editor.Util
{
internal static class RiderPathUtil
{
public static bool IsRiderDevEditor(string editorPath)
{
if (editorPath == null)
return false;
return "rider-dev".Equals(Path.GetFileNameWithoutExtension(editorPath));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d34a9510a5b9d21381c93e73867a193
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System;
namespace Packages.Rider.Editor.Util
{
[Serializable]
internal class SerializableVersion
{
public SerializableVersion(Version version)
{
Major = version.Major;
Minor = version.Minor;
if (version.Build >= 0)
Build = version.Build;
if (version.Revision >= 0)
Revision = version.Revision;
}
public int Build;
public int Major;
public int Minor;
public int Revision;
}
internal static class VersionExtension
{
public static SerializableVersion ToSerializableVersion(this Version version)
{
if (version == null)
return null;
return new SerializableVersion(version);
}
public static Version ToVersion(this SerializableVersion serializableVersion)
{
if (serializableVersion == null)
return null;
var build = serializableVersion.Build;
if (build < 0)
build = 0;
var revision = serializableVersion.Revision;
if (revision < 0)
revision = 0;
return new Version(serializableVersion.Major, serializableVersion.Minor, build,
revision);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e1f00a9be2eb66438e2835fdf1ea11b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Text;
namespace Packages.Rider.Editor.Util
{
internal static class StringBuilderExtensions
{
// StringBuilder.AppendJoin is very useful, but not available in 2019.2
// It requires netstandard 2.1
public static StringBuilder CompatibleAppendJoin(this StringBuilder stringBuilder, char separator, IEnumerable<string> parts)
{
var first = true;
foreach (var part in parts)
{
if (!first) stringBuilder.Append(separator);
stringBuilder.Append(part);
first = false;
}
return stringBuilder;
}
}
}

Some files were not shown because too many files have changed in this diff Show More