コード例 #1
0
        public IDeclaredElement GetDeclaredElement()
        {
            var typeElement = GetTypeElement();

            if (typeElement == null)
            {
                return(null);
            }

            using (CompilationContextCookie.GetOrCreate(myProject.GetResolveContext()))
            {
                foreach (var member in typeElement.EnumerateMembers(myMethodName, typeElement.CaseSensitiveName))
                {
                    var method = member as IMethod;
                    if (method == null)
                    {
                        continue;
                    }
                    if (method.IsAbstract)
                    {
                        continue;
                    }
                    if (method.TypeParameters.Count > 0)
                    {
                        continue;
                    }

                    return(member);
                }
                return(null);
            }
        }
コード例 #2
0
        public override RdUsageGroup CreateModel(IOccurrence occurrence, IOccurrenceBrowserDescriptor descriptor)
        {
            using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
            {
                if (occurrence is ReferenceOccurrence referenceOccurrence &&
                    referenceOccurrence.PrimaryReference is IUnityYamlReference reference)
                {
                    var document   = reference.ComponentDocument;
                    var sourceFile = document.GetSourceFile();
                    if (sourceFile == null || !sourceFile.IsValid())
                    {
                        return(EmptyModel());
                    }

                    var anchor = UnitySceneDataUtil.GetAnchorFromBuffer(document.GetTextAsBuffer());
                    if (anchor == null)
                    {
                        return(EmptyModel());
                    }

                    return(CreateModel(UnityObjectPsiUtil.GetGameObjectPathFromComponent(myUnitySceneDataLocalCache, sourceFile, anchor)));
                }
            }

            return(EmptyModel());
        }
コード例 #3
0
        private List <IGenerator> GetApplicableGeneratorsFromProvider()
        {
            var result = new List <IGenerator>();

            foreach (IGenerator generator in _generatorsProvider.GetAllGenerators())
            {
                if (generator.Visible)
                {
                    generator.DataProvider = _generatorDataProvider;

                    using (CompilationContextCookie.GetOrCreate(generator.DataProvider.PsiFile.GetResolveContext()))
                    {
                        bool generatorAvailable = false;

                        try
                        {
                            generatorAvailable = generator.IsAvailable();
                        }
                        catch (Exception e)
                        {
                            // Pass to exceptions.
                        }

                        if (generatorAvailable)
                        {
                            result.Add(generator);
                        }
                    }
                }
            }

            return(result);
        }
コード例 #4
0
        public override RdUsageGroup CreateModel(IOccurrence occurrence, IOccurrenceBrowserDescriptor descriptor)
        {
            using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
            {
                if (occurrence is UnityAssetOccurrence assetOccurrence && !assetOccurrence.SourceFile.GetLocation().IsAsset())
                {
                    using (ReadLockCookie.Create())
                    {
                        var solution  = occurrence.GetSolution();
                        var processor = solution.GetComponent <AssetHierarchyProcessor>();
                        var consumer  = new UnityScenePathGameObjectConsumer();
                        processor.ProcessSceneHierarchyFromComponentToRoot(assetOccurrence.OwningElementLocation, consumer, true, true);
                        string name = "...";
                        if (consumer.NameParts.Count > 0)
                        {
                            name = string.Join("\\", consumer.NameParts);
                        }

                        return(CreateModel(name));
                    }
                }
            }

            return(EmptyModel());
        }
コード例 #5
0
        private List <HandlerCompletionItem> DetermineHandlers(ISolution solution)
        {
            var handlers = new List <HandlerCompletionItem>();

            using (ReadLockCookie.Create())
            {
                var projects = solution.GetAllProjects();

                foreach (var project in projects)
                {
                    if (!LambdaFinder.IsLambdaProjectType(project))
                    {
                        continue;
                    }
                    var psiModules = project.GetPsiModules();

                    foreach (var psiModule in psiModules)
                    {
                        using (CompilationContextCookie.OverrideOrCreate(psiModule.GetContextFromModule()))
                        {
                            var scope      = _symbolCache.GetSymbolScope(psiModule, false, true);
                            var namespaces = scope.GlobalNamespace.GetNestedNamespaces(scope);

                            foreach (var @namespace in namespaces)
                            {
                                ProcessNamespace(@namespace, scope, handlers);
                            }
                        }
                    }
                }
            }

            return(handlers);
        }
