Example #1
0
        private static MethodDeclarationSyntax GenerateMethodDeclarationWorker(
            IMethodSymbol method, CodeGenerationDestination destination, CodeGenerationOptions options)
        {
            var hasNoBody = !options.GenerateMethodBodies ||
                            destination == CodeGenerationDestination.InterfaceType ||
                            method.IsAbstract;

            var explicitInterfaceSpecifier = GenerateExplicitInterfaceSpecifier(method.ExplicitInterfaceImplementations);

            var returnType = method.ReturnsByRef
                ? method.ReturnType.GenerateRefTypeSyntax()
                : method.ReturnType.GenerateTypeSyntax();

            return AddCleanupAnnotationsTo(SyntaxFactory.MethodDeclaration(
                attributeLists: GenerateAttributes(method, options, explicitInterfaceSpecifier != null),
                modifiers: GenerateModifiers(method, destination, options),
                returnType: returnType,
                explicitInterfaceSpecifier: explicitInterfaceSpecifier,
                identifier: method.Name.ToIdentifierToken(),
                typeParameterList: GenerateTypeParameterList(method, options),
                parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, explicitInterfaceSpecifier != null, options),
                constraintClauses: GenerateConstraintClauses(method),
                body: hasNoBody ? null : StatementGenerator.GenerateBlock(method),
                expressionBody: default(ArrowExpressionClauseSyntax),
                semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken()));
        }
        private IEnumerable<SignatureHelpParameter> GetDelegateTypeParameters(IMethodSymbol invokeMethod, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
        {
            const string TargetName = "target";

            var parts = new List<SymbolDisplayPart>();
            parts.AddRange(invokeMethod.ReturnType.ToMinimalDisplayParts(semanticModel, position));
            parts.Add(Space());
            parts.Add(Punctuation(SyntaxKind.OpenParenToken));

            var first = true;
            foreach (var parameter in invokeMethod.Parameters)
            {
                if (!first)
                {
                    parts.Add(Punctuation(SyntaxKind.CommaToken));
                    parts.Add(Space());
                }

                first = false;
                parts.AddRange(parameter.Type.ToMinimalDisplayParts(semanticModel, position));
            }

            parts.Add(Punctuation(SyntaxKind.CloseParenToken));
            parts.Add(Space());
            parts.Add(new SymbolDisplayPart(SymbolDisplayPartKind.ParameterName, null, TargetName));

            yield return new SignatureHelpParameter(
                TargetName,
                isOptional: false,
                documentationFactory: null,
                displayParts: parts);
        }
        private static bool IsDestructor(IMethodSymbol method)
        {
            if (method.MethodKind == MethodKind.Destructor)
            {
                return true; // for C#
            }

            if (method.Name != "Finalize" || method.Parameters.Length != 0 || !method.ReturnsVoid)
            {
                return false;
            }

            var overridden = method.OverriddenMethod;
            if (overridden == null)
            {
                return false;
            }

            for (var o = overridden.OverriddenMethod; o != null; o = o.OverriddenMethod)
            {
                overridden = o;
            }

            return overridden.ContainingType.SpecialType == SpecialType.System_Object; // it is object.Finalize
        }
 private static bool IsMethodCandidate(IMethodSymbol methodSymbol, Compilation compilation)
 {
     return methodSymbol.IsAsync &&
         methodSymbol.ReturnsVoid &&
         methodSymbol.IsChangeable() &&
         !methodSymbol.IsProbablyEventHandler(compilation);
 }
 /// <summary>
 /// Is this a method on <see cref="Enumerable" /> which takes only a single parameter?
 /// </summary>
 /// <remarks>
 /// Many of the methods we target, like Last, have overloads that take a filter delegate.  It is 
 /// completely appropriate to use such methods even with <see cref="IReadOnlyList{T}" />.  Only the single parameter
 /// ones are suspect
 /// </remarks>
 private static bool IsSingleParameterLinqMethod(IMethodSymbol methodSymbol, ITypeSymbol enumerableType)
 {
     Debug.Assert(methodSymbol.ReducedFrom == null);
     return
         methodSymbol.ContainingSymbol.Equals(enumerableType) &&
         methodSymbol.Parameters.Length == 1;
 }
        private static bool ParameterTypesMatch(SemanticDocument document, IList<ITypeSymbol> parameterTypes, IMethodSymbol method)
        {
            if (method == null)
            {
                return false;
            }

            if (parameterTypes.Count < method.Parameters.Length)
            {
                return false;
            }

            var compilation = document.SemanticModel.Compilation;
            var semanticFactsService = document.Document.GetLanguageService<ISemanticFactsService>();

            for (var i = 0; i < parameterTypes.Count; i++)
            {
                var type1 = parameterTypes[i];
                if (type1 != null)
                {
                    var type2 = method.Parameters[i].Type;

                    if (!semanticFactsService.IsAssignableTo(type1, type2, compilation))
                    {
                        return false;
                    }
                }
            }

            return true;
        }
 /// <summary>
 /// Returns a list of method symbols from a given list of the method symbols, which has its parameter type as
 /// expectedParameterType as its last parameter in addition to matching all the other parameter types of the 
 /// selectedOverload method symbol
 /// </summary>
 /// <param name="methods">List of <see cref="IMethodSymbol"/> to scan for possible overloads</param>
 /// <param name="selectedOverload"><see cref="IMethodSymbol"/> that is currently picked by the user</param>
 /// <param name="expectedTrailingParameterType"><see cref="INamedTypeSymbol"/> type of the leading parameter or the trailing parameter</param>
 public static IEnumerable<IMethodSymbol> GetMethodOverloadsWithDesiredParameterAtTrailing(
      this IEnumerable<IMethodSymbol> methods,
      IMethodSymbol selectedOverload,
      INamedTypeSymbol expectedTrailingParameterType)
 {
     return GetMethodOverloadsWithDesiredParameterAtLeadingOrTrailing(methods, selectedOverload, expectedTrailingParameterType, trailingOnly: true);
 }
Example #8
0
        protected override void ReadSymbol(IMethodSymbol methodSymbol)
        {
            // we don't need to know about static members
            // because they won't be delegated from child to mixin
            if (methodSymbol.IsStatic)
                return;

            // skip methods that are not visible to the outside world
            if (methodSymbol.DeclaredAccessibility == Accessibility.Private ||
                methodSymbol.DeclaredAccessibility == Accessibility.Protected)
                return;

            // skip all property accessors and ctors
            if (methodSymbol.MethodKind == MethodKind.Ordinary)
            {
                var isOverrideFromObject = 
                    methodSymbol.IsOverride &&
                    methodSymbol.OverriddenMethod
                    ?.ContainingType.SpecialType == SpecialType.System_Object;
                var method = new Method(
                    methodSymbol.Name,
                    methodSymbol.ReturnType,
                    isOverrideFromObject)
                {
                    IsAbstract = methodSymbol.IsAbstract,
                    IsOverride = methodSymbol.IsOverride,
                    IsInternal = methodSymbol.DeclaredAccessibility.HasFlag(Accessibility.Internal),
                    Documentation = new DocumentationComment(methodSymbol.GetDocumentationCommentXml())
                };

                var parameterReader = new ParameterSymbolReader(method);
                parameterReader.VisitSymbol(methodSymbol);
                _methods.AddMethod(method);
            }
        }
        public static IParameterSymbol GetParameterSymbol(ArgumentSyntax argument, ArgumentListSyntax argumentList, IMethodSymbol method)
        {
            if (!argumentList.Arguments.Contains(argument) ||
                method == null)
            {
                return null;
            }

            if (argument.NameColon != null)
            {
                return method.Parameters
                    .FirstOrDefault(symbol => symbol.Name == argument.NameColon.Name.Identifier.ValueText);
            }

            var argumentIndex = argumentList.Arguments.IndexOf(argument);
            var parameterIndex = argumentIndex;

            if (parameterIndex >= method.Parameters.Length)
            {
                var p = method.Parameters.Last();
                return p.IsParams ? p : null;
            }
            var parameter = method.Parameters[parameterIndex];
            return parameter;
        }
 private SyntaxNode GetInvertedStatement(
     SyntaxGenerator generator, IMethodSymbol containingOperator, Compilation compilation)
 {
     if (containingOperator.Name == WellKnownMemberNames.EqualityOperatorName)
     {
         return generator.ReturnStatement(
             generator.LogicalNotExpression(
                 generator.ValueEqualsExpression(
                     generator.IdentifierName(containingOperator.Parameters[0].Name),
                     generator.IdentifierName(containingOperator.Parameters[1].Name))));
     }
     else if (containingOperator.Name == WellKnownMemberNames.InequalityOperatorName)
     {
         return generator.ReturnStatement(
             generator.LogicalNotExpression(
                 generator.ValueNotEqualsExpression(
                     generator.IdentifierName(containingOperator.Parameters[0].Name),
                     generator.IdentifierName(containingOperator.Parameters[1].Name))));
     }
     else
     {
         // If it's a  <   >   <=   or  >=   operator then we can't simply invert a call
         // to the existing operator.  i.e. the body of the "<" method should *not* be:
         //    return !(a > b);
         // Just provide a throwing impl for now.
         return generator.DefaultMethodStatement(compilation);
     }
 }
 private static bool IsGetHashCodeOverride(IMethodSymbol method)
 {
     return method.IsOverride &&
            method.ReturnType.SpecialType == SpecialType.System_Int32 &&
            method.Parameters.Length == 0 &&
            IsObjectMethodOverride(method);
 }
Example #12
0
 public static SyntaxNode getMethodDeclaration(IMethodSymbol el)
 {
     var meth = (el.PartialImplementationPart != null) ? el.PartialImplementationPart : el;
     var declarings = meth.DeclaringSyntaxReferences;
     if (declarings == null || declarings.Count() == 0) return null;
     return declarings.First().GetSyntax();
 }
 private static bool MarkedWithStringFormatMethodAttribute(IMethodSymbol method)
 {
     return 
         method.GetAttributes()
         .Select(a => a.AttributeClass.FullName())
         .Any(a => a == "JetBrains.Annotations.StringFormatMethodAttribute");
 }
        public static bool IsFormattableCall(IMethodSymbol method, SemanticModel semanticModel)
        {
            _formattableMembersByNamedTypes = GetFormattableMembers(semanticModel);
            LazyInitializer.EnsureInitialized(ref _formattableMembersByFullName, () => GetFormattableMembersByFullName());

            // Some well-known types we know upfront
            string methodName;
            if (_formattableMembersByNamedTypes.TryGetValue(method.ReceiverType, out methodName))
            {
                if (method.Name == methodName)
                {
                    return true;
                }
            }

            // But some types we can't reference from Portable library, for instance, System.Console
            if (_formattableMembersByFullName.TryGetValue(method.ReceiverType.FullName(), out methodName))
            {
                // Valid only if method has 'format' argument! 
                // TODO: need to extend the dictionary and provide format argument name!
                if (method.Name == methodName && method.Parameters.Any(p => p.Name == expectedFormatArgumentName))
                {
                    return true;
                }
            }

            if (MarkedWithStringFormatMethodAttribute(method))
            {
                return true;
            }

            return false;
        }
 internal static IPropertySymbol CreatePropertySymbol(
     INamedTypeSymbol containingType,
     IList<AttributeData> attributes,
     Accessibility accessibility,
     DeclarationModifiers modifiers,
     ITypeSymbol type,
     IPropertySymbol explicitInterfaceSymbol,
     string name,
     IList<IParameterSymbol> parameters,
     IMethodSymbol getMethod,
     IMethodSymbol setMethod,
     bool isIndexer = false,
     SyntaxNode initializer = null)
 {
     var result = new CodeGenerationPropertySymbol(
         containingType,
         attributes,
         accessibility,
         modifiers,
         type,
         explicitInterfaceSymbol,
         name,
         isIndexer,
         parameters,
         getMethod,
         setMethod);
     CodeGenerationPropertyInfo.Attach(result, modifiers.IsNew, modifiers.IsUnsafe, initializer);
     return result;
 }
        public static bool TryGetParameterSymbol(ArgumentSyntax argument, ArgumentListSyntax argumentList,
            IMethodSymbol method, out IParameterSymbol parameter)
        {
            parameter = null;
            if (!argumentList.Arguments.Contains(argument) ||
                method == null ||
                method.IsVararg)
            {
                return false;
            }

            if (argument.NameColon != null)
            {
                parameter = method.Parameters
                    .FirstOrDefault(symbol => symbol.Name == argument.NameColon.Name.Identifier.ValueText);
                return parameter != null;
            }

            var argumentIndex = argumentList.Arguments.IndexOf(argument);
            var parameterIndex = argumentIndex;

            if (parameterIndex >= method.Parameters.Length)
            {
                var lastParameter = method.Parameters.Last();
                parameter = lastParameter.IsParams ? lastParameter : null;
                return parameter != null;
            }
            parameter = method.Parameters[parameterIndex];
            return true;
        }
        private static string ExpandedMethodName(IMethodSymbol method)
        {
            var ret = new StringBuilder(20);

            ret.Append(method.Name);
            ret.Append("_");

            foreach (var param in method.Parameters)
            {
                ret.Append(param.Type.Name);

                var named = param.Type as INamedTypeSymbol;
                if (named != null)
                {
                    foreach (var typeArg in named.TypeArguments)
                    {
                        if (typeArg.TypeKind != TypeKind.TypeParameter)
                            ret.Append(typeArg.Name);
                    }
                }

                ret.Append("_");
            }

            ret.Remove(ret.Length - 1, 1);
            return ret.ToString();
        }
 private static bool IsEqualsOverride(IMethodSymbol method)
 {
     return method.IsOverride &&
            method.ReturnType.SpecialType == SpecialType.System_Boolean &&
            method.Parameters.Length == 1 &&
            method.Parameters[0].Type.SpecialType == SpecialType.System_Object;
 }
 public UnusedParametersAnalyzer(IMethodSymbol method)
 {
     // Initialization: Assume all parameters are unused.
     var parameters = method.Parameters.Where(p => !p.IsImplicitlyDeclared && p.Locations.Length > 0);
     _unusedParameters = new HashSet<IParameterSymbol>(parameters);
     _unusedParameterNames = new HashSet<string>(parameters.Select(p => p.Name));
 }
        private void RenderMethodSymbol(IMethodSymbol methodSymbol)
        {
            var nonInferredTypeArguments = NonInferredTypeArguments(methodSymbol);
            _sb.Append(methodSymbol.Name);

            if (nonInferredTypeArguments.Any())
            {
                _sb.Append("<");
                var last = nonInferredTypeArguments.Last();
                foreach (var arg in nonInferredTypeArguments)
                {
                    RenderSnippetStartMarker();
                    _sb.Append(arg);
                    RenderSnippetEndMarker();

                    if (arg != last)
                    {
                        _sb.Append(", ");
                    }
                }
                _sb.Append(">");
            }

            RenderParameters(methodSymbol);
            if (methodSymbol.ReturnsVoid && IncludeMarkers)
            {
                _sb.Append(";");
            }
        }
 protected static bool IsAcceptableOverload(IMethodSymbol methodSymbol, SemanticModel model)
 {
     var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation);
     return methodSymbol.IsStatic
         ? IsAcceptableStaticOverload(methodSymbol, stringComparisonType)
         : IsAcceptableInstanceOverload(methodSymbol, stringComparisonType);
 }
