示例#1
0
        public static IAliasSymbol GetAliasInfo(
            ISemanticFactsService semanticFacts, SemanticModel model, SyntaxToken token, CancellationToken cancellationToken)
        {
            if (semanticFacts == null)
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            var entry = GetCachedEntry(model);
            if (entry == null)
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            if (entry.AliasNameSet == null)
            {
                var set = semanticFacts.GetAliasNameSet(model, cancellationToken);
                Interlocked.CompareExchange(ref entry.AliasNameSet, set, null);
            }

            if (entry.AliasNameSet.Contains(token.ValueText))
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            return null;
        }
        private static void ApplyEdit(
            SyntaxEditor editor, SemanticModel semanticModel, INamedTypeSymbol?expressionTypeOpt,
            ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts,
            Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var root = editor.OriginalRoot;
            var conditionalExpression = root.FindNode(diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true);
            var conditionalPartHigh   = root.FindNode(diagnostic.AdditionalLocations[1].SourceSpan);
            var whenPart = root.FindNode(diagnostic.AdditionalLocations[2].SourceSpan);

            syntaxFacts.GetPartsOfConditionalExpression(
                conditionalExpression, out var condition, out var whenTrue, out var whenFalse);

            var conditionalPartLow = syntaxFacts.WalkDownParentheses(conditionalPartHigh);

            editor.ReplaceNode(conditionalExpression,
                               (c, g) =>
            {
                syntaxFacts.GetPartsOfConditionalExpression(
                    c, out var currentCondition, out var currentWhenTrue, out var currentWhenFalse);

                var coalesceExpression = GetCoalesceExpression(
                    syntaxFacts, g, whenPart, whenTrue, conditionalPartLow,
                    currentWhenTrue, currentWhenFalse)
                                         .WithTrailingTrivia(conditionalExpression.GetTrailingTrivia());

                if (semanticFacts.IsInExpressionTree(
                        semanticModel, conditionalExpression, expressionTypeOpt, cancellationToken))
                {
                    coalesceExpression = coalesceExpression.WithAdditionalAnnotations(
                        WarningAnnotation.Create(AnalyzersResources.Changes_to_expression_trees_may_result_in_behavior_changes_at_runtime));
                }

                return(coalesceExpression.WithAdditionalAnnotations(Formatter.Annotation));
            });
            public ReferenceReplacer(
                AbstractReplacePropertyWithMethodsService <TIdentifierNameSyntax, TExpressionSyntax, TCrefSyntax, TStatementSyntax, TPropertySyntax> service,
                SemanticModel semanticModel,
                ISyntaxFactsService syntaxFacts,
                ISemanticFactsService semanticFacts,
                SyntaxEditor editor,
                TIdentifierNameSyntax identifierName,
                IPropertySymbol property, IFieldSymbol propertyBackingField,
                string desiredGetMethodName,
                string desiredSetMethodName,
                CancellationToken cancellationToken)
            {
                _service              = service;
                _semanticModel        = semanticModel;
                _syntaxFacts          = syntaxFacts;
                _semanticFacts        = semanticFacts;
                _editor               = editor;
                _identifierName       = identifierName;
                _property             = property;
                _propertyBackingField = propertyBackingField;
                _desiredGetMethodName = desiredGetMethodName;
                _desiredSetMethodName = desiredSetMethodName;
                _cancellationToken    = cancellationToken;

                _expression = _identifierName;
                _cref       = _service.TryGetCrefSyntax(_identifierName);
                if (_syntaxFacts.IsNameOfMemberAccessExpression(_expression))
                {
                    _expression = _expression.Parent as TExpressionSyntax;
                }
            }
示例#4
0
        public static IAliasSymbol GetAliasInfo(
            ISemanticFactsService semanticFacts, SemanticModel model, SyntaxToken token, CancellationToken cancellationToken)
        {
            if (semanticFacts == null)
            {
                return(model.GetAliasInfo(token.Parent, cancellationToken));
            }

            var entry = GetCachedEntry(model);

            if (entry == null)
            {
                return(model.GetAliasInfo(token.Parent, cancellationToken));
            }

            if (entry.AliasNameSet == null)
            {
                var set = semanticFacts.GetAliasNameSet(model, cancellationToken);
                Interlocked.CompareExchange(ref entry.AliasNameSet, set, null);
            }

            if (entry.AliasNameSet.Contains(token.ValueText))
            {
                return(model.GetAliasInfo(token.Parent, cancellationToken));
            }

            return(null);
        }
示例#5
0
        internal static TokenRenameInfo GetTokenRenameInfo(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var symbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);

            if (symbol != null)
            {
                return(TokenRenameInfo.CreateSingleSymbolTokenInfo(symbol));
            }

            var symbolInfo = semanticModel.GetSymbolInfo(token, cancellationToken);

            if (symbolInfo.Symbol != null)
            {
                return(TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.Symbol));
            }

            if (symbolInfo.CandidateReason == CandidateReason.MemberGroup && symbolInfo.CandidateSymbols.Any())
            {
                // This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
                return(TokenRenameInfo.CreateMemberGroupTokenInfo(symbolInfo.CandidateSymbols));
            }

            return(TokenRenameInfo.NoSymbolsTokenInfo);
        }
 protected AbstractInlineMethodRefactoringProvider(
     ISyntaxFacts syntaxFacts,
     ISemanticFactsService semanticFactsService)
 {
     _syntaxFacts          = syntaxFacts;
     _semanticFactsService = semanticFactsService;
 }
