void AddImportExtensionMethodCompletionData(CompletionDataList result, CSharpSyntaxContext ctx, INamedTypeSymbol fromType, ITypeSymbol receiverType, Dictionary <INamespaceSymbol, List <ImportSymbolCompletionData> > extMethodDict) { try { foreach (var extMethod in fromType.GetMembers().OfType <IMethodSymbol> ().Where(method => method.IsExtensionMethod)) { var reducedMethod = extMethod.ReduceExtensionMethod(receiverType); if (reducedMethod != null) { if (!extMethodDict.TryGetValue(fromType.ContainingNamespace, out var importSymbolList)) { extMethodDict.Add(fromType.ContainingNamespace, importSymbolList = new List <ImportSymbolCompletionData> ()); } var newData = new ImportSymbolCompletionData(this, ctx, reducedMethod, false); ImportSymbolCompletionData existingItem = null; foreach (var data in importSymbolList) { if (data.Symbol.Name == extMethod.Name) { existingItem = data; break; } } if (existingItem != null) { existingItem.AddOverload(newData); } else { result.Add(newData); importSymbolList.Add(newData); } } } } catch (Exception e) { LoggingService.LogError("Exception while AddImportExtensionMethodCompletionData", e); } }
internal void AddImportCompletionData(CSharpSyntaxContext ctx, CompletionDataList result, SemanticModel semanticModel, int position, CancellationToken cancellationToken = default(CancellationToken)) { if (result.Count == 0) { return; } var root = semanticModel.SyntaxTree.GetRoot(); var node = root.FindNode(TextSpan.FromBounds(position, position)); var syntaxTree = root.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.GetContainingTypeOrEnumDeclaration(position, cancellationToken) is EnumDeclarationSyntax || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { return; } var extensionMethodImport = syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken); ITypeSymbol extensionType = null; if (extensionMethodImport) { var memberAccess = ctx.TargetToken.Parent as MemberAccessExpressionSyntax; if (memberAccess != null) { var symbolInfo = ctx.SemanticModel.GetSymbolInfo(memberAccess.Expression); if (symbolInfo.Symbol.Kind == SymbolKind.NamedType) { return; } extensionType = ctx.SemanticModel.GetTypeInfo(memberAccess.Expression).Type; if (extensionType == null) { return; } } else { return; } } var tokenLeftOfPosition = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); if (extensionMethodImport || syntaxTree.IsGlobalStatementContext(position, cancellationToken) || syntaxTree.IsExpressionContext(position, tokenLeftOfPosition, true, cancellationToken) || syntaxTree.IsStatementContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsTypeContext(position, cancellationToken) || syntaxTree.IsTypeDeclarationContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsMemberDeclarationContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsLabelContext(position, cancellationToken)) { var usedNamespaces = new HashSet <string> (); foreach (var un in semanticModel.GetUsingNamespacesInScope(node)) { usedNamespaces.Add(un.GetFullName()); } var enclosingNamespaceName = semanticModel.GetEnclosingNamespace(position, cancellationToken).GetFullName(); var stack = new Stack <INamespaceOrTypeSymbol> (); foreach (var member in semanticModel.Compilation.GlobalNamespace.GetNamespaceMembers()) { stack.Push(member); } var extMethodDict = extensionMethodImport ? new Dictionary <INamespaceSymbol, List <ImportSymbolCompletionData> > () : null; var typeDict = new Dictionary <INamespaceSymbol, HashSet <string> > (); while (stack.Count > 0) { if (cancellationToken.IsCancellationRequested) { break; } var current = stack.Pop(); var currentNs = current as INamespaceSymbol; if (currentNs != null) { var currentNsName = currentNs.GetFullName(); if (usedNamespaces.Contains(currentNsName) || enclosingNamespaceName == currentNsName || (enclosingNamespaceName.StartsWith(currentNsName, StringComparison.Ordinal) && enclosingNamespaceName [currentNsName.Length] == '.')) { foreach (var member in currentNs.GetNamespaceMembers()) { stack.Push(member); } } else { foreach (var member in currentNs.GetMembers()) { stack.Push(member); } } } else { var type = (INamedTypeSymbol)current; if (type.IsImplicitClass || type.IsScriptClass) { continue; } if (type.DeclaredAccessibility != Accessibility.Public) { if (type.DeclaredAccessibility != Accessibility.Internal) { continue; } if (!type.IsAccessibleWithin(semanticModel.Compilation.Assembly)) { continue; } } if (extensionMethodImport) { if (!type.MightContainExtensionMethods) { continue; } foreach (var extMethod in type.GetMembers().OfType <IMethodSymbol> ().Where(method => method.IsExtensionMethod)) { var reducedMethod = extMethod.ReduceExtensionMethod(extensionType); if (reducedMethod != null) { List <ImportSymbolCompletionData> importSymbolList; if (!extMethodDict.TryGetValue(type.ContainingNamespace, out importSymbolList)) { extMethodDict.Add(type.ContainingNamespace, importSymbolList = new List <ImportSymbolCompletionData> ()); } var newData = new ImportSymbolCompletionData(this, reducedMethod, false); var existingItem = importSymbolList.FirstOrDefault(data => data.Symbol.Name == extMethod.Name); if (existingItem != null) { existingItem.AddOverload(newData); } else { result.Add(newData); importSymbolList.Add(newData); } } } } else { HashSet <string> existingTypeHashSet; if (!typeDict.TryGetValue(type.ContainingNamespace, out existingTypeHashSet)) { typeDict.Add(type.ContainingNamespace, existingTypeHashSet = new HashSet <string> ()); } if (!existingTypeHashSet.Contains(type.Name)) { result.Add(new ImportSymbolCompletionData(this, type, false)); existingTypeHashSet.Add(type.Name); } } } } } }