public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { // This is called on the main thread, load the settings and initialise in the background myThreading.Tasks.Factory.StartNew(() => { var streamName = GetType().Namespace + ".Abbreviations.txt"; var stream = GetType().Assembly.GetManifestResourceStream(streamName); if (stream == null) { myLogger.Warn($"Cannot load resource stream: {streamName}"); return; } using (var streamReader = new StreamReader(stream)) { var entry = mySettingsSchema.GetIndexedEntry((CSharpNamingSettings s) => s.Abbreviations); string abbreviation; while ((abbreviation = streamReader.ReadLine()) != null) { ScalarSettingsStoreAccess.SetIndexedValue(mountPoint, entry, abbreviation, null, abbreviation, null, myLogger); } } }); }
private void SetValue <TKeyClass, TEntryValue>([NotNull] ISettingsStorageMountPoint mount, [NotNull] Expression <Func <TKeyClass, TEntryValue> > lambdaexpression, [NotNull] TEntryValue value, IDictionary <SettingsKey, object> keyIndices = null) { ScalarSettingsStoreAccess.SetValue(mount, settingsSchema.GetScalarEntry(lambdaexpression), keyIndices, value, false, null, logger); }
public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { var entry = mySettingsSchema.GetIndexedEntry((InstalledDictionariesSettings s) => s.InstalledDictionaries); var path = (FileSystemPath.Parse(GetType().Assembly.Location).Parent / "Extensions/JetBrains.unity/dictionaries/unity.dic").FullPath; ScalarSettingsStoreAccess.SetIndexedValue(mountPoint, entry, path, null, true, null, myLogger); }
private void ExcludeFolderFromNamespace(ISettingsStorageMountPoint mountPoint, string path) { var index = NamespaceFolderProvider.GetIndexFromOldIndex(FileSystemPath.Parse(path, FileSystemPathInternStrategy.TRY_GET_INTERNED_BUT_DO_NOT_INTERN)); SetIndexedValue(mountPoint, NamespaceProviderSettingsAccessor.NamespaceFoldersToSkip, index, true); }
private void ExcludePackageRootFolderFromNamespace(ISettingsStorageMountPoint mountPoint, IProjectFolder folder, string path) { ExcludeFolderFromNamespace(mountPoint, path); // Is it a package folder? Exclude Scripts, Runtime, Scripts/Runtime and Runtime/Scripts if (folder.Location.Combine("package.json").ExistsFile) { // The folder will be linked if the project's files belong to a package that is external to the solution // folder. With a linked folder, the namespace provider must be the actual path, relative to the parent // folder, rather than the visible path in the Solution Explorer // // NOTE: KEEP UP TO DATE WITH ExternalPackageCustomNamespaceProvider! if (folder.IsLinked && folder.ParentFolder != null) { path = folder.Location.ConvertToRelativePath(folder.ParentFolder.Location).FullPath; } ExcludeFolderFromNamespace(mountPoint, path + @"\Runtime"); ExcludeFolderFromNamespace(mountPoint, path + @"\Scripts"); ExcludeFolderFromNamespace(mountPoint, path + @"\Runtime\Scripts"); ExcludeFolderFromNamespace(mountPoint, path + @"\Scripts\Runtime"); return; } // Recurse until we hit the package root ExcludePackageSubFoldersFromNamespace(mountPoint, folder, path); }
private void InitialiseQuickList(ISettingsStorageMountPoint mountPoint, IMainScopePoint quickList) { var settings = new QuickListSettings { Name = quickList.QuickListTitle }; SetIndexedKey(mountPoint, settings, new GuidIndex(quickList.QuickListUID)); }
public void InitialiseProjectSettings(Lifetime projectLifetime, IProject project, ISettingsStorageMountPoint mountPoint) { SetProjectLangVersion(project, mountPoint); // If the project data cache isn't ready yet, or changes at a later date, reset the overridden lang version myUnityProjectFileCache.RegisterDataChangedCallback(projectLifetime, project.ProjectFileLocation, () => SetProjectLangVersion(project, mountPoint)); }
private void SetIndexedValue <TKeyClass, TEntryIndex, TEntryValue>([NotNull] ISettingsStorageMountPoint mount, [NotNull] Expression <Func <TKeyClass, IIndexedEntry <TEntryIndex, TEntryValue> > > lambdaexpression, [NotNull] TEntryIndex index, [NotNull] TEntryValue value, IDictionary <SettingsKey, object> keyIndices = null) { ScalarSettingsStoreAccess.SetIndexedValue(mount, mySettingsSchema.GetIndexedEntry(lambdaexpression), index, keyIndices, value, null, myLogger); }
private void ExcludePackageSubFoldersFromNamespace(ISettingsStorageMountPoint mountPoint, IProjectFolder thisFolder, string thisPath) { foreach (var subFolder in thisFolder.GetSubFolders()) { var path = thisPath + @"\" + subFolder.Name; ExcludePackageRootFolderFromNamespace(mountPoint, subFolder, path); } }
private void InitNamespaceProviderSettings(ISettingsStorageMountPoint mountPoint) { var assetsPathIndex = NamespaceFolderProvider.GetIndexFromOldIndex(FileSystemPath.Parse("Assets")); SetIndexedValue(mountPoint, NamespaceProviderSettingsAccessor.NamespaceFoldersToSkip, assetsPathIndex, true); var scriptsPathIndex = NamespaceFolderProvider.GetIndexFromOldIndex(FileSystemPath.Parse(@"Assets\Scripts")); SetIndexedValue(mountPoint, NamespaceProviderSettingsAccessor.NamespaceFoldersToSkip, scriptsPathIndex, true); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { InitialiseQuickList(mountPoint, myProjectMainPoint); InitialiseQuickList(mountPoint, myFilesMainPoint); // TODO: Not sure if this would be better handled in a .dotSettings file var pos = 0; AddToQuickList(mountPoint, myProjectMainPoint, "Node", ++pos, "67A1E56D-859B-4BEF-A4EE-1D7A06F1A2B9"); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { InitialiseQuickList(mountPoint, myProjectMainPoint); InitialiseQuickList(mountPoint, myFilesMainPoint); // TODO: Not sure if this would be better handled in a .dotSettings file AddToQuickList(mountPoint, myProjectMainPoint, "MonoBehaviour", 1, "5ff5ac38-7207-4256-91ae-b5436552db13"); AddToQuickList(mountPoint, myProjectMainPoint, "PlayModeTest", 2, "0bcdbc13-d26e-4512-9750-fb930f532e88"); AddToQuickList(mountPoint, myProjectMainPoint, "EditModeTest", 3, "7b7fa2c7-0ee5-4d4f-bb1f-ddbeacdbfc94"); AddToQuickList(mountPoint, myProjectMainPoint, "StandardSurfaceShader", 4, "4b8178a2-8110-4068-a788-43b8227564e5"); AddToQuickList(mountPoint, myProjectMainPoint, "UnlitShader", 5, "fdbd3ad2-8db2-466a-a934-4ce25cb40564"); AddToQuickList(mountPoint, myProjectMainPoint, "ImageEffectShader", 6, "7b10542b-0a61-4bd8-ba91-e5bad4d39f5b"); }
private void AddAutoImportExclusions(ISettingsStorageMountPoint mountPoint, params string[] settings) { var entry = mySettingsSchema.GetIndexedEntry((AutoImport2Settings s) => s.BlackLists); var indexedKey = new Dictionary <SettingsKey, object> { { mySettingsSchema.GetKey <AutoImport2Settings>(), CSharpLanguage.Name } }; foreach (var setting in settings) { ScalarSettingsStoreAccess.SetIndexedValue(mountPoint, entry, setting, indexedKey, true, null, myLogger); } }
public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { // Show type conversion hints always. The default is push-to-hint, but the big benefit for Unity developers // is to see when an implicit conversion is happening between Vector2 and Vector3, as this is a lossy conversion // This can still be overridden at the solution or personal level var entry = mySettingsSchema.GetScalarEntry((CSharpTypeConversionHintsOptions o) => o.ShowTypeConversionHints); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, InlayHintsMode.Always, true, null, myLogger); // Show as a hint, not as an icon entry = mySettingsSchema.GetScalarEntry((CSharpTypeConversionHintsOptions o) => o.ShowHintsInSimplifiedMode); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, false, true, null, myLogger); }
public void InitialiseProjectSettings(Lifetime projectLifetime, IProject project, ISettingsStorageMountPoint mountPoint) { var assetsPathIndex = NamespaceFolderProvider.GetIndexFromOldIndex(FileSystemPath.Parse("Assets")); SetIndexedValue(mountPoint, NamespaceProviderSettingsAccessor.NamespaceFoldersToSkip, assetsPathIndex, true); var scriptsPathIndex = NamespaceFolderProvider.GetIndexFromOldIndex(FileSystemPath.Parse(@"Assets\Scripts")); SetIndexedValue(mountPoint, NamespaceProviderSettingsAccessor.NamespaceFoldersToSkip, scriptsPathIndex, true); }
// The reasoning behind this is fairly simple: // * Package location should not affect namespace // The package owner is not in control of the location of the package on an end user's system. It might be // cloned into the Packages folder, or referenced and cached in the Library/PackageCache folder. It might also // be referenced in an external location with the file: syntax // * Assembly definition location should affect location, but only relative to Assets or package root folder // Packages are self contained units. The location of an assembly definition in a folder structure (especially // the Assets folder) is deliberate on the part of the user and should be part of the namespace // * If the asmdef defines a root namespace (Unity 2020.2a12+) this overrides everything, up to and including // the location of the .asmdef file // * Exclude some folder names, based on observed convention. E.g. Assets, Runtime, Scripts. // Editor is deliberately not excluded. // // There are subtleties: // * Exclude Assets and Assets/Scripts, Packages and Library/PackageCache // * Exclude the package root folder. The package owner is not in control of this. // Referenced packages are stored in Library/PackageCache with a folder name based on ID and version // End users can clone git repos or tarballs into any folder // * Exclude any folder until we get to the package root (the location of the package.json) // If we clone a git repo into Packages, and the repo doesn't have a package in the root of the repo, skip all // folders until we get to the package root. The package can be included via a file: entry in manifest.json // * A package that lives inside the solution structure, but outside of Assets or Packages will have a project // with a path that is relative to the solution root. Ignore all intermediary folders between solution and // package root // * A package that lives outside of the solution structure will have a root folder that is a link to the common // parent of all files in the project. This is usually the asmdef location, AND IS INCORRECT. // The linked folder is not included in namespace suggestions // TODO: The linked folder should be the package root folder (which we normally ignore) // This requires changes to the generated files. Either we include package.json to make a new default folder, // or we add Link attributes to each file item // * After package root, ignore Runtime, Scripts and any combination of the two // // And implications: // * If there is no root namespace specified for an assembly definition in a package, one can be inferred from // the path from the package root to the assembly definition file // E.g. /Packages/[email protected]/Unity.Collections/Unity.Collections.asmdef will have // a "root namespace" of Unity.Collections public void InitialiseProjectSettings(Lifetime projectLifetime, IProject project, ISettingsStorageMountPoint mountPoint) { ExcludeFolderFromNamespace(mountPoint, "Assets"); ExcludeFolderFromNamespace(mountPoint, @"Assets\Scripts"); ExcludePackagesFoldersFromNamespace(mountPoint, project, "Packages"); foreach (var projectFolder in project.GetSubFolders("Library")) { ExcludeFolderFromNamespace(mountPoint, "Library"); ExcludePackagesFoldersFromNamespace(mountPoint, projectFolder, "PackageCache", @"Library"); } ExcludeExternalPackagesFromNamespace(mountPoint, project); }
private void ExcludePackagesFoldersFromNamespace(ISettingsStorageMountPoint mountPoint, IProjectFolder packageHierarchyParentFolder, string packageHierarchyFolderName, string parentProjectRelativePath = "") { var packageHierarchyRootFolderPath = parentProjectRelativePath.Length == 0 ? packageHierarchyFolderName : parentProjectRelativePath + @"\" + packageHierarchyFolderName; foreach (var subFolder in packageHierarchyParentFolder.GetSubFolders(packageHierarchyFolderName)) { // Exclude the root of the package hierarchy (Packages or PackageCache) ExcludeFolderFromNamespace(mountPoint, packageHierarchyRootFolderPath); ExcludePackageSubFoldersFromNamespace(mountPoint, subFolder, packageHierarchyRootFolderPath); } }
public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { // Remove items from auto completion. Anything in these namespaces, or matching the method name will not // show in the auto import completion lists, and will not get the auto-import alt+enter tooltip popup. // If you want to use a type that matches, you need to add the using statement manually. // * Ignore Bool.Lang.* and UnityScript.* as they were deprecated in late 2017, and most of the code there // is not intended to be consumed by users, but the assemblies are still referenced. This prevents e.g.: // Boo.Lang.List`1 from appearing in the completion list above System.Collections.Generic.List`1 // * Also exclude System.Diagnostics.Debug() to prevent similar clashes with UnityEngine.Debug() // See the internal DumpDuplicateTypeNamesAction to generate a list of types that can clash. There are about // 80 types on this list. It's not worth ignoring all of them. But some candidates: // * System.Numerics.Vector{2,3,4} + Quaternion + Plane // * System.Random + UnityEngine.Random AddAutoImportExclusions(mountPoint, "Boo.Lang.*", "UnityScript.*", "System.Diagnostics.Debug"); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { InitialiseQuickList(mountPoint, myProjectMainPoint); InitialiseQuickList(mountPoint, myFilesMainPoint); // TODO: Not sure if this would be better handled in a .dotSettings file var pos = 0; AddToQuickList(mountPoint, myProjectMainPoint, "MonoBehaviour", ++pos, "5ff5ac38-7207-4256-91ae-b5436552db13"); AddToQuickList(mountPoint, myProjectMainPoint, "PlayModeTest", ++pos, "0bcdbc13-d26e-4512-9750-fb930f532e88"); AddToQuickList(mountPoint, myProjectMainPoint, "EditModeTest", ++pos, "7b7fa2c7-0ee5-4d4f-bb1f-ddbeacdbfc94"); AddToQuickList(mountPoint, myProjectMainPoint, "StandardSurfaceShader", ++pos, "4b8178a2-8110-4068-a788-43b8227564e5"); AddToQuickList(mountPoint, myProjectMainPoint, "UnlitShader", ++pos, "fdbd3ad2-8db2-466a-a934-4ce25cb40564"); AddToQuickList(mountPoint, myProjectMainPoint, "ImageEffectShader", ++pos, "7b10542b-0a61-4bd8-ba91-e5bad4d39f5b"); AddToQuickList(mountPoint, myProjectMainPoint, "AsmDef", ++pos, "bf263f0d-4315-42f7-8813-d7afe13fcdeb"); AddToQuickList(mountPoint, myProjectMainPoint, "EditorEntryPoint", ++pos, "DA24767F-E6BB-4463-ACB4-799D7CE68822"); }
private void AddToQuickList(ISettingsStorageMountPoint mountPoint, IMainScopePoint quickList, string name, int position, string guid) { var quickListKey = mySettingsSchema.GetIndexedKey <QuickListSettings>(); var entryKey = mySettingsSchema.GetIndexedKey <EntrySettings>(); var dictionary = new Dictionary <SettingsKey, object> { { quickListKey, new GuidIndex(quickList.QuickListUID) }, { entryKey, new GuidIndex(new Guid(guid)) } }; if (!ScalarSettingsStoreAccess.IsIndexedKeyDefined(mountPoint, entryKey, dictionary, null, myLogger)) { ScalarSettingsStoreAccess.CreateIndexedKey(mountPoint, entryKey, dictionary, null, myLogger); } SetValue(mountPoint, (EntrySettings e) => e.EntryName, name, dictionary); SetValue(mountPoint, (EntrySettings e) => e.Position, position, dictionary); }
public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { // Navigate to source for external symbols (ensure default value is still set) var entry = mySettingsSchema.GetScalarEntry((ExternalSourcesSettings s) => s.NavigationMode); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, ExternalSourcesNavigationMode.Sources, true, null, myLogger); // Use source files from PDBs, if available (ensure default value is still set) // This is the important setting. Without this, we would show decompiled code, even though we can navigate // to source from the Unity Explorer entry = mySettingsSchema.GetScalarEntry((PdbNavigationSettings s) => s.UseSymbolFiles); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, true, true, null, myLogger); // Allow navigating to private and internal package symbols (not the default) entry = mySettingsSchema.GetScalarEntry((ExternalSourcesSettings s) => s.ShowNonPublicCompiledElementsInGoto); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, true, true, null, myLogger); }
private void ExcludeExternalPackagesFromNamespace(ISettingsStorageMountPoint mountPoint, IProject project) { // Handle assembly definitions for packages that live outside of the Unity project structure (i.e. not under // Assets, Packages or Library/PackageCache), or that lives outside of the solution completely. // If the assembly definition lives outside of the solution, this folder will be a link to the assembly // definition location, NOT the package root. If it lives in the Unity solution folder, it will be the start // of the path to the project root foreach (var projectFolder in project.GetSubFolders()) { if (projectFolder.Name.Equals("Assets", StringComparison.OrdinalIgnoreCase) || projectFolder.Name.Equals("Library", StringComparison.OrdinalIgnoreCase) || projectFolder.Name.Equals("Packages", StringComparison.OrdinalIgnoreCase)) { continue; } ExcludePackageRootFolderFromNamespace(mountPoint, projectFolder, projectFolder.Name); } }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { InitialiseQuickList(mountPoint, myProjectMainPoint); InitialiseQuickList(mountPoint, myFilesMainPoint); // TODO: Not sure if this would be better handled in a .dotSettings file var pos = 0; AddToQuickList(mountPoint, myProjectMainPoint, "MonoBehaviour", ++pos, "5ff5ac38-7207-4256-91ae-b5436552db13"); AddToQuickList(mountPoint, myProjectMainPoint, "ScriptableObject", ++pos, "1404A333-DA7C-47AC-8CB5-7C944DD1422D"); AddToQuickList(mountPoint, myProjectMainPoint, "StateMachineBehaviour", ++pos, "AFA01340-773E-488A-93D6-E19540AE2F1B"); AddToQuickList(mountPoint, myProjectMainPoint, "PlayModeTest", ++pos, "0bcdbc13-d26e-4512-9750-fb930f532e88"); AddToQuickList(mountPoint, myProjectMainPoint, "CustomEditor", ++pos, "2E5D288C-A209-41EE-93B2-7CACDCAE18C6"); AddToQuickList(mountPoint, myProjectMainPoint, "EditorWindow", ++pos, "CA9DFEEA-D5B5-4DDC-933F-8D618D71538E"); AddToQuickList(mountPoint, myProjectMainPoint, "PropertyDrawer", ++pos, "7901AA8B-4060-4763-8FD5-B7B5384FABAA"); AddToQuickList(mountPoint, myProjectMainPoint, "ScriptableWizard", ++pos, "E1BD73A0-0145-4A1A-B4AA-7744144744AF"); AddToQuickList(mountPoint, myProjectMainPoint, "AssetPostprocessor", ++pos, "B669492E-B3A6-4F98-9998-9AF480374340"); AddToQuickList(mountPoint, myProjectMainPoint, "EditModeTest", ++pos, "7b7fa2c7-0ee5-4d4f-bb1f-ddbeacdbfc94"); AddToQuickList(mountPoint, myProjectMainPoint, "StandardSurfaceShader", ++pos, "4b8178a2-8110-4068-a788-43b8227564e5"); AddToQuickList(mountPoint, myProjectMainPoint, "UnlitShader", ++pos, "fdbd3ad2-8db2-466a-a934-4ce25cb40564"); AddToQuickList(mountPoint, myProjectMainPoint, "ImageEffectShader", ++pos, "7b10542b-0a61-4bd8-ba91-e5bad4d39f5b"); AddToQuickList(mountPoint, myProjectMainPoint, "AsmDef", ++pos, "bf263f0d-4315-42f7-8813-d7afe13fcdeb"); AddToQuickList(mountPoint, myProjectMainPoint, "EditorEntryPoint", ++pos, "DA24767F-E6BB-4463-ACB4-799D7CE68822"); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { var text = AdditionalFileLayoutResources.DefaultAdditionalFileLayoutPatterns; SetValue(mountPoint, (AdditionalFileLayoutSettings s) => s.Pattern, text); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { SetIndexedValue(mountPoint, (CSharpNamingSettings key) => key.UserRules, SerializedFieldRuleGuid, GetUnitySerializedFieldRule()); }
public void InitialiseSolutionSettings(ISettingsStorageMountPoint mountPoint) { var entry = mySettingsSchema.GetScalarEntry((CppFormattingSettingsKey s) => s.INDENT_PREPROCESSOR_DIRECTIVES); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, PreprocessorIndent.Normal, true, null, myLogger); }
public override void InitDefaultSettings(ISettingsStorageMountPoint mountPoint) { SetIndexedValue(mountPoint, UnitySettingsAccessor.UnityClasses, "UnityEngine.MonoBehaviour"); SetIndexedValue(mountPoint, UnitySettingsAccessor.UnityClasses, "UnityEngine.ScriptableObject"); SetIndexedValue(mountPoint, UnitySettingsAccessor.UnityAttributes, "UnityEngine.SerializeField"); }
public void InitialiseProjectSettings(Lifetime projectLifetime, IProject project, ISettingsStorageMountPoint mountPoint) { if (myInTests) { return; } // hide, because for Unity projects this wouldn't work. // for Unity we have `UnityRunMarkerProvider` instead. var entry = mySettingsSchema.GetScalarEntry((RunMarkerSettings o) => o.ShowMarkerOnStaticMethods); ScalarSettingsStoreAccess.SetValue(mountPoint, entry, null, false, true, null, myLogger); }
private void SetProjectLangVersion(IProject project, ISettingsStorageMountPoint mountPoint) { // Only if it's a generated project. Class libraries can use whatever language version they want if (!project.IsUnityGeneratedProject()) { return; } #region Explanation // Make sure we don't suggest code changes that won't compile in Unity due to mismatched C# language levels // (e.g. C#6 "elvis" operator) // // * Unity prior to 5.5 uses an old mono compiler that only supports C# 4 // * Unity 5.5 and later adds C# 6 support as an option. This is enabled by setting // the API compatibility level to NET_4_6 // * The CSharp60Support plugin replaces the compiler with either C# 6 or C# 7.0 or 8.0 // It can be recognised by a folder called `CSharp60Support` or `CSharp70Support` or `CSharp80Support` // in the root of the project // (https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration) // * Note that since Unity 2017.2 till 2018.3, we've been special-cased in the Unity csproj generation // and we've been getting v4.5 for old runtime and default values (4.7.1) for new. So where // it says 3.5 below, that depends on the version of Unity. Older versions will give us 3.5, // newer versions 4.5. // // Scenarios: // * No VSTU installed (including Unity 5.5) // .csproj has NO `LangVersion`. `TargetFrameworkVersion` will be `v3.5` // * Early versions of VSTU // .csproj has NO `LangVersion`. `TargetFrameworkVersion` will be `v3.5` // * Later versions of VSTU // `LangVersion` is correctly set to "4". `TargetFrameworkVersion` will be `v3.5` // OR `LangVersion` is set to "6" or "latest". // * VSTU for 5.5 // `LangVersion` is set to "default". `TargetFrameworkVersion` will be `v3.5` or `v4.6` // Note that "default" for VS"15" or Rider will be C# 7.0! // * Unity3dRider is installed // Uses Unity's own generation and adds correct `LangVersion` // `TargetFrameworkVersion` will be correct for the selected runtime // * CSharp60Support is installed // .csproj has NO `LangVersion` // `TargetFrameworkVersion` is NOT accurate (support for C# 6 is not dependent on/trigger by .net 4.6) // Look for `CSharp60Support` or `CSharp70Support` folders // * Unity 2018.x+. LangVersion is `latest`. MSBuild 16 treats `newest` as C# 8. Re# and Rider start suggesting it. // // Actions: // * If `LangVersion` is missing or "default" // then override based on `TargetFrameworkVersion` or presence of `CSharp60Support`/`CSharp70Support` // else do nothing // * If `LangVersion` is "latest" // then override based on `CSharp80Support` presence or LangVersion matching Roslyn bundled in Unity // // Notes: // * Unity and VSTU have two separate .csproj routines. VSTU adds extra references, // the VSTU project flavour GUID and imports UnityVs.targets, which disables the // `GenerateTargetFrameworkMonikerAttribute` target // * CSharp60Support post-processes the .csproj file directly if VSTU is not installed. // If it is installed, it registers a delegate with `ProjectFilesGenerator.ProjectFileGeneration` // and removes it before it's written to disk // * `LangVersion` can be conditionally specified, which makes checking for "default" awkward // * If Unity3dRider + CSharp60Support are both installed, last write wins // Order of post-processing is non-deterministic, so Rider's LangVersion might be removed #endregion var languageLevel = ReSharperSettingsCSharpLanguageLevel.Default; if (IsLangVersionMissing(project) || IsLangVersionDefault(project)) { // Support for https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration // See also https://github.com/JetBrains/resharper-unity/issues/50#issuecomment-257611218 if (project.Location.CombineWithShortName("CSharp70Support").ExistsDirectory) { languageLevel = ReSharperSettingsCSharpLanguageLevel.CSharp70; } else if (project.Location.CombineWithShortName("CSharp60Support").ExistsDirectory) { languageLevel = ReSharperSettingsCSharpLanguageLevel.CSharp60; } else { languageLevel = IsTargetFrameworkAtLeast46(project) ? ReSharperSettingsCSharpLanguageLevel.CSharp60 : ReSharperSettingsCSharpLanguageLevel.CSharp40; } } if (IsLangVersionLatest(project)) { if (project.Location.CombineWithShortName("CSharp80Support").ExistsDirectory) // https://forum.unity.com/threads/would-the-roslyn-compiler-compile-c-8-0-preview.598069/ { languageLevel = ReSharperSettingsCSharpLanguageLevel.CSharp80; } else { var appPath = myUnityProjectFileCache.GetAppPath(project); var contentPath = UnityInstallationFinder.GetApplicationContentsPath(appPath); if (!contentPath.IsNullOrEmpty()) { var roslynDir = contentPath.Combine("Tools").Combine("Roslyn"); if (roslynDir.ExistsDirectory) { languageLevel = myLanguageLevelProjectProperty.GetLatestAvailableLanguageLevel(roslynDir).ToSettingsLanguageLevel(); } } } } // Always set a value. It's either the overridden value, or Default, which resets to whatever is in the // project file SetValue(mountPoint, (CSharpLanguageProjectSettings s) => s.LanguageLevel, languageLevel); }