コード例 #6
0
        public override string ToString()
        {
            using (ReadLockCookie.Create())
            {
                using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                {
                    var de = DeclaredElementPointer.FindDeclaredElement();
                    if (de == null)
                    {
                        return("INVALID");
                    }

                    if (IsRelatedToScriptableObject())
                    {
                        var value = InspectorVariableUsage.Value.GetFullPresentation(GetSolution(), DeclaredElementPointer.FindDeclaredElement(), true);
                        return($"{de.ShortName} = {value}");
                    }
                    else
                    {
                        var value = InspectorVariableUsage.Value.GetPresentation(GetSolution(), DeclaredElementPointer.FindDeclaredElement(), true);
                        return($"{de.ShortName} = {value}");
                    }
                }
            }
        }
コード例 #7
0
 private IEnumerable <UnityType> GetBaseUnityTypes(UnityTypes types, ITypeElement type, Version normalisedVersion)
 {
     return(types.Types.Where(t =>
     {
         using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
             return t.SupportsVersion(normalisedVersion) && type.IsDescendantOf(t.GetTypeElement(type.Module));
     }));
 }
コード例 #8
0
ファイル: UnityType.cs プロジェクト: van800/resharper-unity
 public ITypeElement GetTypeElement([NotNull] IPsiModule module)
 {
     using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
     {
         var type = TypeFactory.CreateTypeByCLRName(myTypeName, module);
         return(type.GetTypeElement());
     }
 }
コード例 #9
0
 public ITypeElement GetTypeElement(KnownTypesCache knownTypesCache, [NotNull] IPsiModule module)
 {
     using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
     {
         var type = knownTypesCache.GetByClrTypeName(myTypeName, module);
         return(type.GetTypeElement());
     }
 }
 private static ITypeElement GetTypeElement(IClrTypeName typeName, KnownTypesCache knownTypesCache,
                                            IPsiModule module)
 {
     using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
     {
         var type = knownTypesCache.GetByClrTypeName(typeName, module);
         return(type.GetTypeElement());
     }
 }
コード例 #11
0
 public override string ToString()
 {
     using (ReadLockCookie.Create())
     {
         using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
         {
             var value = InspectorVariableUsage.Value.GetPresentation(GetSolution(), DeclaredElementPointer.FindDeclaredElement(), true);
             return($"{InspectorVariableUsage.Name} = {value}");
         }
     }
 }
コード例 #12
0
        public void NavigateToMethod(MethodReference methodReference)
        {
            var declaredElement = MethodDeclaredElement(methodReference);

            using (ReadLockCookie.Create())
            {
                using (CompilationContextCookie.GetOrCreate(UniversalModuleReferenceContext.Instance))
                {
                    declaredElement.Navigate(true);
                }
            }
        }
コード例 #13
0
 private void OnChanged(IReadOnlyCollection <ITypeElement> changedTypes)
 {
     using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
     {
         var linkedTypes   = changedTypes.SelectMany(LinkedTypesUtil.GetLinkedTypes).ToList();
         var relevantTests = linkedTypes.Select(x => _unitTestElementStuff.GetElement(x)).WhereNotNull();
         foreach (var relevantTest in relevantTests)
         {
             _unitTestResultManager.MarkOutdated(relevantTest);
         }
     }
 }
コード例 #14
0
        public override RdUsageGroup CreateModel(IOccurrence occurrence, IOccurrenceBrowserDescriptor descriptor)
        {
            using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
            {
                if (occurrence is ReferenceOccurrence referenceOccurrence &&
                    referenceOccurrence.PrimaryReference is IUnityYamlReference reference)
                {
                    return(CreateModel(UnityObjectPsiUtil.GetComponentName(reference.ComponentDocument)));
                }
            }

            return(EmptyModel());
        }
コード例 #15
0
 private void InvalidateReferencingModules(IPsiModule psiModule)
 {
     using (CompilationContextCookie.GetOrCreate(psiModule.GetContextFromModule()))
     {
         var resolveContext = CompilationContextCookie.GetContext();
         foreach (var psiModuleReference in PsiModules.GetReverseModuleReferences(psiModule, resolveContext))
         {
             if (myPsiModules.TryGetValue(psiModuleReference.Module, out var moduleSymbols))
             {
                 moduleSymbols.Invalidate();
             }
         }
     }
 }