示例#7
0
            public ForEachInfo(
                ISemanticFactsService semanticFacts,
                string collectionNameSuggestion,
                string countName,
                ITypeSymbol explicitCastInterface,
                ITypeSymbol forEachElementType,
                bool requireCollectionStatement,
                TForEachStatement forEachStatement
                )
            {
                SemanticFacts = semanticFacts;

                RequireExplicitCastInterface = explicitCastInterface != null;

                CollectionNameSuggestion = collectionNameSuggestion;
                CountName = countName;

                ExplicitCastInterface = explicitCastInterface;
                ForEachElementType    = forEachElementType;

                RequireCollectionStatement =
                    requireCollectionStatement || (explicitCastInterface != null);

                ForEachStatement = forEachStatement;
            }
示例#8
0
 public EmbeddedLanguageInfo(int stringLiteralTokenKind, int interpolatedTextTokenKind, ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, IVirtualCharService virtualCharService)
 {
     StringLiteralTokenKind    = stringLiteralTokenKind;
     InterpolatedTextTokenKind = interpolatedTextTokenKind;
     SyntaxFacts        = syntaxFacts;
     SemanticFacts      = semanticFacts;
     VirtualCharService = virtualCharService;
 }
示例#9
0
        protected static ImmutableArray <IMethodSymbol> GetReferencedAccessorSymbols(
            ISyntaxFactsService syntaxFacts,
            ISemanticFactsService semanticFacts,
            SemanticModel model,
            IPropertySymbol property,
            SyntaxNode node,
            CancellationToken cancellationToken
            )
        {
            if (syntaxFacts.IsForEachStatement(node))
            {
                var symbols = semanticFacts.GetForEachSymbols(model, node);

                // the only accessor method referenced in a foreach-statement is the .Current's
                // get-accessor
                return(symbols.CurrentProperty.GetMethod == null
                  ? ImmutableArray <IMethodSymbol> .Empty
                  : ImmutableArray.Create(symbols.CurrentProperty.GetMethod));
            }

            if (semanticFacts.IsWrittenTo(model, node, cancellationToken))
            {
                // if it was only written to, then only the setter was referenced.
                // if it was written *and* read, then both accessors were referenced.
                using var _ = ArrayBuilder <IMethodSymbol> .GetInstance(out var result);

                result.AddIfNotNull(property.SetMethod);

                if (!semanticFacts.IsOnlyWrittenTo(model, node, cancellationToken))
                {
                    result.AddIfNotNull(property.GetMethod);
                }

                return(result.ToImmutable());
            }
            else
            {
                // Wasn't written. This could be a normal read, or it could be neither a read nor
                // write. Example of this include:
                //
                // 1) referencing through something like nameof().
                // 2) referencing in a cref in a doc-comment.
                //
                // This list is thought to be complete.  However, if new examples are found, they
                // can be added here.
                var inNameOf = semanticFacts.IsInsideNameOfExpression(
                    model,
                    node,
                    cancellationToken
                    );
                var inStructuredTrivia = node.IsPartOfStructuredTrivia();

                return(inNameOf || inStructuredTrivia || property.GetMethod == null
                  ? ImmutableArray <IMethodSymbol> .Empty
                  : ImmutableArray.Create(property.GetMethod));
            }
        }
示例#10
0
        private static bool IsCompatible <TExpressionSyntax>(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            IMethodSymbol constructor,
            ImmutableArray <TExpressionSyntax?> expressions)
            where TExpressionSyntax : SyntaxNode
        {
            Debug.Assert(constructor.Parameters.Length == expressions.Length);

            // Resolve the constructor into our semantic model's compilation; if the constructor we're looking at is from
            // another project with a different language.
            var constructorInCompilation = (IMethodSymbol?)SymbolKey.Create(constructor).Resolve(semanticModel.Compilation).Symbol;

            if (constructorInCompilation == null)
            {
                // If the constructor can't be mapped into our invocation project, we'll just bail.
                // Note the logic in this method doesn't handle a complicated case where:
                //
                // 1. Project A has some public type.
                // 2. Project B references A, and has one constructor that uses the public type from A.
                // 3. Project C, which references B but not A, has an invocation of B's constructor passing some
                //    parameters.
                //
                // The algorithm of this class tries to map the constructor in B (that we might delegate to) into
                // C, but that constructor might not be mappable if the public type from A is not available.
                // However, theoretically the public type from A could have a user-defined conversion.
                // The alternative approach might be to map the type of the parameters back into B, and then
                // classify the conversions in Project B, but that'll run into other issues if the experssions
                // don't have a natural type (like default). We choose to ignore all complicated cases here.
                return(false);
            }

            for (var i = 0; i < constructorInCompilation.Parameters.Length; i++)
            {
                var constructorParameter = constructorInCompilation.Parameters[i];
                if (constructorParameter == null)
                {
                    return(false);
                }

                // In VB the argument may not have been specified at all if the parameter is optional
                if (expressions[i] is null && constructorParameter.IsOptional)
                {
                    continue;
                }

                var conversion = semanticFacts.ClassifyConversion(semanticModel, expressions[i], constructorParameter.Type);
                if (!conversion.IsIdentity && !conversion.IsImplicit)
                {
                    return(false);
                }
            }

            return(true);
        }
