private void InitializeNonDelegatedConstructor(CancellationToken cancellationToken) { var typeParametersNames = TypeToGenerateIn.GetAllTypeParameters().Select(t => t.Name).ToImmutableArray(); var parameterNames = GetParameterNames(_arguments, typeParametersNames, cancellationToken); GetParameters(_arguments, ParameterTypes, parameterNames, cancellationToken); }
private IMethodSymbol FindConstructorToDelegateTo( ImmutableArray <IParameterSymbol> parameters, ImmutableArray <TExpressionSyntax> expressions, ImmutableArray <IMethodSymbol> constructors, CancellationToken cancellationToken) { foreach (var constructor in constructors) { // Don't bother delegating to an implicit constructor. We don't want to add `: base()` as that's just // redundant for subclasses and `: this()` won't even work as we won't have an implicit constructor once // we add this new constructor. if (constructor.IsImplicitlyDeclared) { continue; } // Don't delegate to another constructor in this type if it's got the same parameter types as the // one we're generating. This can happen if we're generating the new constructor because parameter // names don't match (when a user explicitly provides named parameters). if (TypeToGenerateIn.Equals(constructor.ContainingType) && constructor.Parameters.Select(p => p.Type).SequenceEqual(ParameterTypes)) { continue; } if (GenerateConstructorHelpers.CanDelegateTo(_document, parameters, expressions, constructor) && !_service.WillCauseConstructorCycle(this, _document, constructor, cancellationToken)) { return(constructor); } } return(null); }
private bool IsCompatible(IMethodSymbol constructor, List <ITypeSymbol> parameterTypes) { Debug.Assert(constructor.Parameters.Length == parameterTypes.Count); // Don't delegate to another constructor in this type. if we're generating a new constructor with the // same parameter types. Note: this can happen if we're generating the new constructor because // parameter names don't match (when a user explicitly provides named parameters). if (TypeToGenerateIn.Equals(constructor.ContainingType) && constructor.Parameters.Select(p => p.Type).SequenceEqual(this.ParameterTypes)) { return(false); } var compilation = _document.SemanticModel.Compilation; for (var i = 0; i < constructor.Parameters.Length; i++) { var constructorParameter = constructor.Parameters[i]; var conversion = compilation.ClassifyCommonConversion(parameterTypes[i], constructorParameter.Type); if (!conversion.IsIdentity && !conversion.IsImplicit) { return(false); } } return(true); }
internal ImmutableArray <ITypeSymbol> GetParameterTypes(CancellationToken cancellationToken) { var allTypeParameters = TypeToGenerateIn.GetAllTypeParameters(); var semanticModel = _document.SemanticModel; var allTypes = _arguments.Select(a => _service.GetArgumentType(_document.SemanticModel, a, cancellationToken)); return(allTypes.Select(t => FixType(t, semanticModel, allTypeParameters)).ToImmutableArray()); }
private void DetermineFieldType( SemanticDocument semanticDocument, CancellationToken cancellationToken) { var typeInference = semanticDocument.Document.GetLanguageService <ITypeInferenceService>(); var inferredType = typeInference.InferType( semanticDocument.SemanticModel, SimpleNameOrMemberAccessExpressionOpt, objectAsDefault: true, name: IdentifierToken.ValueText, cancellationToken: cancellationToken); var compilation = semanticDocument.SemanticModel.Compilation; inferredType = inferredType.SpecialType == SpecialType.System_Void ? compilation.ObjectType : inferredType; if (IsInConditionalAccessExpression) { inferredType = inferredType.RemoveNullableIfPresent(); } if (inferredType.IsDelegateType() && !inferredType.CanBeReferencedByName) { var namedDelegateType = inferredType.GetDelegateType(compilation)?.DelegateInvokeMethod?.ConvertToType(compilation); if (namedDelegateType != null) { inferredType = namedDelegateType; } } // Substitute 'object' for all captured method type parameters. Note: we may need to // do this for things like anonymous types, as well as captured type parameters that // aren't in scope in the destination type. var capturedMethodTypeParameters = inferredType.GetReferencedMethodTypeParameters(); var mapping = capturedMethodTypeParameters.ToDictionary(tp => tp, tp => compilation.ObjectType); TypeMemberType = inferredType.SubstituteTypes(mapping, compilation); var availableTypeParameters = TypeToGenerateIn.GetAllTypeParameters(); TypeMemberType = TypeMemberType.RemoveUnavailableTypeParameters( compilation, availableTypeParameters); var enclosingMethodSymbol = semanticDocument.SemanticModel.GetEnclosingSymbol <IMethodSymbol>(SimpleNameOrMemberAccessExpressionOpt.SpanStart, cancellationToken); if (enclosingMethodSymbol != null && enclosingMethodSymbol.TypeParameters != null && enclosingMethodSymbol.TypeParameters.Length != 0) { var combinedTypeParameters = new List <ITypeParameterSymbol>(); combinedTypeParameters.AddRange(availableTypeParameters); combinedTypeParameters.AddRange(enclosingMethodSymbol.TypeParameters); LocalType = inferredType.RemoveUnavailableTypeParameters( compilation, combinedTypeParameters); } else { LocalType = TypeMemberType; } }
internal ImmutableArray <ITypeSymbol> GetParameterTypes( TService service, SemanticDocument document, CancellationToken cancellationToken) { var allTypeParameters = TypeToGenerateIn.GetAllTypeParameters(); var semanticModel = document.SemanticModel; var allTypes = AttributeArguments != null ? AttributeArguments.Select(a => service.GetAttributeArgumentType(semanticModel, a, cancellationToken)) : Arguments.Select(a => service.GetArgumentType(semanticModel, a, cancellationToken)); return(allTypes.Select(t => FixType(t, semanticModel, allTypeParameters)).ToImmutableArray()); }
private async Task <bool> TryInitializeAsync( TService service, SemanticDocument document, SyntaxNode node, CancellationToken cancellationToken) { if (service.IsIdentifierNameGeneration(node)) { if (!TryInitializeIdentifierName(service, document, (TSimpleNameSyntax)node, cancellationToken)) { return(false); } } else { return(false); } // Ok. It either didn't bind to any symbols, or it bound to a symbol but with // errors. In the former case we definitely want to offer to generate a field. In // the latter case, we want to generate a field *unless* there's an existing member // with the same name. Note: it's ok if there's an existing field with the same // name. var existingMembers = TypeToGenerateIn.GetMembers(IdentifierToken.ValueText); if (existingMembers.Any()) { // TODO: Code coverage There was an existing member that the new member would // clash with. return(false); } cancellationToken.ThrowIfCancellationRequested(); TypeToGenerateIn = await SymbolFinder.FindSourceDefinitionAsync(TypeToGenerateIn, document.Project.Solution, cancellationToken).ConfigureAwait(false) as INamedTypeSymbol; if (!service.ValidateTypeToGenerateIn( document.Project.Solution, TypeToGenerateIn, true, EnumType)) { return(false); } return(CodeGenerator.CanAdd(document.Project.Solution, TypeToGenerateIn, cancellationToken)); }
protected async Task <bool> TryFinishInitializingStateAsync(TService service, SemanticDocument document, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); TypeToGenerateIn = await SymbolFinder.FindSourceDefinitionAsync(TypeToGenerateIn, document.Project.Solution, cancellationToken).ConfigureAwait(false) as INamedTypeSymbol; if (TypeToGenerateIn.IsErrorType()) { return(false); } if (!service.ValidateTypeToGenerateIn(document.Project.Solution, TypeToGenerateIn, IsStatic, ClassInterfaceModuleStructTypes)) { return(false); } if (!CodeGenerator.CanAdd(document.Project.Solution, TypeToGenerateIn, cancellationToken)) { return(false); } // Ok. It either didn't bind to any symbols, or it bound to a symbol but with // errors. In the former case we definitely want to offer to generate a method. In // the latter case, we want to generate a method *unless* there's an existing method // with the same signature. var existingMethods = TypeToGenerateIn.GetMembers(IdentifierToken.ValueText) .OfType <IMethodSymbol>(); var destinationProvider = document.Project.Solution.Workspace.Services.GetLanguageServices(TypeToGenerateIn.Language); var syntaxFacts = destinationProvider.GetService <ISyntaxFactsService>(); var syntaxFactory = destinationProvider.GetService <SyntaxGenerator>(); IsContainedInUnsafeType = service.ContainingTypesOrSelfHasUnsafeKeyword(TypeToGenerateIn); var generatedMethod = SignatureInfo.GenerateMethod(syntaxFactory, false, cancellationToken); return(!existingMethods.Any(m => SignatureComparer.Instance.HaveSameSignature(m, generatedMethod, caseSensitive: syntaxFacts.IsCaseSensitive, compareParameterName: true, isParameterCaseSensitive: syntaxFacts.IsCaseSensitive))); }
private async Task <bool> TryInitializeAsync( TService service, SemanticDocument document, SyntaxNode node, CancellationToken cancellationToken) { if (service.IsIdentifierNameGeneration(node)) { // Cases that we deal with currently: // // 1) expr.Goo // 2) expr->Goo // 3) Goo if (!TryInitializeSimpleName(service, document, (TSimpleNameSyntax)node, cancellationToken)) { return(false); } } else if (service.IsExplicitInterfaceGeneration(node)) { // 4) bool IGoo.NewProp if (!TryInitializeExplicitInterface(service, document, node, cancellationToken)) { return(false); } } else { return(false); } // Ok. It either didn't bind to any symbols, or it bound to a symbol but with // errors. In the former case we definitely want to offer to generate a field. In // the latter case, we want to generate a field *unless* there's an existing member // with the same name. Note: it's ok if there's a method with the same name. var existingMembers = TypeToGenerateIn.GetMembers(IdentifierToken.ValueText) .Where(m => m.Kind != SymbolKind.Method); if (existingMembers.Any()) { // TODO: Code coverage // There was an existing method that the new method would clash with. return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } TypeToGenerateIn = await SymbolFinder.FindSourceDefinitionAsync(TypeToGenerateIn, document.Project.Solution, cancellationToken).ConfigureAwait(false) as INamedTypeSymbol; if (!service.ValidateTypeToGenerateIn( document.Project.Solution, TypeToGenerateIn, IsStatic, ClassInterfaceModuleStructTypes)) { return(false); } IsContainedInUnsafeType = service.ContainingTypesOrSelfHasUnsafeKeyword(TypeToGenerateIn); return(CanGenerateLocal() || CodeGenerator.CanAdd(document.Project.Solution, TypeToGenerateIn, cancellationToken)); }