public static bool ShouldUseSmartTokenFormatterInsteadOfIndenter( IEnumerable<IFormattingRule> formattingRules, CompilationUnitSyntax root, TextLine line, OptionSet optionSet, CancellationToken cancellationToken) { Contract.ThrowIfNull(formattingRules); Contract.ThrowIfNull(root); if (!optionSet.GetOption(FeatureOnOffOptions.AutoFormattingOnReturn, LanguageNames.CSharp)) { return false; } if (optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp) != FormattingOptions.IndentStyle.Smart) { return false; } var firstNonWhitespacePosition = line.GetFirstNonWhitespacePosition(); if (!firstNonWhitespacePosition.HasValue) { return false; } var token = root.FindToken(firstNonWhitespacePosition.Value); if (token.IsKind(SyntaxKind.None) || token.SpanStart != firstNonWhitespacePosition) { return false; } // first see whether there is a line operation for current token var previousToken = token.GetPreviousToken(includeZeroWidth: true); // only use smart token formatter when we have two visible tokens. if (previousToken.Kind() == SyntaxKind.None || previousToken.IsMissing) { return false; } var lineOperation = FormattingOperations.GetAdjustNewLinesOperation(formattingRules, previousToken, token, optionSet); if (lineOperation == null || lineOperation.Option == AdjustNewLinesOption.ForceLinesIfOnSingleLine) { // no indentation operation, nothing to do for smart token formatter return false; } // We're pressing enter between two tokens, have the formatter figure out hte appropriate // indentation. return true; }
static DebugDataTipInfo GetInfo (CompilationUnitSyntax root, SemanticModel semanticModel, int position, CancellationToken cancellationToken) { var token = root.FindToken (position); string textOpt = null; var expression = token.Parent as ExpressionSyntax; if (expression == null) { if (Microsoft.CodeAnalysis.CSharpExtensions.IsKind (token, SyntaxKind.IdentifierToken)) { if (token.Parent is MethodDeclarationSyntax) { return default(DebugDataTipInfo); } if (semanticModel != null) { if (token.Parent is PropertyDeclarationSyntax) { var propertySymbol = semanticModel.GetDeclaredSymbol ((PropertyDeclarationSyntax)token.Parent); if (propertySymbol.IsStatic) { textOpt = propertySymbol.ContainingType.GetFullName () + "." + propertySymbol.Name; } } else if (token.GetAncestor<FieldDeclarationSyntax> () != null) { var fieldSymbol = semanticModel.GetDeclaredSymbol (token.GetAncestor<VariableDeclaratorSyntax> ()); if (fieldSymbol.IsStatic) { textOpt = fieldSymbol.ContainingType.GetFullName () + "." + fieldSymbol.Name; } } } return new DebugDataTipInfo (token.Span, text: textOpt); } else { return default(DebugDataTipInfo); } } if (expression.IsAnyLiteralExpression ()) { // If the user hovers over a literal, give them a DataTip for the type of the // literal they're hovering over. // Partial semantics should always be sufficient because the (unconverted) type // of a literal can always easily be determined. var type = semanticModel?.GetTypeInfo (expression, cancellationToken).Type; return type == null ? default(DebugDataTipInfo) : new DebugDataTipInfo (expression.Span, type.GetFullName ()); } // Check if we are invoking method and if we do return null so we don't invoke it if (expression.Parent is InvocationExpressionSyntax || (semanticModel != null && expression.Parent is MemberAccessExpressionSyntax && expression.Parent.Parent is InvocationExpressionSyntax && semanticModel.GetSymbolInfo (token).Symbol is IMethodSymbol)) { return default(DebugDataTipInfo); } if (expression.IsRightSideOfDotOrArrow ()) { var curr = expression; while (true) { var conditionalAccess = curr.GetParentConditionalAccessExpression (); if (conditionalAccess == null) { break; } curr = conditionalAccess; } if (curr == expression) { // NB: Parent.Span, not Span as below. return new DebugDataTipInfo (expression.Parent.Span, text: null); } // NOTE: There may not be an ExpressionSyntax corresponding to the range we want. // For example, for input a?.$$B?.C, we want span [|a?.B|]?.C. return new DebugDataTipInfo (TextSpan.FromBounds (curr.SpanStart, expression.Span.End), text: null); } var typeSyntax = expression as TypeSyntax; if (typeSyntax != null && typeSyntax.IsVar) { // If the user is hovering over 'var', then pass back the full type name that 'var' // binds to. var type = semanticModel?.GetTypeInfo (typeSyntax, cancellationToken).Type; if (type != null) { textOpt = type.GetFullName (); } } if (semanticModel != null) { if (expression is IdentifierNameSyntax) { if (expression.Parent is ObjectCreationExpressionSyntax) { textOpt = ((INamedTypeSymbol)semanticModel.GetSymbolInfo (expression).Symbol).GetFullName (); } else if (expression.Parent is AssignmentExpressionSyntax && expression.Parent.Parent is InitializerExpressionSyntax) { var variable = expression.GetAncestor<VariableDeclaratorSyntax> (); if (variable != null) { textOpt = variable.Identifier.Text + "." + ((IdentifierNameSyntax)expression).Identifier.Text; } } } } return new DebugDataTipInfo (expression.Span, textOpt); }