private static bool FindMatchingBrace(SourceLocation position, int direction, SyntaxNode parent, SyntaxKind syntaxKind, out TextSpan right) { var tokens = parent.ChildNodes.Where(t => t.Kind == syntaxKind); var relevantTokens = (direction < 0) ? from t in tokens where t.SourceRange.End <= position select t : from t in tokens where position < t.SourceRange.Start select t; right = new TextSpan(); var found = false; foreach (var token in relevantTokens.Cast<SyntaxToken>()) { if (!found) { right = token.Span; found = true; } else return false; } return found; }
private static BraceMatchingResult MatchBraces(SyntaxToken token, SourceLocation position, SyntaxKind leftKind, SyntaxKind rightKind) { var isLeft = token.Kind == leftKind && position == token.SourceRange.Start; var isRight = token.Kind == rightKind && position == token.SourceRange.End; if (isLeft) { var left = token.Span; TextSpan right; if (FindMatchingBrace(position, 1, token.Parent, rightKind, out right)) return MapResultToFile(left, right); } else if (isRight) { TextSpan left; var right = token.Span; if (FindMatchingBrace(position, -1, token.Parent, leftKind, out left)) return MapResultToFile(left, right); } return BraceMatchingResult.None; }
public IEnumerable<CompletionItem> GetItems(SemanticModel semanticModel, SourceLocation position) { var syntaxTree = semanticModel.Compilation.SyntaxTree; return GetAvailableKeywords(syntaxTree, position) .Select(k => k.GetText()) .Select(t => new CompletionItem(t, t, t + " Keyword", Glyph.Keyword)); }
private static BraceMatchingResult MatchBraces(SyntaxTree syntaxTree, SourceLocation position, SyntaxKind leftKind, SyntaxKind rightKind) { return syntaxTree.Root.FindStartTokens(position) .Select(t => MatchBraces(t, position, leftKind, rightKind)) .Where(r => r.IsValid) .DefaultIfEmpty(BraceMatchingResult.None) .First(); }
public BraceMatchingResult MatchBraces(SyntaxTree syntaxTree, SourceLocation position) { return _matchingKinds .Select(k => MatchBraces(syntaxTree, position, k.Item1, k.Item2)) .Where(r => r.IsValid) .DefaultIfEmpty(BraceMatchingResult.None) .First(); }
private static bool IsInPropertyAccess(SyntaxNode root, SourceLocation position) { var token = root.FindTokenOnLeft(position); if (token == null || !token.SourceRange.ContainsOrTouches(position)) return false; var propertyAccess = token.Parent.AncestorsAndSelf().OfType<FieldAccessExpressionSyntax>().FirstOrDefault(); return propertyAccess != null && (propertyAccess.DotToken == token || propertyAccess.Name == token); }
public IEnumerable<HighlightSpan> GetHighlights(SemanticModel semanticModel, SourceLocation position) { var symbolAtPosition = semanticModel.FindSymbol(position); if (symbolAtPosition == null) return Enumerable.Empty<HighlightSpan>(); return semanticModel.FindUsages(symbolAtPosition.Value.Symbol) .Select(s => new HighlightSpan(s.Span, s.Kind == SymbolSpanKind.Definition)); }
private static IEnumerable<SyntaxKind> GetAvailableKeywords(SyntaxTree syntaxTree, SourceLocation position) { var isInNonUserCode = syntaxTree.Root.InNonUserCode(position); if (isInNonUserCode) yield break; var isPreprocessorDirectiveContext = syntaxTree.DefinitelyInMacro(position); var leftToken = syntaxTree.Root.FindTokenOnLeft(position); var targetToken = leftToken.GetPreviousTokenIfTouchingWord(position); if (targetToken == null) yield break; var isPreprocessorKeywordContext = isPreprocessorDirectiveContext && syntaxTree.IsPreprocessorKeywordContext(position, leftToken); var isStatementContext = !isPreprocessorDirectiveContext && targetToken.IsBeginningOfStatementContext(); var isSemanticContext = !isPreprocessorDirectiveContext && leftToken.HasAncestor<SemanticSyntax>(); var isTypeDeclarationContext = syntaxTree.IsTypeDeclarationContext(targetToken); if (IsValidBreakKeywordContext(isStatementContext, leftToken)) yield return SyntaxKind.BreakKeyword; if (targetToken.IsSwitchLabelContext()) yield return SyntaxKind.CaseKeyword; if (IsValidContinueKeywordContext(isStatementContext, leftToken)) yield return SyntaxKind.ContinueKeyword; if (isPreprocessorDirectiveContext || IsValidElseKeywordContext(targetToken)) yield return SyntaxKind.ElseKeyword; if (isPreprocessorKeywordContext || isStatementContext) yield return SyntaxKind.IfKeyword; if (isSemanticContext) yield return SyntaxKind.PackoffsetKeyword; if (isStatementContext) yield return SyntaxKind.ReturnKeyword; if (isSemanticContext) yield return SyntaxKind.RegisterKeyword; if (isTypeDeclarationContext) yield return SyntaxKind.StructKeyword; if (isStatementContext) yield return SyntaxKind.SwitchKeyword; if (isStatementContext || IsValidWhileKeywordContext(targetToken)) yield return SyntaxKind.WhileKeyword; }
public static SymbolSpan? FindSymbol(this SemanticModel semanticModel, SourceLocation position) { if (semanticModel == null) throw new ArgumentNullException(nameof(semanticModel)); var syntaxTree = semanticModel.SyntaxTree; return syntaxTree.Root.FindNodes(position) .SelectMany(n => GetSymbolSpans(semanticModel, n)) .Where(s => s.Span.IsInRootFile && s.SourceRange.ContainsOrTouches(position)) .Select(s => s).Cast<SymbolSpan?>().FirstOrDefault(); }
private static IEnumerable<CompletionItem> GetGlobalCompletions(SemanticModel semanticModel, SourceLocation position) { var symbols = semanticModel.LookupSymbols(position) .Where(x => !(x is SemanticSymbol)) .Where(x => !(x is AttributeSymbol)); if (!semanticModel.SyntaxTree.PossiblyInTypeName(position)) symbols = symbols.Where(x => !(x is TypeSymbol)); return CreateSymbolCompletions(symbols); }
public static IEnumerable<HighlightSpan> GetHighlights(this SemanticModel semanticModel, SourceLocation position, IEnumerable<IHighlighter> highlighters) { var result = new List<HighlightSpan>(); foreach (var highlighter in highlighters) { result.AddRange(highlighter .GetHighlights(semanticModel, position) .Where(x => x.Span.IsInRootFile)); } return result; }
public static bool IsPreprocessorKeywordContext(this SyntaxTree syntaxTree, SourceLocation position, SyntaxToken preProcessorTokenOnLeftOfPosition) { // cases: // #| // #d| // # | // # d| // note: comments are not allowed between the # and item. var token = preProcessorTokenOnLeftOfPosition; token = token.GetPreviousTokenIfTouchingWord(position); if (token.IsKind(SyntaxKind.HashToken)) return true; return false; }
private static FieldAccessExpressionSyntax GetPropertyAccessExpression(SyntaxNode root, SourceLocation position) { var token = root.FindTokenOnLeft(position); var previous = token.GetPreviousToken(false, true); var dot = previous != null && previous.Kind == SyntaxKind.DotToken ? previous : token; var p = dot.Parent.AncestorsAndSelf().OfType<FieldAccessExpressionSyntax>().FirstOrDefault(); if (p != null) { var afterDot = p.DotToken.SourceRange.End <= position && position <= p.Name.SourceRange.End; if (afterDot) return p; } return null; }
public IEnumerable<CompletionItem> GetItems(SemanticModel semanticModel, SourceLocation position) { var root = semanticModel.SyntaxTree.Root; // We don't want to show a completions for these cases. if (semanticModel.SyntaxTree.PossiblyInUserGivenName(position)) return Enumerable.Empty<CompletionItem>(); if (semanticModel.SyntaxTree.DefinitelyInMacro(position)) return Enumerable.Empty<CompletionItem>(); if (semanticModel.SyntaxTree.DefinitelyInVariableDeclaratorQualifier(position)) return Enumerable.Empty<CompletionItem>(); // Comments and literals don't get completion information if (root.InComment(position) || root.InLiteral(position)) return Enumerable.Empty<CompletionItem>(); if (semanticModel.SyntaxTree.DefinitelyInTypeName(position)) return GetTypeCompletions(semanticModel, position); var propertyAccessExpression = GetPropertyAccessExpression(root, position); return propertyAccessExpression == null ? GetGlobalCompletions(semanticModel, position) : GetMemberCompletions(semanticModel, propertyAccessExpression); }
public IEnumerable<Symbol> LookupSymbols(SourceLocation position) { var node = FindClosestNodeWithBinder(_bindingResult.Root, position); var binder = node == null ? null : _bindingResult.GetBinder(node); return binder == null ? Enumerable.Empty<Symbol>() : LookupSymbols(binder); }
private SyntaxNode FindClosestNodeWithBinder(SyntaxNode root, SourceLocation position) { var token = root.FindTokenContext(position); return (from n in token.Parent.AncestorsAndSelf() let bc = _bindingResult.GetBinder(n) where bc != null select n).FirstOrDefault(); }
private static IEnumerable<CompletionItem> GetTypeCompletions(SemanticModel semanticModel, SourceLocation position) { var symbols = semanticModel.LookupSymbols(position).OfType<TypeSymbol>(); return CreateSymbolCompletions(symbols); }