示例#11
0
 protected AbstractEmbeddedLanguagesProvider(
     int stringLiteralTokenKind,
     int interpolatedTextTokenKind,
     ISyntaxFactsService syntaxFacts,
     ISemanticFactsService semanticFacts,
     IVirtualCharService virtualCharService)
 {
     _embeddedLanguages = ImmutableArray.Create <IEmbeddedLanguage>(
         new RegexEmbeddedLanguage(stringLiteralTokenKind, syntaxFacts, semanticFacts, virtualCharService),
         new FallbackEmbeddedLanguage(stringLiteralTokenKind, interpolatedTextTokenKind, syntaxFacts, semanticFacts, virtualCharService));
 }
示例#12
0
            public UniqueVariableNameGenerator(
                SyntaxNode memberDeclaration,
                SemanticModel semanticModel,
                ISemanticFactsService semanticFacts,
                CancellationToken cancellationToken)
            {
                _memberDeclaration = memberDeclaration;
                _semanticModel     = semanticModel;
                _semanticFacts     = semanticFacts;
                _cancellationToken = cancellationToken;

                _usedNames = PooledHashSet <string> .GetInstance();
            }
示例#13
0
 protected static SyntaxToken CreateUniqueName(
     ISemanticFactsService semanticFacts,
     SemanticModel model,
     SyntaxNode location,
     string baseName,
     CancellationToken cancellationToken
     ) =>
 semanticFacts.GenerateUniqueLocalName(
     model,
     location,
     containerOpt: null,
     baseName,
     cancellationToken
     );
示例#14
0
        public FallbackEmbeddedLanguage(
            int stringLiteralTokenKind,
            int interpolatedTextTokenKind,
            ISyntaxFactsService syntaxFacts,
            ISemanticFactsService semanticFacts,
            IVirtualCharService virtualCharService)
        {
            _stringLiteralTokenKind    = stringLiteralTokenKind;
            _interpolatedTextTokenKind = interpolatedTextTokenKind;
            _syntaxFacts        = syntaxFacts;
            _semanticFacts      = semanticFacts;
            _virtualCharService = virtualCharService;

            Classifier = new FallbackEmbeddedClassifier(this);
        }
        public EmbeddedLanguageInfo(
            ISyntaxFacts syntaxFacts,
            ISemanticFactsService semanticFacts,
            IVirtualCharService virtualCharService)
        {
            SyntaxFacts        = syntaxFacts;
            SemanticFacts      = semanticFacts;
            VirtualCharService = virtualCharService;

            using var array = TemporaryArray <int> .Empty;
            array.Add(syntaxFacts.SyntaxKinds.StringLiteralToken);
            array.AsRef().AddIfNotNull(syntaxFacts.SyntaxKinds.SingleLineRawStringLiteralToken);
            array.AsRef().AddIfNotNull(syntaxFacts.SyntaxKinds.MultiLineRawStringLiteralToken);
            AllStringLiteralKinds = array.ToImmutableAndClear();
        }
示例#16
0
        internal static TokenRenameInfo GetTokenRenameInfo(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            SyntaxToken token,
            CancellationToken cancellationToken
            )
        {
            var symbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);

            if (symbol != null)
            {
                return(TokenRenameInfo.CreateSingleSymbolTokenInfo(symbol));
            }

            var symbolInfo = semanticModel.GetSymbolInfo(token, cancellationToken);

            if (symbolInfo.Symbol != null)
            {
                if (symbolInfo.Symbol.IsTupleType())
                {
                    return(TokenRenameInfo.NoSymbolsTokenInfo);
                }

                return(TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.Symbol));
            }

            if (
                symbolInfo.CandidateReason == CandidateReason.MemberGroup &&
                symbolInfo.CandidateSymbols.Any()
                )
            {
                // This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
                return(TokenRenameInfo.CreateMemberGroupTokenInfo(symbolInfo.CandidateSymbols));
            }

            if (
                RenameLocation.ShouldRename(symbolInfo.CandidateReason) &&
                symbolInfo.CandidateSymbols.Length == 1
                )
            {
                // TODO(cyrusn): We're allowing rename here, but we likely should let the user
                // know that there is an error in the code and that rename results might be
                // inaccurate.
                return(TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.CandidateSymbols[0]));
            }

            return(TokenRenameInfo.NoSymbolsTokenInfo);
        }
