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; } }
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); }
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; }
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; }
public EmbeddedLanguageInfo(int stringLiteralTokenKind, int interpolatedTextTokenKind, ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, IVirtualCharService virtualCharService) { StringLiteralTokenKind = stringLiteralTokenKind; InterpolatedTextTokenKind = interpolatedTextTokenKind; SyntaxFacts = syntaxFacts; SemanticFacts = semanticFacts; VirtualCharService = virtualCharService; }
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)); } }
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); }
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)); }
public UniqueVariableNameGenerator( SyntaxNode memberDeclaration, SemanticModel semanticModel, ISemanticFactsService semanticFacts, CancellationToken cancellationToken) { _memberDeclaration = memberDeclaration; _semanticModel = semanticModel; _semanticFacts = semanticFacts; _cancellationToken = cancellationToken; _usedNames = PooledHashSet <string> .GetInstance(); }
protected static SyntaxToken CreateUniqueName( ISemanticFactsService semanticFacts, SemanticModel model, SyntaxNode location, string baseName, CancellationToken cancellationToken ) => semanticFacts.GenerateUniqueLocalName( model, location, containerOpt: null, baseName, cancellationToken );
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(); }
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); }
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); }
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); }
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 })); } }
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; }
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)); }
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>(); }
private static bool IsExchangable( ISemanticFactsService semanticFact, ITypeSymbol type1, ITypeSymbol type2, Compilation compilation) { return(compilation.HasImplicitConversion(type1, type2) || compilation.HasImplicitConversion(type2, type1)); }
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; } }
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)); }
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);
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; }