Example #22
0
 public override IParameterSymbol GetThisParameter(IMethodSymbol method)
 {
     ParameterSymbol thisParameter;
     return ((MethodSymbol)method).TryGetThisParameter(out thisParameter)
         ? thisParameter
         : null;
 }
Example #23
0
        private static ConversionOperatorDeclarationSyntax GenerateConversionDeclarationWorker(
            IMethodSymbol method,
            CodeGenerationDestination destination,
            CodeGenerationOptions options)
        {
            var hasNoBody = !options.GenerateMethodBodies || method.IsExtern;

            var reusableSyntax = GetReuseableSyntaxNodeForSymbol<ConversionOperatorDeclarationSyntax>(method, options);
            if (reusableSyntax != null)
            {
                return reusableSyntax;
            }

            var operatorToken = SyntaxFactory.Token(SyntaxFacts.GetOperatorKind(method.MetadataName));
            var keyword = method.MetadataName == WellKnownMemberNames.ImplicitConversionName
                ? SyntaxFactory.Token(SyntaxKind.ImplicitKeyword)
                : SyntaxFactory.Token(SyntaxKind.ExplicitKeyword);

            return SyntaxFactory.ConversionOperatorDeclaration(
                attributeLists: AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options),
                modifiers: GenerateModifiers(method),
                implicitOrExplicitKeyword: keyword,
                operatorKeyword: SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
                type: method.ReturnType.GenerateTypeSyntax(),
                parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, isExplicit: false, options: options),
                body: hasNoBody ? null : StatementGenerator.GenerateBlock(method),
                semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken());
        }
        private async Task<Solution> RenameThenRemoveAsyncTokenAsync(Document document, SyntaxNode node, IMethodSymbol methodSymbol, CancellationToken cancellationToken)
        {
            var name = methodSymbol.Name;
            var newName = name.Substring(0, name.Length - AsyncSuffix.Length);
            var solution = document.Project.Solution;
            var options = solution.Workspace.Options;

            // Store the path to this node.  That way we can find it post rename.
            var syntaxPath = new SyntaxPath(node);

            // Rename the method to remove the 'Async' suffix, then remove the 'async' keyword.
            var newSolution = await Renamer.RenameSymbolAsync(solution, methodSymbol, newName, options, cancellationToken).ConfigureAwait(false);
            var newDocument = newSolution.GetDocument(document.Id);
            var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode newNode;
            if (syntaxPath.TryResolve<SyntaxNode>(newRoot, out newNode))
            {
                var semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                var newMethod = (IMethodSymbol)semanticModel.GetDeclaredSymbol(newNode, cancellationToken);
                return await RemoveAsyncTokenAsync(newDocument, newMethod, newNode, cancellationToken).ConfigureAwait(false);
            }

            return newSolution;
        }