示例#17
0
        public RegexEmbeddedLanguage(
            int stringLiteralKind,
            ISyntaxFactsService syntaxFacts,
            ISemanticFactsService semanticFacts,
            IVirtualCharService virtualCharService)
        {
            StringLiteralKind  = stringLiteralKind;
            SyntaxFacts        = syntaxFacts;
            SemanticFacts      = semanticFacts;
            VirtualCharService = virtualCharService;

            BraceMatcher       = new RegexEmbeddedBraceMatcher(this);
            Classifier         = new RegexEmbeddedClassifier(this);
            Highlighter        = new RegexEmbeddedHighlighter(this);
            DiagnosticAnalyzer = new RegexDiagnosticAnalyzer(this);
        }
示例#18
0
        private ForEachInfo GetForeachInfo(
            ISemanticFactsService semanticFact, OptionSet options, SemanticModel model,
            TForEachStatement foreachStatement, CancellationToken cancellationToken)
        {
            var operation = model.GetOperation(foreachStatement, cancellationToken) as IForEachLoopOperation;

            if (operation == null || operation.Locals.Length != 1)
            {
                return(null);
            }

            var foreachVariable = operation.Locals[0];

            if (foreachVariable == null)
            {
                return(null);
            }

            // Perform language specific checks if the foreachStatement
            // is using unsupported features
            if (!IsSupported(foreachVariable, operation, foreachStatement))
            {
                return(null);
            }

            IsForEachVariableWrittenInside = CheckIfForEachVariableIsWrittenInside(model, foreachVariable, foreachStatement);

            var foreachCollection = RemoveImplicitConversion(operation.Collection);

            if (foreachCollection == null)
            {
                return(null);
            }

            GetInterfaceInfo(semanticFact, model, foreachVariable, foreachCollection,
                             out var explicitCastInterface, out var collectionNameSuggestion, out var countName);
            if (countName == null)
            {
                return(null);
            }

            var requireCollectionStatement = CheckRequireCollectionStatement(foreachCollection);

            return(new ForEachInfo(
                       semanticFact, collectionNameSuggestion, countName, explicitCastInterface,
                       foreachVariable.Type, requireCollectionStatement, foreachStatement));
        }
            /// <summary>
            /// If the symbol could not be bound, we could be dealing with a partial invocation, we'll try to find a possible overload.
            /// </summary>
            private static (IMethodSymbol?symbol, int parameterIndex) GuessCurrentSymbolAndParameter(
                SeparatedSyntaxList <ArgumentSyntax> arguments, ImmutableArray <IMethodSymbol> methodGroup, int position,
                SemanticModel semanticModel, ISemanticFactsService semanticFactsService)
            {
                if (arguments.Count != 0)
                {
                    foreach (var method in methodGroup)
                    {
                        if (FindParameterIndexIfCompatibleMethod(arguments, method, position, semanticModel, semanticFactsService, out var parameterIndex))
                        {
                            return(method, parameterIndex);
                        }
                    }
                }

                // Note: Providing no recommendation if no arguments allows the model to keep the last implicit choice
                return(null, -1);
            }
示例#20
0
        private static SyntaxNode GetNewMethodDeclaration(
            IMethodSymbol method,
            TArgumentSyntax argument,
            SeparatedSyntaxList <TArgumentSyntax> argumentList,
            SyntaxGenerator generator,
            SyntaxNode declaration,
            ISemanticFactsService semanticFacts,
            string argumentName,
            SyntaxNode expression,
            SemanticModel semanticModel,
            ITypeSymbol parameterType,
            CancellationToken cancellationToken)
        {
            if (!string.IsNullOrWhiteSpace(argumentName))
            {
                var newParameterSymbol = CodeGenerationSymbolFactory.CreateParameterSymbol(
                    attributes: default(ImmutableArray <AttributeData>),
                    refKind: RefKind.None,
                    isParams: false,
                    type: parameterType,
                    name: argumentName);

                var newParameterDeclaration = generator.ParameterDeclaration(newParameterSymbol);
                return(generator.AddParameters(declaration, new[] { newParameterDeclaration }));
            }
            else
            {
                var name = semanticFacts.GenerateNameForExpression(
                    semanticModel, expression, capitalize: false, cancellationToken: cancellationToken);
                var uniqueName = NameGenerator.EnsureUniqueness(name, method.Parameters.Select(p => p.Name));

                var newParameterSymbol = CodeGenerationSymbolFactory.CreateParameterSymbol(
                    attributes: default(ImmutableArray <AttributeData>),
                    refKind: RefKind.None,
                    isParams: false,
                    type: parameterType,
                    name: uniqueName);

                var argumentIndex           = argumentList.IndexOf(argument);
                var newParameterDeclaration = generator.ParameterDeclaration(newParameterSymbol);
                return(generator.InsertParameters(
                           declaration, argumentIndex, new[] { newParameterDeclaration }));
            }
        }
