示例#1
0
        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));
        }
示例#3
0
            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);
            }
示例#4
0
 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));
 }
示例#5
0
        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));
        }
示例#6
0
 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);
 }
示例#7
0
        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)));
        }
示例#8
0
        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);
        }
示例#9
0
        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));
            });
        }
示例#12
0
        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)));
 }
示例#14
0
 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);
        }
示例#16
0
        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)));
            }
        }
示例#17
0
        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);
            }
        }
示例#18
0
        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);
            }
        }
示例#21
0
        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);
            }
        }
示例#22
0
 public static bool IsEventHandler(string shortName)
 {
     return(EventNames.Contains(shortName));
 }
示例#23
0
        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);
                }));
            });
        }