コード例 #16
0
        // NOTE: This method assumes that the type is not a descendant of UnityEngine.Object!
        private bool IsSerializableType([CanBeNull] ITypeElement type, [NotNull] IProject project, bool isTypeUsage,
                                        bool hasSerializeReference = false)
        {
            if (!(type is IStruct || type is IClass))
            {
                return(false);
            }

            if (isTypeUsage)
            {
                // Type usage (e.g. field declaration) is stricter. Means it must be a concrete type with no type
                // parameters, unless the type usage is for [SerializeReference], which allows abstract types
                if (type is IModifiersOwner modifiersOwner && modifiersOwner.IsAbstract && !hasSerializeReference)
                {
                    return(false);
                }

                // Unity 2020.1 allows fields to have generic types. It's currently undocumented, but there are no
                // limitations on the number of type parameters, or even nested type parameters. The base type needs to
                // be serializable, but type parameters don't (if a non-serializable type parameter is used as a field,
                // it just isn't serialised).
                // https://blogs.unity3d.com/2020/03/17/unity-2020-1-beta-is-now-available-for-feedback/
                var unityVersion = myUnityVersion.GetActualVersion(project);
                if (unityVersion < new Version(2020, 1) && type is ITypeParametersOwner typeParametersOwner &&
                    typeParametersOwner.TypeParameters.Count > 0)
                {
                    return(false);
                }
            }

            if (type is IClass @class && @class.IsStaticClass())
            {
                return(false);
            }

            // System.Dictionary is special cased and excluded. We can see this in UnitySerializationLogic.cs in the
            // reference source repo. It also excludes anything with a full name beginning "System.", which includes
            // "System.Version" (which is marked [Serializable]). However, it doesn't exclude string, int, etc.
            // TODO: Rewrite this whole section to properly mimic UnitySerializationLogic.cs
            var name = type.GetClrName();

            if (Equals(name, KnownTypes.SystemVersion) || Equals(name, PredefinedType.GENERIC_DICTIONARY_FQN))
            {
                return(false);
            }

            using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                return(type.HasAttributeInstance(PredefinedType.SERIALIZABLE_ATTRIBUTE_CLASS, true));
        }
コード例 #17
0
 public override string ToString()
 {
     using (ReadLockCookie.Create())
     {
         using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
         {
             var declaredElement = DeclaredElementPointer.FindDeclaredElement();
             if (declaredElement == null)
             {
                 return("Invalid");
             }
             return(DeclaredElementMenuItemFormatter.FormatText(declaredElement, declaredElement.PresentationLanguage, out _).Text);
         }
     }
 }
        protected override void DoTest(Lifetime lifetime, IProject testProject)
        {
            var position = GetCaretPosition();

            IProjectFile item;

            if (position == null)
            {
                item = testProject.GetSubItemsRecursively().OfType <IProjectFile>().First("No project file");
            }
            else
            {
                item = (IProjectFile)testProject.FindProjectItemsByLocation(position.FileName)
                       .Single("No project file", "More than one project file");
            }

            var swea = SolutionAnalysisService.GetInstance(Solution);

            Assert.IsTrue(item.Kind == ProjectItemKind.PHYSICAL_FILE);
            using (TestPresentationMap.Cookie())
                using (swea.RunAnalysisCookie())
                {
                    using (var definition = Lifetime.Define(lifetime))
                    {
                        var boundstore = ChangeSettingsTemporarily(definition.Lifetime).BoundStore;
                        boundstore.SetValue(HighlightingSettingsAccessor.CalculateUnusedTypeMembers, InplaceUsageAnalysis);

                        ITextControl textControl = position != null
                        ? OpenTextControl(definition.Lifetime, position)
                        : OpenTextControl(definition.Lifetime, item);

                        {
                            swea.ReanalyzeFile(item.ToSourceFile());
                            using (CompilationContextCookie.GetOrCreate(textControl.GetContext(Solution)))
                            {
                                ExecuteWithGold(item, writer =>
                                {
                                    var highlightings = GetHighlightings(textControl);

                                    DumpQuickFixesAvailability(writer, highlightings, textControl, Solution);
                                });
                            }
                        }
                    }
                }
        }
