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); }