Example #25
0
        private static OperatorDeclarationSyntax GenerateOperatorDeclarationWorker(
            IMethodSymbol method,
            CodeGenerationDestination destination,
            CodeGenerationOptions options)
        {
            var hasNoBody = !options.GenerateMethodBodies || method.IsExtern;

            var operatorSyntaxKind = SyntaxFacts.GetOperatorKind(method.MetadataName);
            if (operatorSyntaxKind == SyntaxKind.None)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Cannot_generate_code_for_unsupported_operator_0, method.Name), nameof(method));
            }

            var operatorToken = SyntaxFactory.Token(operatorSyntaxKind);

            return SyntaxFactory.OperatorDeclaration(
                attributeLists: AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options),
                modifiers: GenerateModifiers(method),
                returnType: method.ReturnType.GenerateTypeSyntax(),
                operatorKeyword: SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
                operatorToken: operatorToken,
                parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, isExplicit: false, options: options),
                body: hasNoBody ? null : StatementGenerator.GenerateBlock(method),
                semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken());
        }
Example #26
0
        public static ChangeType CompareTo(this IMethodSymbol symbol, IMethodSymbol comparedTo)
        {
            if (symbol == null)
                return ChangeType.Added;

            if (comparedTo == null)
                return ChangeType.Deleted;

            if (symbol.ReturnType != comparedTo.ReturnType)
                return ChangeType.Rewritten;

            if (symbol.DeclaredAccessibility != comparedTo.DeclaredAccessibility)
                return ChangeType.Rewritten;

            if (symbol.Parameters.Count != comparedTo.Parameters.Count)
                return ChangeType.Rewritten;

            for (var index = 0; index < symbol.Parameters.Count; index++)
            {
                if (symbol.Parameters.ElementAt(index).Type == symbol.Parameters.ElementAt(index).Type)
                    return ChangeType.Rewritten;
            }

            return ChangeType.None;
        }