示例#21
0
        private static TokenSemanticInfo GetSemanticInfo(
            SemanticModel semanticModel,
            ISemanticFactsService semanticFacts,
            ISyntaxFactsService syntaxFacts,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var aliasSymbol = semanticModel.GetAliasInfo(token.Parent, cancellationToken);

            var bindableParent = syntaxFacts.GetBindableParent(token);
            var type           = semanticModel.GetTypeInfo(bindableParent, cancellationToken).Type;

            var declaredSymbol = MapSymbol(semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken), type);
            var allSymbols     = semanticModel.GetSymbolInfo(bindableParent, cancellationToken)
                                 .GetBestOrAllSymbols()
                                 .WhereAsArray(s => !s.Equals(declaredSymbol))
                                 .SelectAsArray(s => MapSymbol(s, type));

            // NOTE(cyrusn): This is a workaround to how the semantic model binds and returns
            // information for VB event handlers.  Namely, if you have:
            //
            // Event X]()
            // Sub Foo()
            //      Dim y = New $$XEventHandler(AddressOf bar)
            // End Sub
            //
            // Only GetTypeInfo will return any information for XEventHandler.  So, in this
            // case, we upgrade the type to be the symbol we return.
            if (type != null && allSymbols.Length == 0)
            {
                if (type.Kind == SymbolKind.NamedType)
                {
                    var namedType = (INamedTypeSymbol)type;
                    if (namedType.TypeKind == TypeKind.Delegate ||
                        namedType.AssociatedSymbol != null)
                    {
                        allSymbols = ImmutableArray.Create <ISymbol>(type);
                        type       = null;
                    }
                }
            }

            return(new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type));
        }
 public IntroduceParameterDocumentRewriter(AbstractIntroduceParameterService <TExpressionSyntax, TInvocationExpressionSyntax, TObjectCreationExpressionSyntax, TIdentifierNameSyntax> service,
                                           Document originalDocument,
                                           TExpressionSyntax expression,
                                           IMethodSymbol methodSymbol,
                                           SyntaxNode containingMethod,
                                           IntroduceParameterCodeActionKind selectedCodeAction,
                                           bool allOccurrences)
 {
     _service          = service;
     _originalDocument = originalDocument;
     _generator        = SyntaxGenerator.GetGenerator(originalDocument);
     _syntaxFacts      = originalDocument.GetRequiredLanguageService <ISyntaxFactsService>();
     _semanticFacts    = originalDocument.GetRequiredLanguageService <ISemanticFactsService>();
     _expression       = expression;
     _methodSymbol     = methodSymbol;
     _containerMethod  = containingMethod;
     _actionKind       = selectedCodeAction;
     _allOccurrences   = allOccurrences;
 }
示例#23
0
        private static bool IsCompatible <TExpressionSyntax>(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            IMethodSymbol constructor,
            ImmutableArray <TExpressionSyntax> expressions)
            where TExpressionSyntax : SyntaxNode
        {
            Debug.Assert(constructor.Parameters.Length == expressions.Length);

            for (var i = 0; i < constructor.Parameters.Length; i++)
            {
                var constructorParameter = constructor.Parameters[i];
                var conversion           = semanticFacts.ClassifyConversion(semanticModel, expressions[i], constructorParameter.Type);
                if (!conversion.IsIdentity && !conversion.IsImplicit)
                {
                    return(false);
                }
            }

            return(true);
        }
        private static TokenSemanticInfo GetSemanticInfo(
            SemanticModelBase semanticModel,
            ISemanticFactsService semanticFacts,
            ISyntaxFactsService syntaxFacts,
            ISyntaxToken token,
            CancellationToken cancellationToken)
        {
            //var aliasSymbol = semanticModel.GetAliasInfo(token.Parent, cancellationToken);
            IAliasSymbol aliasSymbol = null;

            var bindableParent = syntaxFacts.GetBindableParent(token);
            var type           = semanticModel.GetTypeInfo(bindableParent).Type;

            var declaredSymbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);
            var allSymbols     = semanticModel.GetSymbolInfo(bindableParent)
                                 .GetBestOrAllSymbols()
                                 .WhereAsArray(s => !s.Equals(declaredSymbol))
                                 .SelectAsArray(s => s);

            return(new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type));
        }