コード例 #19
0
        public override RdUsageGroup CreateModel(IOccurrence occurrence, IOccurrenceBrowserDescriptor descriptor)
        {
            using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
            {
                if (occurrence is UnityAssetOccurrence assetOccurrence)
                {
                    var hierarchyContainer = assetOccurrence.GetSolution()?.GetComponent <AssetDocumentHierarchyElementContainer>();
                    var element            = hierarchyContainer?.GetHierarchyElement(assetOccurrence.OwningElementLocation, true);
                    if (element is IComponentHierarchy componentHierarchyElement)
                    {
                        return(CreateModel(AssetUtils.GetComponentName(myMetaFileGuidCache, componentHierarchyElement)));
                    }
                }
            }

            return(EmptyModel());
        }
コード例 #20
0
        public void NavigateToClass(UClass uClass)
        {
            var classSymbol = GetClassSymbol(uClass.Name.Data);

            if (classSymbol == null)
            {
                return;
            }
            var declaredElement = new CppParserSymbolDeclaredElement(_psiServices, classSymbol);

            using (ReadLockCookie.Create())
            {
                using (CompilationContextCookie.GetOrCreate(UniversalModuleReferenceContext.Instance))
                {
                    declaredElement.Navigate(true);
                }
            }
        }
コード例 #21
0
        public IEnumerable <IProject> GetProjectDependencies(IT4File file)
        {
            file.AssertContainsNoIncludeContext();
            var sourceFile     = file.LogicalPsiSourceFile.NotNull();
            var projectFile    = sourceFile.ToProjectFile().NotNull();
            var psiModule      = sourceFile.PsiModule;
            var resolveContext = projectFile.SelectResolveContext();

            using (CompilationContextCookie.GetOrCreate(resolveContext))
            {
                return(PsiModules
                       .GetModuleReferences(psiModule)
                       .Select(it => it.Module)
                       .OfType <IProjectPsiModule>()
                       .Select(it => it.Project)
                       .AsList());
            }
        }
