コード例 #1
0
            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);
            }
コード例 #3
0
            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);
            }
コード例 #4
0
            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());
            }
コード例 #5
0
            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;
                }
            }
コード例 #6
0
            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());
            }
コード例 #7
0
            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));
            }
コード例 #8
0
            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)));
            }
コード例 #9
0
            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));
            }