示例#25
0
 private static bool IsExchangable(
     ISemanticFactsService semanticFact, ITypeSymbol type1, ITypeSymbol type2, Compilation compilation)
 {
     return(semanticFact.IsAssignableTo(type1, type2, compilation) ||
            semanticFact.IsAssignableTo(type2, type1, compilation));
 }
            public RenameRewriter(RenameRewriterParameters parameters)
                : base(visitIntoStructuredTrivia: true)
            {
                _documentId = parameters.Document.Id;
                _renameRenamableSymbolDeclaration = parameters.RenamedSymbolDeclarationAnnotation;
                _solution = parameters.OriginalSolution;
                _replacementText = parameters.ReplacementText;
                _originalText = parameters.OriginalText;
                _possibleNameConflicts = parameters.PossibleNameConflicts;
                _renameLocations = parameters.RenameLocations;
                _conflictLocations = parameters.ConflictLocationSpans;
                _cancellationToken = parameters.CancellationToken;
                _semanticModel = parameters.SemanticModel;
                _renamedSymbol = parameters.RenameSymbol;
                _replacementTextValid = parameters.ReplacementTextValid;
                _renameSpansTracker = parameters.RenameSpansTracker;
                _isRenamingInStrings = parameters.OptionSet.GetOption(RenameOptions.RenameInStrings);
                _isRenamingInComments = parameters.OptionSet.GetOption(RenameOptions.RenameInComments);
                _stringAndCommentTextSpans = parameters.StringAndCommentTextSpans;
                _renameAnnotations = parameters.RenameAnnotations;

                _aliasSymbol = _renamedSymbol as IAliasSymbol;
                _renamableDeclarationLocation = _renamedSymbol.Locations.FirstOrDefault(loc => loc.IsInSource && loc.SourceTree == _semanticModel.SyntaxTree);
                _isVerbatim = _replacementText.StartsWith("@", StringComparison.Ordinal);

                _simplificationService = parameters.Document.Project.LanguageServices.GetService<ISimplificationService>();
                _semanticFactsService = parameters.Document.Project.LanguageServices.GetService<ISemanticFactsService>();
            }
示例#27
0
 private static bool IsExchangable(
     ISemanticFactsService semanticFact, ITypeSymbol type1, ITypeSymbol type2, Compilation compilation)
 {
     return(compilation.HasImplicitConversion(type1, type2) ||
            compilation.HasImplicitConversion(type2, type1));
 }
示例#28
0
        private static void GetInterfaceInfo(
            ISemanticFactsService semanticFact, SemanticModel model, ILocalSymbol foreachVariable, IOperation foreachCollection,
            out ITypeSymbol explicitCastInterface, out string collectionNameSuggestion, out string countName)
        {
            explicitCastInterface    = default;
            collectionNameSuggestion = default;
            countName = default;

            // go through list of types and interfaces to find out right set;
            var foreachType = foreachVariable.Type;

            if (IsNullOrErrorType(foreachType))
            {
                return;
            }

            var collectionType = foreachCollection.Type;

            if (IsNullOrErrorType(collectionType))
            {
                return;
            }

            // go through explicit types first.

            // check array case
            if (collectionType is IArrayTypeSymbol array)
            {
                if (array.Rank != 1)
                {
                    // array type supports IList and other interfaces, but implementation
                    // only supports Rank == 1 case. other case, it will throw on runtime
                    // even if there is no error on compile time.
                    // we explicitly mark that we only support Rank == 1 case
                    return;
                }

                if (!IsExchangable(semanticFact, array.ElementType, foreachType, model.Compilation))
                {
                    return;
                }

                collectionNameSuggestion = "array";
                explicitCastInterface    = null;
                countName = Length;
                return;
            }

            // check string case
            if (collectionType.SpecialType == SpecialType.System_String)
            {
                var charType = model.Compilation.GetSpecialType(SpecialType.System_Char);
                if (!IsExchangable(semanticFact, charType, foreachType, model.Compilation))
                {
                    return;
                }

                collectionNameSuggestion = "str";
                explicitCastInterface    = null;
                countName = Length;
                return;
            }

            // check ImmutableArray case
            if (collectionType.OriginalDefinition.Equals(model.Compilation.GetTypeByMetadataName(typeof(ImmutableArray <>).FullName)))
            {
                var indexer = GetInterfaceMember(collectionType, get_Item);
                if (indexer != null)
                {
                    if (!IsExchangable(semanticFact, indexer.ReturnType, foreachType, model.Compilation))
                    {
                        return;
                    }

                    collectionNameSuggestion = "array";
                    explicitCastInterface    = null;
                    countName = Length;
                    return;
                }
            }

            // go through all known interfaces we support next.
            var knownCollectionInterfaces = s_KnownInterfaceNames.Select(
                s => model.Compilation.GetTypeByMetadataName(s)).Where(t => !IsNullOrErrorType(t));

            // for all interfaces, we suggest collection name as "list"
            collectionNameSuggestion = "list";

            // check type itself is interface case
            if (collectionType.TypeKind == TypeKind.Interface && knownCollectionInterfaces.Contains(collectionType.OriginalDefinition))
            {
                var indexer = GetInterfaceMember(collectionType, get_Item);
                if (indexer != null &&
                    IsExchangable(semanticFact, indexer.ReturnType, foreachType, model.Compilation))
                {
                    explicitCastInterface = null;
                    countName             = Count;
                    return;
                }
            }

            // check regular cases (implicitly implemented)
            ITypeSymbol explicitInterface = null;

            foreach (var current in collectionType.AllInterfaces)
            {
                if (!knownCollectionInterfaces.Contains(current.OriginalDefinition))
                {
                    continue;
                }

                // see how the type implements the interface
                var countSymbol   = GetInterfaceMember(current, get_Count);
                var indexerSymbol = GetInterfaceMember(current, get_Item);
                if (countSymbol == null || indexerSymbol == null)
                {
                    continue;
                }

                var countImpl   = collectionType.FindImplementationForInterfaceMember(countSymbol) as IMethodSymbol;
                var indexerImpl = collectionType.FindImplementationForInterfaceMember(indexerSymbol) as IMethodSymbol;
                if (countImpl == null || indexerImpl == null)
                {
                    continue;
                }

                if (!IsExchangable(semanticFact, indexerImpl.ReturnType, foreachType, model.Compilation))
                {
                    continue;
                }

                // implicitly implemented!
                if (countImpl.ExplicitInterfaceImplementations.IsEmpty &&
                    indexerImpl.ExplicitInterfaceImplementations.IsEmpty)
                {
                    explicitCastInterface = null;
                    countName             = Count;
                    return;
                }

                if (explicitInterface == null)
                {
                    explicitInterface = current;
                }
            }

            // okay, we don't have implicitly implemented one, but we do have explicitly implemented one
            if (explicitInterface != null)
            {
                explicitCastInterface = explicitInterface;
                countName             = Count;
            }
        }
