Beispiel #1
0
            private async Task <bool> TryInitializeAsync(
                TService service,
                SemanticDocument document,
                SyntaxNode node,
                CancellationToken cancellationToken)
            {
                if (!(node is TSimpleNameSyntax))
                {
                    return(false);
                }

                this.SimpleName = (TSimpleNameSyntax)node;
                var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();

                syntaxFacts.GetNameAndArityOfSimpleName(this.SimpleName, out var name, out var arity);

                this.Name           = name;
                this.NameIsVerbatim = syntaxFacts.IsVerbatimIdentifier(this.SimpleName.GetFirstToken());
                if (string.IsNullOrWhiteSpace(this.Name))
                {
                    return(false);
                }
                // We only support simple names or dotted names.  i.e. "(some + expr).Goo" is not a
                // valid place to generate a type for Goo.
                if (!service.TryInitializeState(document, this.SimpleName, cancellationToken, out var generateTypeServiceStateOptions))
                {
                    return(false);
                }

                if (char.IsLower(name[0]) && !document.SemanticModel.Compilation.IsCaseSensitive)
                {
                    // It's near universal in .Net that types start with a capital letter.  As such,
                    // if this name starts with a lowercase letter, don't even bother to offer
                    // "generate type".  The user most likely wants to run 'Add Import' (which will
                    // then fix up a case where they typed an existing type name in lowercase,
                    // intending the fix to case correct it).
                    return(false);
                }

                this.NameOrMemberAccessExpression = generateTypeServiceStateOptions.NameOrMemberAccessExpression;
                this.ObjectCreationExpressionOpt  = generateTypeServiceStateOptions.ObjectCreationExpressionOpt;

                var semanticModel = document.SemanticModel;
                var info          = semanticModel.GetSymbolInfo(this.SimpleName, cancellationToken);

                if (info.Symbol != null)
                {
                    // This bound, so no need to generate anything.
                    return(false);
                }

                var semanticFacts = document.Project.LanguageServices.GetService <ISemanticFactsService>();

                if (!semanticFacts.IsTypeContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsExpressionContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsStatementContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsNameOfContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsNamespaceContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken))
                {
                    return(false);
                }

                // If this isn't something that can be created, then don't bother offering to create
                // it.
                if (info.CandidateReason == CandidateReason.NotCreatable)
                {
                    return(false);
                }

                if (info.CandidateReason == CandidateReason.Inaccessible ||
                    info.CandidateReason == CandidateReason.NotReferencable ||
                    info.CandidateReason == CandidateReason.OverloadResolutionFailure)
                {
                    // We bound to something inaccessible, or overload resolution on a
                    // constructor call failed.  Don't want to offer GenerateType here.
                    return(false);
                }

                if (this.ObjectCreationExpressionOpt != null)
                {
                    // If we're new'ing up something illegal, then don't offer generate type.
                    var typeInfo = semanticModel.GetTypeInfo(this.ObjectCreationExpressionOpt, cancellationToken);
                    if (typeInfo.Type.IsModuleType())
                    {
                        return(false);
                    }
                }

                await DetermineNamespaceOrTypeToGenerateInAsync(service, document, cancellationToken).ConfigureAwait(false);

                // Now, try to infer a possible base type for this new class/interface.
                this.InferBaseType(service, document, cancellationToken);
                this.IsInterface         = GenerateInterface(service, cancellationToken);
                this.IsStruct            = GenerateStruct(service, semanticModel, cancellationToken);
                this.IsAttribute         = this.BaseTypeOrInterfaceOpt != null && this.BaseTypeOrInterfaceOpt.Equals(semanticModel.Compilation.AttributeType());
                this.IsException         = this.BaseTypeOrInterfaceOpt != null && this.BaseTypeOrInterfaceOpt.Equals(semanticModel.Compilation.ExceptionType());
                this.IsMembersWithModule = generateTypeServiceStateOptions.IsMembersWithModule;
                this.IsTypeGeneratedIntoNamespaceFromMemberAccess = generateTypeServiceStateOptions.IsTypeGeneratedIntoNamespaceFromMemberAccess;
                this.IsInterfaceOrEnumNotAllowedInTypeContext     = generateTypeServiceStateOptions.IsInterfaceOrEnumNotAllowedInTypeContext;
                this.IsDelegateAllowed     = generateTypeServiceStateOptions.IsDelegateAllowed;
                this.IsDelegateOnly        = generateTypeServiceStateOptions.IsDelegateOnly;
                this.IsEnumNotAllowed      = generateTypeServiceStateOptions.IsEnumNotAllowed;
                this.DelegateMethodSymbol  = generateTypeServiceStateOptions.DelegateCreationMethodSymbol;
                this.IsClassInterfaceTypes = generateTypeServiceStateOptions.IsClassInterfaceTypes;
                this.IsSimpleNameGeneric   = service.IsGenericName(this.SimpleName);
                this.PropertiesToGenerate  = generateTypeServiceStateOptions.PropertiesToGenerate;

                if (this.IsAttribute && this.TypeToGenerateInOpt.GetAllTypeParameters().Any())
                {
                    this.TypeToGenerateInOpt = null;
                }

                return(this.TypeToGenerateInOpt != null || this.NamespaceToGenerateInOpt != null);
            }
            private bool TryInitialize(
                TService service,
                SemanticDocument document,
                SyntaxNode node,
                CancellationToken cancellationToken)
            {
                if (!(node is TSimpleNameSyntax))
                {
                    return(false);
                }

                this.SimpleName = (TSimpleNameSyntax)node;
                string name;
                int    arity;
                var    syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();

                syntaxFacts.GetNameAndArityOfSimpleName(this.SimpleName, out name, out arity);

                this.Name           = name;
                this.NameIsVerbatim = syntaxFacts.IsVerbatimIdentifier(this.SimpleName.GetFirstToken());
                if (string.IsNullOrWhiteSpace(this.Name))
                {
                    return(false);
                }

                // We only support simple names or dotted names.  i.e. "(some + expr).Foo" is not a
                // valid place to generate a type for Foo.
                GenerateTypeServiceStateOptions generateTypeServiceStateOptions;

                if (!service.TryInitializeState(document, this.SimpleName, cancellationToken, out generateTypeServiceStateOptions))
                {
                    return(false);
                }

                this.NameOrMemberAccessExpression = generateTypeServiceStateOptions.NameOrMemberAccessExpression;
                this.ObjectCreationExpressionOpt  = generateTypeServiceStateOptions.ObjectCreationExpressionOpt;

                var semanticModel = document.SemanticModel;
                var info          = semanticModel.GetSymbolInfo(this.SimpleName, cancellationToken);

                if (info.Symbol != null)
                {
                    // This bound, so no need to generate anything.
                    return(false);
                }

                var semanticFacts = document.Project.LanguageServices.GetService <ISemanticFactsService>();

                if (!semanticFacts.IsTypeContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsExpressionContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsStatementContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsNameOfContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken) &&
                    !semanticFacts.IsNamespaceContext(semanticModel, this.NameOrMemberAccessExpression.SpanStart, cancellationToken))
                {
                    return(false);
                }

                // If this isn't something that can be created, then don't bother offering to create
                // it.
                if (info.CandidateReason == CandidateReason.NotCreatable)
                {
                    return(false);
                }

                if (info.CandidateReason == CandidateReason.Inaccessible ||
                    info.CandidateReason == CandidateReason.NotReferencable ||
                    info.CandidateReason == CandidateReason.OverloadResolutionFailure)
                {
                    // We bound to something inaccessible, or overload resolution on a
                    // constructor call failed.  Don't want to offer GenerateType here.
                    return(false);
                }

                if (this.ObjectCreationExpressionOpt != null)
                {
                    // If we're new'ing up something illegal, then don't offer generate type.
                    var typeInfo = semanticModel.GetTypeInfo(this.ObjectCreationExpressionOpt, cancellationToken);
                    if (typeInfo.Type.IsModuleType())
                    {
                        return(false);
                    }
                }

                DetermineNamespaceOrTypeToGenerateIn(service, document, cancellationToken);

                // Now, try to infer a possible base type for this new class/interface.
                this.InferBaseType(service, document, cancellationToken);
                this.IsInterface         = GenerateInterface(service, cancellationToken);
                this.IsStruct            = GenerateStruct(service, semanticModel, cancellationToken);
                this.IsAttribute         = this.BaseTypeOrInterfaceOpt != null && this.BaseTypeOrInterfaceOpt.Equals(semanticModel.Compilation.AttributeType());
                this.IsException         = this.BaseTypeOrInterfaceOpt != null && this.BaseTypeOrInterfaceOpt.Equals(semanticModel.Compilation.ExceptionType());
                this.IsMembersWithModule = generateTypeServiceStateOptions.IsMembersWithModule;
                this.IsTypeGeneratedIntoNamespaceFromMemberAccess = generateTypeServiceStateOptions.IsTypeGeneratedIntoNamespaceFromMemberAccess;
                this.IsInterfaceOrEnumNotAllowedInTypeContext     = generateTypeServiceStateOptions.IsInterfaceOrEnumNotAllowedInTypeContext;
                this.IsDelegateAllowed     = generateTypeServiceStateOptions.IsDelegateAllowed;
                this.IsDelegateOnly        = generateTypeServiceStateOptions.IsDelegateOnly;
                this.IsEnumNotAllowed      = generateTypeServiceStateOptions.IsEnumNotAllowed;
                this.DelegateMethodSymbol  = generateTypeServiceStateOptions.DelegateCreationMethodSymbol;
                this.IsClassInterfaceTypes = generateTypeServiceStateOptions.IsClassInterfaceTypes;
                this.IsSimpleNameGeneric   = service.IsGenericName(this.SimpleName);
                this.PropertiesToGenerate  = generateTypeServiceStateOptions.PropertiesToGenerate;

                if (this.IsAttribute && this.TypeToGenerateInOpt.GetAllTypeParameters().Any())
                {
                    this.TypeToGenerateInOpt = null;
                }

                return(this.TypeToGenerateInOpt != null || this.NamespaceToGenerateInOpt != null);
            }