public async System.Threading.Tasks.Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, CancellationToken cancellationToken) { Contract.ThrowIfFalse(document.IsFromPrimaryBranch()); cancellationToken.ThrowIfCancellationRequested(); if (!_optionService.GetOption(InternalFeatureOnOffOptions.DesignerAttributes)) { return; } // use tree version so that things like compiler option changes are considered var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false); var projectVersion = await document.Project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false); var semanticVersion = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false); var existingData = await _state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false); if (existingData != null) { // check whether we can use the data as it is (can happen when re-using persisted data from previous VS session) if (CheckVersions(document, textVersion, projectVersion, semanticVersion, existingData)) { var workspace = document.Project.Solution.Workspace as VisualStudioWorkspaceImpl; RegisterDesignerAttribute(workspace, document.Id, existingData.DesignerAttributeArgument); return; } } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); // Delay getting any of these until we need them, but hold on to them once we have them. string designerAttributeArgument = null; Compilation compilation = null; INamedTypeSymbol designerAttribute = null; SemanticModel model = null; // get type defined in current tree foreach (var typeNode in GetAllTopLevelTypeDefined(root)) { cancellationToken.ThrowIfCancellationRequested(); if (HasAttributesOrBaseTypeOrIsPartial(typeNode)) { if (designerAttribute == null) { if (compilation == null) { compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); } designerAttribute = compilation.DesignerCategoryAttributeType(); if (designerAttribute == null) { // The DesignerCategoryAttribute doesn't exist. InvalidateDocument(document); return; } } if (model == null) { model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } var definedType = model.GetDeclaredSymbol(typeNode, cancellationToken) as INamedTypeSymbol; if (definedType == null) { continue; } // walk up type chain foreach (var type in definedType.GetBaseTypesAndThis()) { cancellationToken.ThrowIfCancellationRequested(); // if it has designer attribute, set it var attribute = type.GetAttributes().Where(d => designerAttribute.Equals(d.AttributeClass)).FirstOrDefault(); if (attribute != null && attribute.ConstructorArguments.Length == 1) { designerAttributeArgument = GetArgumentString(attribute.ConstructorArguments[0]); await RegisterDesignerAttributeAndSaveStateAsync(document, textVersion, semanticVersion, designerAttributeArgument, existingData, cancellationToken).ConfigureAwait(false); return; } } } // check only first type if (ProcessOnlyFirstTypeDefined()) { break; } } await RegisterDesignerAttributeAndSaveStateAsync(document, textVersion, semanticVersion, designerAttributeArgument, existingData, cancellationToken).ConfigureAwait(false); }