示例#29
0
        internal static TokenRenameInfo GetTokenRenameInfo(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var symbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);
            if (symbol != null)
            {
                return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbol);
            }

            var symbolInfo = semanticModel.GetSymbolInfo(token, cancellationToken);
            if (symbolInfo.Symbol != null)
            {
                if (symbolInfo.Symbol.IsTupleType())
                {
                    return TokenRenameInfo.NoSymbolsTokenInfo;
                }

                return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.Symbol);
            }

            if (symbolInfo.CandidateReason == CandidateReason.MemberGroup && symbolInfo.CandidateSymbols.Any())
            {
                // This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
                return TokenRenameInfo.CreateMemberGroupTokenInfo(symbolInfo.CandidateSymbols);
            }

            if (RenameLocation.ShouldRename(symbolInfo.CandidateReason) &&
                symbolInfo.CandidateSymbols.Length == 1)
            {
                // TODO(cyrusn): We're allowing rename here, but we likely should let the user
                // know that there is an error in the code and that rename results might be
                // inaccurate.
                return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.CandidateSymbols[0]);
            }

            return TokenRenameInfo.NoSymbolsTokenInfo;
        }
 protected abstract bool TryConvert(
     TQueryExpression queryExpression,
     SemanticModel semanticModel,
     ISemanticFactsService semanticFacts,
     CancellationToken cancellationToken,
     out DocumentUpdateInfo documentUpdate);
        private ForEachInfo GetForeachInfo(
            ISemanticFactsService semanticFact, OptionSet options, SemanticModel model,
            TForEachStatement foreachStatement, CancellationToken cancellationToken)
        {
            var operation = model.GetOperation(foreachStatement, cancellationToken) as IForEachLoopOperation;

            if (operation == null || operation.Locals.Length != 1)
            {
                return(null);
            }

            var foreachVariable = operation.Locals[0];

            if (foreachVariable == null)
            {
                return(null);
            }

            // VB can have Next variable. but we only support
            // simple 1 variable case.
            if (operation.NextVariables.Length > 1)
            {
                return(null);
            }

            // it is okay to omit variable in Next, but if it presents, it must be same as one in the loop
            if (!operation.NextVariables.IsEmpty)
            {
                var nextVariable = operation.NextVariables[0] as ILocalReferenceOperation;
                if (nextVariable == null || nextVariable.Local?.Equals(foreachVariable) == false)
                {
                    // we do not support anything else than local reference for next variable
                    // operation
                    return(null);
                }
            }

            if (CheckIfForEachVariableIsWrittenInside(model, foreachVariable, foreachStatement))
            {
                return(null);
            }

            var foreachCollection = RemoveImplicitConversion(operation.Collection);

            if (foreachCollection == null)
            {
                return(null);
            }

            GetInterfaceInfo(semanticFact, model, foreachVariable, foreachCollection,
                             out var explicitCastInterface, out var collectionNameSuggestion, out var countName);
            if (countName == null)
            {
                return(null);
            }

            var requireCollectionStatement = CheckRequireCollectionStatement(foreachCollection);

            return(new ForEachInfo(
                       semanticFact, collectionNameSuggestion, countName, explicitCastInterface,
                       foreachVariable.Type, requireCollectionStatement, foreachStatement));
        }