Example #27
0
        /// <summary>
        /// Process a method declaration for documentation.
        /// </summary>
        /// <param name="symbol">The method in question.</param>
        /// <returns><c>Docs</c> if the method contains any, otherwise <c>null</c>.</returns>
        public static Doc ForMethod(IMethodSymbol symbol)
        {
            var doc = symbol.GetDocumentationCommentXml();
              if (string.IsNullOrEmpty(doc))
              {
            return null;
              }

              var sections = new List<Tuple<int, string, string>>();
              var xdoc = XDocument.Parse(doc).Root;

              ProcessFull(xdoc, sections);
              var cursor = sections.FindIndex(t => t.Item2 == "Summary");
              var paramsSection = ProcessParameters(xdoc, symbol.Parameters.Select(p => p.Name).ToList());
              sections.Insert(cursor + 1, paramsSection);

              var returnElement = xdoc.Element("returns");
              if (returnElement != null)
              {
            var content = ProcessContent(returnElement);
            if (!string.IsNullOrEmpty(content))
            {
              sections.Insert(cursor + 2, Tuple.Create(2, "Return value", $"<p>{content}</p>"));
            }
              }

              var resultString = string.Join("\n", sections.Select(t => $"<h{t.Item1 + 2}>{t.Item2}</h{t.Item1 + 2}>{t.Item3}"));

              return new Doc
              {
            Format = "text/html",
            Data = resultString
              };
        }