コード例 #22
0
        private bool IsHandlerExists(Lifetime lifetime, int projectId, string className, string methodName)
        {
            var indicator = NullProgressIndicator.CreateCancellable(lifetime);

            using (TryReadLockCookie.Create(indicator, _locks,
                                            () => !lifetime.IsAlive || _locks.ContentModelLocks.IsWriteLockRequested))
            {
                var project = _projectModelViewHost.GetItemById <IProject>(projectId);
                Assertion.AssertNotNull(project, "project instance should not be null");
                _logger.Verbose($"Searching handler with name '{className}.{methodName}' in the project {project}...");

                var psiModules = project.GetPsiModules();
                foreach (var psiModule in psiModules)
                {
                    using (CompilationContextCookie.OverrideOrCreate(psiModule.GetContextFromModule()))
                    {
                        var scope = _symbolCache.GetSymbolScope(psiModule, false, true);

                        var typeElements = scope.GetElementsByQualifiedName(className).OfType <IClass>();
                        foreach (var typeElement in typeElements)
                        {
                            InterruptableActivityCookie.CheckAndThrow(indicator);
                            foreach (var method in typeElement.Methods)
                            {
                                if (method.ShortName != methodName)
                                {
                                    continue;
                                }
                                if (!LambdaFinder.IsSuitableLambdaMethod(method))
                                {
                                    continue;
                                }

                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
コード例 #23
0
        private void InvalidateReferencingModules(IPsiModule psiModule)
        {
            if (PsiModulesCaches.IsEmpty())
            {
                return;
            }

            // todo: reuse FcsProjectProvider references
            using (CompilationContextCookie.GetOrCreate(psiModule.GetContextFromModule()))
            {
                var resolveContext = CompilationContextCookie.GetContext();
                foreach (var psiModuleReference in PsiModules.GetReverseModuleReferences(psiModule, resolveContext))
                {
                    if (PsiModulesCaches.TryGetValue(psiModuleReference.Module, out var moduleSymbols))
                    {
                        moduleSymbols.Invalidate();
                    }
                }
            }
        }
        public override IDeclaredElement?GetDeclaredElement()
        {
            if (Specification.BehaviorType == null)
            {
                return(null);
            }

            using (CompilationContextCookie.OverrideOrCreate(Project.GetResolveContext(TargetFrameworkId)))
            {
                var behaviorType = UT.Facade.TypeCache.GetTypeElement(
                    Project,
                    TargetFrameworkId,
                    new ClrTypeName(Specification.BehaviorType),
                    false,
                    true);

                return(behaviorType?
                       .EnumerateMembers <IField>(FieldName, behaviorType.CaseSensitiveName)
                       .FirstOrDefault());
            }
        }
コード例 #25
0
        public static bool TryExecuteGenerator(IGenerator generator, Action executeAction)
        {
            using (CompilationContextCookie.GetOrCreate(generator.DataProvider.PsiFile.GetResolveContext()))
            {
                try
                {
                    executeAction();
                    return(true);
                }
                catch (GeneratorErrorException e)
                {
                    MessageBox.ShowError(e.Message);
                }
                catch (Exception e)
                {
                    MessageBox.ShowError(e.ToString());
                }
            }

            return(false);
        }
コード例 #26
0
        public override IEnumerable <BulbMenuItem> GetBulbMenuItems(IHighlighter highlighter)
        {
            var solution = Shell.Instance.GetComponent <SolutionsManager>().Solution;

            if (solution == null)
            {
                return(EmptyList <BulbMenuItem> .InstanceList);
            }

            var textControlManager = solution.GetComponent <ITextControlManager>();
            var textControl        = textControlManager.FocusedTextControl.Value;

            var daemon = solution.GetComponent <IDaemon>();

            if (daemon.GetHighlighting(highlighter) is NukeMarkOnGutter highlighting)
            {
                using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                    return(highlighting.GetBulbMenuItems(solution, textControl, (InvisibleAnchor)Anchor.NotNull()));
            }

            return(EmptyList <BulbMenuItem> .InstanceList);
        }
コード例 #27
0
        public override IEnumerable <BulbMenuItem> GetBulbMenuItems(IHighlighter highlighter)
        {
            var solution = Shell.Instance.GetComponent <SolutionsManager>().Solution;

            if (solution == null)
            {
                return(EmptyList <BulbMenuItem> .InstanceList);
            }

            var unityImplicitUsageHighlightingContributor = solution.GetComponent <UnityHighlightingContributor>();

            var daemon = solution.GetComponent <IDaemon>();

            if (daemon.GetHighlighting(highlighter) is UnityGutterMarkInfo highlighting)
            {
                using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                    return(unityImplicitUsageHighlightingContributor.CreateBulbItemsForUnityDeclaration(highlighting
                                                                                                        .Declaration));
            }

            return(EmptyList <BulbMenuItem> .InstanceList);
        }
コード例 #28
0
        public override string ToString()
        {
            var pointer = DeclaredElementPointer;

            if (pointer is null)
            {
                return("Invalid");
            }
            using (ReadLockCookie.Create())
            {
                using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                {
                    var element = pointer.FindDeclaredElement();
                    if (element == null)
                    {
                        return("Invalid");
                    }
                    var language = element.PresentationLanguage;
                    return(DeclaredElementMenuItemFormatter.FormatText(element, language, out _)?.Text ?? "Invalid");
                }
            }
        }
コード例 #29
0
        public void Execute(IDataContext dataContext, DelegateExecute nextExecute)
        {
            using (ReadLockCookie.Create())
            {
                var solution = dataContext.GetData(ProjectModelDataConstants.SOLUTION);
                if (solution == null)
                {
                    nextExecute();
                    return;
                }

                using (CompilationContextCookie.Create(GetResolveContext(dataContext, solution)))
                {
                    // The real code creates a modal loop here, so can use the data
                    // We use a modeless loop, so make sure the data context lasts
                    // for longer
                    var dataContextLifetimeDefinition = Lifetimes.Define(lifetime);
                    var extendedContext = dataContext.Prolongate(dataContextLifetimeDefinition.Lifetime);

                    var toExecute = GetWorkflowListToExecute(extendedContext);
                    if (toExecute == null || toExecute.Count == 0)
                    {
                        dataContextLifetimeDefinition.Terminate();
                        nextExecute();
                        return;
                    }

                    if (toExecute.HasMoreThan(1) || handler.ShowMenuWithOneItem)
                    {
                        ExecuteGroup(extendedContext, toExecute, dataContextLifetimeDefinition);
                        return;
                    }

                    handler.Execute(extendedContext, toExecute.Single().First);
                    dataContextLifetimeDefinition.Terminate();
                }
            }
        }
コード例 #30
0
        protected override void AugmentQuickInfoSessionCore(
            IQuickInfoSession session,
            IList <object> quickInfoContent,
            IDocumentMarkup documentMarkup,
            TooltipFormattingProvider tooltipFormattingProvider,
            out ITrackingSpan applicableToSpan)
        {
            applicableToSpan = null;

            ITextSnapshot textSnapshot = TextBuffer.CurrentSnapshot;
            TextRange     textRange    = GetCurrentTextRange(session, textSnapshot);
            IShellLocks   shellLocks   = Shell.Instance.GetComponent <IShellLocks>();
            Span?         finalSpan    = null;

            void GetEnhancedTooltips()
            {
                using (shellLocks.UsingReadLock()) {
                    IDocument document  = documentMarkup.Document;
                    var       presenter = new MultipleTooltipContentPresenter(tooltipFormattingProvider.GetTooltipFormatting(), document);
                    IContextBoundSettingsStore settings = document.GetSettings();
                    ISolution solution = TryGetCurrentSolution();
                    bool      hasIdentifierTooltipContent = false;

                    var resolveContext = solution != null?document.GetContext(solution) : UniversalModuleReferenceContext.Instance;

                    using (CompilationContextCookie.GetOrCreate(resolveContext)) {
                        if (solution != null)
                        {
                            DocumentRange          documentRange = textRange.CreateDocumentRange(document);
                            IdentifierContentGroup contentGroup  = GetIdentifierContentGroup(documentRange, solution, settings);
                            if (contentGroup != null)
                            {
                                foreach (IdentifierTooltipContent content in contentGroup.Identifiers)
                                {
                                    presenter.AddIdentifierTooltipContent(content);
                                    finalSpan = content.TrackingRange.ToSpan().Union(finalSpan);
                                    hasIdentifierTooltipContent = true;
                                }
                                if (contentGroup.ArgumentRole != null)
                                {
                                    presenter.AddArgumentRoleTooltipContent(contentGroup.ArgumentRole);
                                    if (finalSpan == null)
                                    {
                                        // Only track the argument role if we have nothing else displayed.
                                        // See https://github.com/MrJul/ReSharper.EnhancedTooltip/issues/70
                                        finalSpan = contentGroup.ArgumentRole.TrackingRange.ToSpan();
                                    }
                                }
                            }
                        }

                        List <Vs10Highlighter> highlighters = documentMarkup.GetHighlightersOver(textRange).OfType <Vs10Highlighter>().ToList();
                        foreach (Vs10Highlighter highlighter in highlighters)
                        {
                            IEnumerable <IReSharperTooltipContent> contents = GetTooltipContents(highlighter, highlighter.Range, documentMarkup, solution, hasIdentifierTooltipContent);
                            foreach (IReSharperTooltipContent content in contents)
                            {
                                if (presenter.TryAddReSharperContent(content))
                                {
                                    finalSpan = content.TrackingRange.ToSpan().Union(finalSpan);
                                }
                            }
                        }
                    }

                    var vsSquiggleContents = session.RetrieveVsSquiggleContents()
                                             .OfType <string>()
                                             .ToSet();

                    bool ignoredFirstVsElement = false;
                    foreach (object content in quickInfoContent)
                    {
                        if (content == null)
                        {
                            continue;
                        }

                        // ignore existing R# elements
                        if (content is IQuickInfoContent)
                        {
                            continue;
                        }

                        var contentFullName = content.GetType().FullName;

                        // ignore the first VS element, as it's the identifier tooltip and we already have one
                        if (hasIdentifierTooltipContent && !ignoredFirstVsElement)
                        {
                            if (contentFullName == VsFullTypeNames.ContainerElement ||                          /* VS 2017 >= 15.8 */
                                contentFullName == VsFullTypeNames.QuickInfoDisplayPanel ||                         /* VS 2015 and VS 2017 < 15.8 */
                                content is ITextBuffer /* VS2012 and VS2013 */)
                            {
                                ignoredFirstVsElement = true;
                                continue;
                            }
                        }

                        // ignore Roslyn's bulb info placeholder (interactive tooltip "press ctrl+.")
                        if (contentFullName == VsFullTypeNames.LightBulbQuickInfoPlaceHolder)
                        {
                            continue;
                        }

                        if (contentFullName == VsFullTypeNames.QuickInfoDisplayPanel)
                        {
                            presenter.AddVsIdentifierContent(new VsIdentifierContent(content));
                        }
                        else if (content is string stringContent && vsSquiggleContents.Contains(stringContent))
                        {
                            presenter.AddVsSquiggleContent(new VsSquiggleContent(stringContent));
                        }