private void InstallPluginIfRequired(ICollection <IProject> projects) { if (myPluginInstallations.Contains(mySolution.SolutionFilePath)) { return; } if (!myBoundSettingsStore.GetValue((UnityPluginSettings s) => s.InstallUnity3DRiderPlugin)) { return; } if (projects.Count == 0) { return; } // forcing fresh install due to being unable to provide proper setting until InputField is patched in Rider // ReSharper disable once ArgumentsStyleNamedExpression var installationInfo = myDetector.GetInstallationInfo(projects, previousInstallationDir: FileSystemPath.Empty); if (!installationInfo.ShouldInstallPlugin) { myLogger.Info("Plugin should not be installed."); if (installationInfo.ExistingFiles.Count > 0) { myLogger.Info("Already existing plugin files:\n{0}", string.Join("\n", installationInfo.ExistingFiles)); } return; } myQueue.Enqueue(() => { Install(installationInfo); myPluginInstallations.Add(mySolution.SolutionFilePath); }); }
bool ICache.UpToDate(IPsiSourceFile sourceFile) { lock (lockObject) { if (dirtyFiles.Contains(sourceFile)) { return(false); } if (!registrationsMap.ContainsKey(sourceFile)) { return(false); } } return(!ShouldBeProcessed(sourceFile)); }
public override void VisitSemanticNode(ISemantic semanticParam, IHighlightingConsumer context) { if (semanticParam.NameNode is CgIdentifierTokenNode id && !id.Name.IsNullOrEmpty()) { if (mySemantics.Contains(id.Name)) { context.AddHighlighting(new CgHighlighting(CgHighlightingAttributeIds.KEYWORD, id.GetDocumentRange())); } else if (myIsErrorHighlightingEnabled) { var range = GetErrorRange(id); context.AddHighlighting(new CgSyntaxError("Semantic, packoffset or register expected", range)); } } base.VisitSemanticNode(semanticParam, context); }
private bool IsKnownCommonAttribute(string name, IEnumerable <IHtmlDeclaredElementsProvider> providers) { // This is horrible. We can't override existing tags and attributes, but we calling the // other providers dynamically causes serious perf issues. We'll just make do with // caching the standard HTML attributes and hope for the best. We also can't do this // in the constructor, or we get a nasty circular instantiation issue. I'll file a YT // ticket to handle this better in a future version. if (allAttributes == null) { lock (lockObject) { if (allAttributes == null) { allAttributes = standardProvider.GetAllAttributesSymbolTable().Names().ToHashSet(IdentityFunc <string> .Instance, StringComparer.InvariantCultureIgnoreCase); } } } return(allAttributes.Contains(name)); }
public override void Execute(Action <DaemonStageResult> committer) { var highlightingConsumer = new FilteringHighlightingConsumer(DaemonProcess.SourceFile, File, DaemonProcess.ContextBoundSettingsStore); File.ProcessThisAndDescendants(this, highlightingConsumer); foreach (var declaration in File.Descendants <ICSharpDeclaration>()) { var declaredElement = declaration.DeclaredElement; if (declaredElement == null) { continue; } if (myEventFunctions != null && myEventFunctions.Contains(declaredElement)) { var method = (declaredElement as IMethod).NotNull("method != null"); var eventFunction = myAPI.GetUnityEventFunction(method); if (eventFunction == null) // happens after event function refactoring { continue; } myCommonIconProvider.AddEventFunctionHighlighting(highlightingConsumer, method, eventFunction, "Event function", myProcessKind); myMarkedDeclarations.Add(method); } else { if (myMarkedDeclarations.Contains(declaredElement)) { continue; } myCommonIconProvider.AddFrequentlyCalledMethodHighlighting(highlightingConsumer, declaration, "Frequently called", "Frequently called code", myProcessKind); } } committer(new DaemonStageResult(highlightingConsumer.Highlightings)); }
public static bool IsAnnotatedWithKnownTestAttribute(this IMethodDeclaration methodDeclaration) { if (methodDeclaration.AttributeSectionList != null) { foreach (var attribute in methodDeclaration.AttributeSectionList.AttributesEnumerable) { var attributeClass = attribute.Name.Reference.Resolve().DeclaredElement as IClass; if (attributeClass == null) { return(false); } var clrTypeName = attributeClass.GetClrName(); if (TestMethodClrAttributes.Contains(clrTypeName)) { return(true); } } } return(false); }
public bool IsPluginNeeded([NotNull] IProject project) { var assetsDir = GetAssetsDirectory(project); if (assetsDir == null) { return(false); // not a Unity project } var jetBrainsDir = assetsDir .CombineWithShortName("Plugins") .CombineWithShortName("Editor") .CombineWithShortName("JetBrains"); if (!jetBrainsDir.ExistsDirectory) { return(true); } var existingFiles = new JetHashSet <string>(jetBrainsDir.GetChildFiles().Select(f => f.Name)); return(ourPluginFiles.Any(f => !existingFiles.Contains(f))); }
protected override bool AddLookupItems(T4CodeCompletionContext context, IItemsCollector collector) { ITreeNode node = context.BasicContext.File.FindNodeAt(context.BasicContext.SelectedTreeRange); Assertion.AssertNotNull(node, "node == null"); var ranges = context.BasicContext.GetRanges(node); collector.AddRanges(ranges); var directive = node.GetContainingNode <IT4Directive>(); Assertion.AssertNotNull(directive, "directive != null"); DirectiveInfo directiveInfo = _directiveInfoManager.GetDirectiveByName(directive.GetName()); if (directiveInfo == null) { return(false); } JetHashSet <string> existingNames = directive .GetAttributes() .Select(attr => attr.GetName()) .ToJetHashSet(s => s, StringComparer.OrdinalIgnoreCase); foreach (string attributeName in directiveInfo.SupportedAttributes.Select(attr => attr.Name)) { if (existingNames.Contains(attributeName)) { continue; } var item = new TextLookupItem(attributeName); item.InitializeRanges(ranges, context.BasicContext); collector.Add(item); } return(true); }
public override void Execute(Action <DaemonStageResult> committer) { var highlightingConsumer = new FilteringHighlightingConsumer(DaemonProcess.SourceFile, File, DaemonProcess.ContextBoundSettingsStore); File.ProcessThisAndDescendants(this, highlightingConsumer); foreach (var declaration in File.Descendants <ICSharpDeclaration>()) { var declaredElement = declaration.DeclaredElement; if (declaredElement == null) { continue; } if (myEventFunctions != null && myEventFunctions.Contains(declaredElement)) { var method = (declaredElement as IMethod).NotNull("method != null"); myUnityHighlightingContributor.AddUnityImplicitHighlightingForEventFunction(highlightingConsumer, method, myAPI.GetUnityEventFunction(method), myProcessKind); myMarkedDeclarations.Add(method); } else { if (myMarkedDeclarations.Contains(declaredElement)) { continue; } myUnityHighlightingContributor.AddHighlighting(highlightingConsumer, declaration, "Frequently called code", "Frequently called", myProcessKind, true); } } committer(new DaemonStageResult(highlightingConsumer.Highlightings)); }
// На основе множества статусов вычисляет один. // (Для группы равноправных элементов, например, всех предыдущих элементов) private VariableDisposeStatus UniteStatus(JetHashSet<VariableDisposeStatus> statusSet, bool hasCrossroads) { var disposedAndInvocationSet = new List<VariableDisposeStatus> { VariableDisposeStatus.Disposed, VariableDisposeStatus.DependsOnInvocation }; if (statusSet.IsSupersetOf(disposedAndInvocationSet)) return VariableDisposeStatus.Disposed; if (statusSet.Contains(VariableDisposeStatus.DependsOnInvocation)) return VariableDisposeStatus.DependsOnInvocation; var bothSet = new List<VariableDisposeStatus> { VariableDisposeStatus.Disposed, VariableDisposeStatus.NotDisposed }; if (statusSet.Contains(VariableDisposeStatus.Both) || statusSet.IsSupersetOf(bothSet)) return VariableDisposeStatus.Both; if (!hasCrossroads) { if (statusSet.Contains(VariableDisposeStatus.Disposed)) return VariableDisposeStatus.Disposed; if (statusSet.Contains(VariableDisposeStatus.NotDisposed)) return VariableDisposeStatus.NotDisposed; Assertion.Fail("Unknown status"); return VariableDisposeStatus.Unknown; } if (statusSet.Contains(VariableDisposeStatus.Unknown)) return VariableDisposeStatus.Unknown; if (statusSet.Contains(VariableDisposeStatus.Disposed)) return VariableDisposeStatus.Disposed; return VariableDisposeStatus.NotDisposed; }
private void InstallPluginIfRequired() { if (!myUnitySolutionTracker.IsUnityProjectFolder.Value) { return; } if (myPluginInstallations.Contains(mySolution.SolutionFilePath)) { return; } if (!myBoundSettingsStore.GetValue((UnitySettings s) => s.InstallUnity3DRiderPlugin)) { return; } // Unity 2019.2+ is expected to have com.unity.ide.rider package, which loads EditorPlugin directly from Rider installation var manifestJsonFile = mySolution.SolutionDirectory.Combine("Packages/manifest.json"); if (manifestJsonFile.ExistsFile) { var text = manifestJsonFile.ReadAllText2().Text; //"com.unity.ide.rider": "1.0.7" var match = Regex.Match(text, @"""com\.unity\.ide\.rider""\s*:\s*""(?<version>.*)""", RegexOptions.Multiline); if (match.Success) { if (Version.TryParse(match.Groups["version"].Value, out var version)) { if (version >= new Version(1, 0, 7)) { myLogger.Verbose($"com.unity.ide.rider version {version}. Skip EditorPlugin installation."); return; } myLogger.Verbose($"com.unity.ide.rider version {version}. EditorPlugin installation continues."); } } } var localPackage = mySolution.SolutionDirectory.Combine("Packages/com.unity.ide.rider/package.json"); if (localPackage.ExistsFile) { myLogger.Verbose("Local package com.unity.ide.rider detected, skip EditorPlugin installation."); return; } // forcing fresh install due to being unable to provide proper setting until InputField is patched in Rider // ReSharper disable once ArgumentsStyleNamedExpression var installationInfo = myDetector.GetInstallationInfo(myCurrentVersion, previousInstallationDir: FileSystemPath.Empty); if (!installationInfo.ShouldInstallPlugin) { myLogger.Info("Plugin should not be installed."); if (installationInfo.ExistingFiles.Count > 0) { myLogger.Info("Already existing plugin files:\n{0}", string.Join("\n", installationInfo.ExistingFiles)); } return; } QueueInstall(installationInfo); myQueue.Enqueue(() => { mySolution.Locks.Tasks.StartNew(myLifetime, Scheduling.MainDispatcher, () => myRefresher.Refresh(RefreshType.Normal)); }); }
private void InstallPluginIfRequired() { if (!myUnitySolutionTracker.IsUnityProjectFolder.Value) { return; } if (myPluginInstallations.Contains(mySolution.SolutionFilePath)) { return; } if (!myBoundSettingsStore.GetValue((UnitySettings s) => s.InstallUnity3DRiderPlugin)) { return; } var versionForSolution = myUnityVersion.ActualVersionForSolution.Value; if (versionForSolution >= new Version("2019.2")) // 2019.2+ would not work fine either without Rider package, and when package is present it loads EditorPlugin directly from Rider installation. { var installationInfoToRemove = myDetector.GetInstallationInfo(myCurrentVersion, previousInstallationDir: FileSystemPath.Empty); if (!installationInfoToRemove.PluginDirectory.IsAbsolute) { return; } var pluginDll = installationInfoToRemove.PluginDirectory.Combine(PluginPathsProvider.BasicPluginDllFile); if (pluginDll.ExistsFile) { myQueue.Enqueue(() => { myLogger.Info($"Remove {pluginDll}. Rider package should be used instead."); pluginDll.DeleteFile(); FileSystemPath.Parse(pluginDll.FullPath + ".meta").DeleteFile(); // jetbrainsDir is usually "Assets\Plugins\Editor\JetBrains", however custom locations were also possible var jetbrainsDir = installationInfoToRemove.PluginDirectory; if (jetbrainsDir.GetChildren().Any() || jetbrainsDir.Name != "JetBrains") { return; } jetbrainsDir.DeleteDirectoryNonRecursive(); FileSystemPath.Parse(jetbrainsDir.FullPath + ".meta").DeleteFile(); var pluginsEditorDir = jetbrainsDir.Directory; if (pluginsEditorDir.GetChildren().Any() || pluginsEditorDir.Name != "Editor") { return; } pluginsEditorDir.DeleteDirectoryNonRecursive(); FileSystemPath.Parse(pluginsEditorDir.FullPath + ".meta").DeleteFile(); var pluginsDir = pluginsEditorDir.Directory; if (pluginsDir.GetChildren().Any() || pluginsDir.Name != "Plugins") { return; } pluginsDir.DeleteDirectoryNonRecursive(); FileSystemPath.Parse(pluginsDir.FullPath + ".meta").DeleteFile(); }); } return; } // forcing fresh install due to being unable to provide proper setting until InputField is patched in Rider // ReSharper disable once ArgumentsStyleNamedExpression var installationInfo = myDetector.GetInstallationInfo(myCurrentVersion, previousInstallationDir: FileSystemPath.Empty); if (!installationInfo.ShouldInstallPlugin) { myLogger.Info("Plugin should not be installed."); if (installationInfo.ExistingFiles.Count > 0) { myLogger.Info("Already existing plugin files:\n{0}", string.Join("\n", installationInfo.ExistingFiles)); } return; } QueueInstall(installationInfo); myQueue.Enqueue(() => { mySolution.Locks.Tasks.StartNew(myLifetime, Scheduling.MainGuard, () => myRefresher.StartRefresh(RefreshType.Normal)); }); }
public void Populate(IGeneratorContext context) { context.InputElements.AddRange(context.ProvidedElements.OfType <GeneratorDeclaredElement>() .Where(e => myInputElements.Contains(e.DeclaredElement.ShortName))); }
private static bool IsUnityBuiltinType(IType type) { return(type is IDeclaredType declaredType && ourUnityBuiltinSerializedFieldTypes.Contains(declaredType.GetClrName())); }
public Dictionary <int, Dictionary <string, IAssetValue> > GetImportedValuesForUnityEvent(LocalReference scriptLocation, JetHashSet <string> allUnityEventNames) { var result = new Dictionary <int, Dictionary <string, IAssetValue> >(); foreach (var modification in myPrefabInstanceHierarchy.PrefabModifications) { if (!(modification.Target is ExternalReference externalReference)) { continue; } if (!modification.PropertyPath.Contains("m_PersistentCalls")) { continue; } var location = new LocalReference(Location.OwningPsiPersistentIndex, PrefabsUtil.GetImportedDocumentAnchor(myPrefabInstanceHierarchy.Location.LocalDocumentAnchor, externalReference.LocalDocumentAnchor)); if (!location.Equals(scriptLocation)) { continue; } var parts = modification.PropertyPath.Split('.'); var unityEventName = parts[0]; if (!allUnityEventNames.Contains(unityEventName)) { continue; } var dataPart = parts.FirstOrDefault(t => t.StartsWith("data")); if (dataPart == null) { continue; } if (!int.TryParse(dataPart.RemoveStart("data[").RemoveEnd("]"), out var index)) { continue; } var last = parts.Last(); if (!result.TryGetValue(index, out var modifications)) { modifications = new Dictionary <string, IAssetValue>(); result[index] = modifications; } switch (last) { case "m_Mode" when modification.Value is AssetSimpleValue simpleValue: modifications[last] = simpleValue; break; case "m_MethodName" when modification.Value is AssetSimpleValue simpleValue: modifications[last] = simpleValue; modifications["m_MethodNameRange"] = new Int2Value(modification.ValueRange.StartOffset, modification.ValueRange.EndOffset); break; case "m_Target" when modification.ObjectReference is IHierarchyReference objectReference: modifications[last] = new AssetReferenceValue(objectReference); break; } } return(result); }
private void ProcessDirective([NotNull] IT4Directive directive) { IT4Token nameToken = directive.GetNameToken(); if (nameToken == null) return; DirectiveInfo directiveInfo = _directiveInfoManager.GetDirectiveByName(nameToken.GetText()); if (directiveInfo == null) return; // Notify of missing required attributes. IEnumerable<string> attributeNames = directive.GetAttributes().SelectNotNull(attr => attr.GetName()); var hashSet = new JetHashSet<string>(attributeNames, StringComparer.OrdinalIgnoreCase); foreach (DirectiveAttributeInfo attributeInfo in directiveInfo.SupportedAttributes) { if (attributeInfo.IsRequired && !hashSet.Contains(attributeInfo.Name)) { AddHighlighting(new HighlightingInfo(nameToken.GetHighlightingRange(), new MissingRequiredAttributeHighlighting(nameToken, attributeInfo.Name))); } } // Assembly attributes in preprocessed templates are useless. if (directiveInfo == _directiveInfoManager.Assembly && DaemonProcess.SourceFile.ToProjectFile().IsPreprocessedT4Template()) { AddHighlighting(new HighlightingInfo(directive.GetHighlightingRange(), new IgnoredAssemblyDirectiveHighlighting(directive))); } }
protected override void TransformItems(ISpecificCodeCompletionContext context, IItemsCollector collector) { JetHashSet <string> templateNames = context.BasicContext.GetData(TemplateNamesKey); if (templateNames == null || templateNames.Count == 0) { return; } List <ILookupItem> toRemove = collector.Items.Where(lookupItem => (lookupItem.IsKeyword()) && templateNames.Contains(lookupItem.GetText())).ToList(); foreach (var lookupItem in toRemove) { collector.Remove(lookupItem); } }
private void ProcessDirective([NotNull] IT4Directive directive) { IT4Token nameToken = directive.GetNameToken(); if (nameToken == null) return; DirectiveInfo directiveInfo = _directiveInfoManager.GetDirectiveByName(nameToken.GetText()); if (directiveInfo == null) return; IEnumerable<string> attributeNames = directive.GetAttributes().SelectNotNull(attr => attr.GetName()); var hashSet = new JetHashSet<string>(attributeNames, StringComparer.OrdinalIgnoreCase); foreach (DirectiveAttributeInfo attributeInfo in directiveInfo.SupportedAttributes) { if (attributeInfo.IsRequired && !hashSet.Contains(attributeInfo.Name)) { AddHighlighting(new HighlightingInfo(nameToken.GetHighlightingRange(), new MissingRequiredAttributeHighlighting(nameToken, attributeInfo.Name))); } } }
protected override bool AcceptReference(IReference reference) { var referenceExpressionReference = reference as ReferenceExpressionReference; if (referenceExpressionReference != null) { var owner = referenceExpressionReference.Owner.Qualifier as IReferenceExpression; if (owner != null) { var acceptReference = AcceptReference(owner.Reference); if (acceptReference) { return(true); } } } return(acceptableReferenceNames.IsEmpty() || reference.GetAllNames().Any(x => acceptableReferenceNames.Contains(x))); }
private void CreateProtocols(FileSystemPath protocolInstancePath) { if (!protocolInstancePath.ExistsFile) { return; } List <ProtocolInstance> protocolInstanceList; try { protocolInstanceList = ProtocolInstance.FromJson(protocolInstancePath.ReadAllText2().Text); } catch (Exception e) { myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e); return; } var protocolInstance = protocolInstanceList?.SingleOrDefault(a => a.SolutionName == mySolution.SolutionFilePath.NameWithoutExtension); if (protocolInstance == null) { return; } myLogger.Info($"EditorPlugin protocol port {protocolInstance.Port} for Solution: {protocolInstance.SolutionName}."); try { var lifetime = mySessionLifetimes.Next(); myLogger.Info("Create protocol..."); myLogger.Info("Creating SocketWire with port = {0}", protocolInstance.Port); var wire = new SocketWire.Client(lifetime, myDispatcher, protocolInstance.Port, "UnityClient"); var protocol = new Protocol("UnityEditorPlugin", new Serializers(), new Identities(IdKind.Client), myDispatcher, wire, lifetime); protocol.ThrowErrorOnOutOfSyncModels = false; protocol.OutOfSyncModels.AdviseOnce(lifetime, e => { if (myPluginInstallations.Contains(mySolution.SolutionFilePath)) { return; } myPluginInstallations.Add(mySolution.SolutionFilePath); // avoid displaying Notification multiple times on each AppDomain.Reload in Unity var appVersion = myUnityVersion.GetActualVersionForSolution(); if (appVersion < new Version(2019, 2)) { var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) => s.InstallUnity3DRiderPlugin); var isEnabled = myBoundSettingsStore.GetValueProperty <bool>(lifetime, entry, null).Value; if (!isEnabled) { myHost.PerformModelAction(model => model.OnEditorModelOutOfSync()); } } else { var notification = new NotificationModel("Advanced Unity integration is unavailable", $"Please update External Editor to {myHostProductInfo.VersionMarketingString} in Unity Preferences.", true, RdNotificationEntryType.WARN); mySolution.Locks.ExecuteOrQueue(lifetime, "OutOfSyncModels.Notify", () => myNotificationsModel.Notification(notification)); } }); wire.Connected.WhenTrue(lifetime, lf => { myLogger.Info("WireConnected."); var editor = new EditorPluginModel(lf, protocol); editor.IsBackendConnected.Set(rdVoid => true); if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.Windows) { var frontendProcess = Process.GetCurrentProcess().GetParent(); // RiderProcessId is not used on non-Windows, but this line gives bad warning in the log if (frontendProcess != null) { editor.RiderProcessId.SetValue(frontendProcess.Id); } } myHost.PerformModelAction(m => m.SessionInitialized.Value = true); SubscribeToLogs(lf, editor); SubscribeToOpenFile(editor); editor.Play.Advise(lf, b => myHost.PerformModelAction(rd => rd.Play.SetValue(b))); editor.Pause.Advise(lf, b => myHost.PerformModelAction(rd => rd.Pause.SetValue(b))); editor.ClearOnPlay.Advise(lf, time => myHost.PerformModelAction(rd => rd.ClearOnPlay(time))); editor.UnityProcessId.View(lf, (_, pid) => myHost.PerformModelAction(t => t.UnityProcessId.Set(pid))); // I have split this into groups, because want to use async api for finding reference and pass them via groups to Unity myHost.PerformModelAction(t => t.ShowFileInUnity.Advise(lf, v => editor.ShowFileInUnity.Fire(v))); myHost.PerformModelAction(t => t.ShowPreferences.Advise(lf, v => { editor.ShowPreferences.Fire(); })); editor.EditorLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s))); editor.PlayerLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s))); // Note that these are late-init properties. Once set, they are always set and do not allow nulls. // This means that if/when the Unity <-> Backend protocol closes, they still retain the last value // they had - so the front end will retain the log and application paths of the just-closed editor. // Opening a new editor instance will reconnect and push a new value through to the front end editor.UnityApplicationData.Advise(lifetime, s => myHost.PerformModelAction(a => { var version = UnityVersion.Parse(s.ApplicationVersion); a.UnityApplicationData.SetValue(new UnityApplicationData(s.ApplicationPath, s.ApplicationContentsPath, s.ApplicationVersion, UnityVersion.RequiresRiderPackage(version))); })); editor.ScriptCompilationDuringPlay.Advise(lifetime, s => myHost.PerformModelAction(a => a.ScriptCompilationDuringPlay.Set(ConvertToScriptCompilationEnum(s)))); myHost.PerformModelAction(rd => { rd.GenerateUIElementsSchema.Set((l, u) => editor.GenerateUIElementsSchema.Start(l, u).ToRdTask(l)); }); TrackActivity(editor, lf); if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel", () => { UnityModel.SetValue(editor); }); } lf.AddAction(() => { if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () => { myLogger.Info("Wire disconnected."); myHost.PerformModelAction(m => m.SessionInitialized.Value = false); UnityModel.SetValue(null); }); } }); }); } catch (Exception ex) { myLogger.Error(ex); } }
private void InstallPluginIfRequired(Lifetime lifetime, [NotNull] IProject project) { if (!myBoundSettingsStore.GetValue((UnityPluginSettings s) => s.InstallUnity3DRiderPlugin)) { return; } if (myPluginInstallations.Contains(project.ProjectFileLocation)) { return; } var installationInfo = myDetector.GetInstallationInfo(project); if (!installationInfo.ShouldInstallPlugin) { return; } var currentVersion = typeof(UnityPluginInstaller).Assembly.GetName().Version; if (currentVersion <= installationInfo.Version) { return; } var isFreshInstall = installationInfo.Version == new Version(); if (isFreshInstall) { myLogger.LogMessage(LoggingLevel.INFO, "Fresh install"); } lock (mySyncObj) { if (myPluginInstallations.Contains(project.ProjectFileLocation)) { return; } FileSystemPath installedPath; if (!TryInstall(installationInfo, out installedPath)) { myLogger.LogMessage(LoggingLevel.WARN, "Plugin was not installed"); } else { string userTitle; string userMessage; if (isFreshInstall) { userTitle = "Unity: plugin installed"; userMessage = $@"Rider plugin v{currentVersion} for the Unity Editor was automatically installed for the project '{mySolution.Name}' This allows better integration between the Unity Editor and Rider IDE. The plugin file can be found on the following path: {installedPath.MakeRelativeTo(mySolution.SolutionFilePath)}"; } else { userTitle = "Unity: plugin updated"; userMessage = $"Rider plugin was succesfully upgraded from version {installationInfo.Version} to {currentVersion}"; } myLogger.LogMessage(LoggingLevel.INFO, userTitle); var notification = new RdNotificationEntry(userTitle, userMessage, true, RdNotificationEntryType.INFO); myNotifications.Notification.Fire(notification); } myPluginInstallations.Add(project.ProjectFileLocation); } }
public static bool IsEventHandler(string shortName) { return(EventNames.Contains(shortName)); }
public UnrealPluginDetector(Lifetime lifetime, ILogger logger, CppUE4SolutionDetector solutionDetector, ISolution solution, IShellLocks locks, ISolutionLoadTasksScheduler scheduler) { myLifetime = lifetime; InstallInfoProperty = new Property <UnrealPluginInstallInfo>(myLifetime, "UnrealPlugin.InstallInfoNotification", null, true); myLogger = logger; mySolution = solution; mySolutionDetector = solutionDetector; mySolutionDetector.IsUE4Solution_Observable.Change.Advise_When(myLifetime, newValue => newValue == TriBool.True, _ => { scheduler.EnqueueTask(new SolutionLoadTask("Find installed RiderLink plugins", SolutionLoadTaskKinds.Done, () => { myLogger.Info("[UnrealLink]: Looking for RiderLink plugins"); myUnrealVersion = mySolutionDetector.Version; if (myUnrealVersion < myMinimalSupportedVersion) { locks.ExecuteOrQueue(myLifetime, "UnrealLink.CheckSupportedVersion", () => { var notification = new NotificationModel( $"Unreal Engine {myMinimalSupportedVersion}+ is required", $"<html>UnrealLink supports Unreal Engine versions starting with {myMinimalSupportedVersion}<br>" + "<b>WARNING: Advanced users only</b><br>" + "You can manually download the latest version of plugin and build It for your version of Unreal Editor<br>" + RiderContextNotificationHelper.MakeLink( "https://github.com/JetBrains/UnrealLink/releases/latest", "Download latest Unreal Editor plugin") + "</html>", true, RdNotificationEntryType.WARN, new List <NotificationHyperlink>()); var notificationsModel = Shell.Instance.GetComponent <NotificationsModel>(); notificationsModel.Notification(notification); }); return; } var installInfo = new UnrealPluginInstallInfo(); var foundEnginePlugin = TryGetEnginePluginFromSolution(solutionDetector, installInfo); ISet <FileSystemPath> uprojectLocations; using (solution.Locks.UsingReadLock()) { var allProjects = mySolution.GetAllProjects(); if (solutionDetector.SupportRiderProjectModel == CppUE4ProjectModelSupportMode.UprojectOpened) { uprojectLocations = allProjects.Where(project => { if (project.IsMiscProjectItem() || project.IsMiscFilesProject()) { return(false); } var location = project.Location; if (location == null) { return(false); } if (EXCLUDED_PROJECTS.Contains(location.NameWithoutExtension)) { return(false); } // TODO: drop this ugly check after updating to net211 where Location == "path/to/game.uproject" var isUproject = location.ExistsFile && location.ExtensionNoDot == UPROJECT_FILE_FORMAT && location.NameWithoutExtension == project.Name; return(isUproject || (location / $"{location.Name}.uproject").ExistsFile); }).Select(project => { var location = project.Location; if (location.ExistsFile) { return(location); } return(location / $"{location.Name}.uproject"); }).ToSet(); } else { uprojectLocations = allProjects.SelectMany(project => project.GetAllProjectFiles(projectFile => { var location = projectFile.Location; if (location == null || !location.ExistsFile) { return(false); } return(location.ExtensionNoDot == UPROJECT_FILE_FORMAT && location.NameWithoutExtension == project.Name); })).Select(file => file.Location).ToSet(); } } myLogger.Info($"[UnrealLink]: Found {uprojectLocations.Count} uprojects"); if (!foundEnginePlugin && !uprojectLocations.IsEmpty()) { // All projects in the solution are bound to the same engine // So take first project and use it to find Unreal Engine TryGetEnginePluginFromUproject(uprojectLocations.FirstNotNull(), installInfo); foundEnginePlugin = installInfo.EnginePlugin.IsPluginAvailable; } // Gather data about Project plugins foreach (var uprojectLocation in uprojectLocations) { myLogger.Info($"[UnrealLink]: Looking for plugin in {uprojectLocation}"); var projectPlugin = GetProjectPluginForUproject(uprojectLocation); if (projectPlugin.IsPluginAvailable) { myLogger.Info( $"[UnrealLink]: found plugin {projectPlugin.UnrealPluginRootFolder}"); } installInfo.ProjectPlugins.Add(projectPlugin); } if (foundEnginePlugin) { installInfo.Location = PluginInstallLocation.Engine; } else if (installInfo.ProjectPlugins.Any(description => description.IsPluginAvailable)) { installInfo.Location = PluginInstallLocation.Game; } else { installInfo.Location = PluginInstallLocation.NotInstalled; } InstallInfoProperty.SetValue(installInfo); })); }); }