示例#32
0
        private static IEnumerable <ISymbol> GetSymbolsEnumerable(
            SemanticModel semanticModel,
            ISemanticFactsService semanticFacts,
            ISyntaxFactsService syntaxFacts,
            SyntaxToken token,
            bool bindLiteralsToUnderlyingType,
            CancellationToken cancellationToken)
        {
            var declaredSymbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);

            if (declaredSymbol != null)
            {
                yield return(declaredSymbol);

                yield break;
            }

            var aliasInfo = semanticModel.GetAliasInfo(token.Parent, cancellationToken);

            if (aliasInfo != null)
            {
                yield return(aliasInfo);
            }

            var bindableParent = syntaxFacts.GetBindableParent(token);
            var allSymbols     = semanticModel.GetSymbolInfo(bindableParent, cancellationToken).GetBestOrAllSymbols().ToList();
            var type           = semanticModel.GetTypeInfo(bindableParent, cancellationToken).Type;

            if (type != null && allSymbols.Count == 0)
            {
                if ((bindLiteralsToUnderlyingType && syntaxFacts.IsLiteral(token)) ||
                    syntaxFacts.IsAwaitKeyword(token))
                {
                    yield return(type);
                }

                if (type.Kind == SymbolKind.NamedType)
                {
                    var namedType = (INamedTypeSymbol)type;
                    if (namedType.TypeKind == TypeKind.Delegate ||
                        namedType.AssociatedSymbol != null)
                    {
                        yield return(type);
                    }
                }
            }

            foreach (var symbol in allSymbols)
            {
                if (symbol.IsThisParameter() && type != null)
                {
                    yield return(type);
                }
                else if (symbol.IsFunctionValue())
                {
                    var method = symbol.ContainingSymbol as IMethodSymbol;

                    if (method != null)
                    {
                        if (method.AssociatedSymbol != null)
                        {
                            yield return(method.AssociatedSymbol);
                        }
                        else
                        {
                            yield return(method);
                        }
                    }
                    else
                    {
                        yield return(symbol);
                    }
                }
                else
                {
                    yield return(symbol);
                }
            }
        }
            /// <summary>
            /// Simulates overload resolution with the arguments provided so far and determines if you might be calling this overload.
            /// Returns true if an overload is acceptable. In that case, we output the parameter that should be highlighted given the cursor's
            /// position in the partial invocation.
            /// </summary>
            internal static bool FindParameterIndexIfCompatibleMethod(SeparatedSyntaxList <ArgumentSyntax> arguments, IMethodSymbol method, int position,
                                                                      SemanticModel semanticModel, ISemanticFactsService semanticFactsService, out int foundParameterIndex)
            {
                // map the arguments to their corresponding parameters
                var argumentCount = arguments.Count;

                using var _ = ArrayBuilder <int> .GetInstance(argumentCount, fillWithValue : -1, out var argToParamMap);

                if (!TryPrepareArgToParamMap(arguments, method, argToParamMap))
                {
                    foundParameterIndex = -1;
                    return(false);
                }

                // verify that the arguments are compatible with their corresponding parameters
                var parameters = method.Parameters;

                for (var argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++)
                {
                    var parameterIndex = argToParamMap[argumentIndex];
                    if (parameterIndex < 0)
                    {
                        continue;
                    }

                    var parameter = parameters[parameterIndex];
                    var argument  = arguments[argumentIndex];

                    if (!IsCompatibleArgument(argument, parameter))
                    {
                        foundParameterIndex = -1;
                        return(false);
                    }
                }

                // find the parameter at the cursor position
                var argumentIndexToSave = TryGetArgumentIndex(arguments, position);

                if (argumentIndexToSave >= 0)
                {
                    var foundParam = argToParamMap[argumentIndexToSave];
                    if (foundParam >= 0)
                    {
                        foundParameterIndex = foundParam;
                    }
                    else
                    {
                        foundParameterIndex = FirstUnspecifiedParameter(argToParamMap, argumentCount);
                    }
                }
                else
                {
                    foundParameterIndex = -1;
                }

                Debug.Assert(foundParameterIndex < parameters.Length);

                return(true);
示例#34
0
        internal static TokenRenameInfo GetTokenRenameInfo(
            ISemanticFactsService semanticFacts,
            SemanticModel semanticModel,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var symbol = semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken);
            if (symbol != null)
            {
                return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbol);
            }

            var symbolInfo = semanticModel.GetSymbolInfo(token, cancellationToken);
            if (symbolInfo.Symbol != null)
            {
                return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.Symbol);
            }

            if (symbolInfo.CandidateReason == CandidateReason.MemberGroup && symbolInfo.CandidateSymbols.Any())
            {
                // This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
                return TokenRenameInfo.CreateMemberGroupTokenInfo(symbolInfo.CandidateSymbols);
            }

            return TokenRenameInfo.NoSymbolsTokenInfo;
        }