Example #28
0
        internal static ConstructorDeclarationSyntax GenerateConstructorDeclaration(
            IMethodSymbol constructor, CodeGenerationDestination destination, CodeGenerationOptions options)
        {
            options = options ?? CodeGenerationOptions.Default;

            var reusableSyntax = GetReuseableSyntaxNodeForSymbol<ConstructorDeclarationSyntax>(constructor, options);
            if (reusableSyntax != null)
            {
                return reusableSyntax;
            }

            bool hasNoBody = !options.GenerateMethodBodies;

            var declaration = SyntaxFactory.ConstructorDeclaration(
                attributeLists: AttributeGenerator.GenerateAttributeLists(constructor.GetAttributes(), options),
                modifiers: GenerateModifiers(constructor, options),
                identifier: CodeGenerationConstructorInfo.GetTypeName(constructor).ToIdentifierToken(),
                parameterList: ParameterGenerator.GenerateParameterList(constructor.Parameters, isExplicit: false, options: options),
                initializer: GenerateConstructorInitializer(constructor),
                body: hasNoBody ? null : GenerateBlock(constructor),
                semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : default(SyntaxToken));

            return AddCleanupAnnotationsTo(
                ConditionallyAddDocumentationCommentTo(declaration, constructor, options));
        }
        private SyntaxNode FixMethod(
            bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method,
            ITypeSymbol taskType, INamedTypeSymbol taskOfTType)
        {
            var newReturnType = method.ReturnType;

            if (methodSymbol.ReturnsVoid)
            {
                if (!keepVoid)
                {
                    newReturnType = taskType.GenerateTypeSyntax();
                }
            }
            else
            {
                if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType))
                {
                    // If it's not already Task-like, then wrap the existing return type
                    // in Task<>.
                    newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax();
                }
            }

            var newModifiers = method.Modifiers.Add(s_asyncToken);
            return method.WithReturnType(newReturnType).WithModifiers(newModifiers);
        }
            public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor)
            {
                Debug.Assert(symbol.Equals(symbol.ConstructedFrom));

                visitor.WriteSymbolKey(symbol.ReducedFrom);
                visitor.WriteSymbolKey(symbol.ReceiverType);
            }