///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Sets the current statement indicator, by finding the next breakpoint after the specified snapshot offset. /// </summary> /// <param name="document">The editor document.</param> /// <param name="startSnapshotOffset">The starting snapshot offset to examine.</param> /// <returns>The current statement snapshot offset.</returns> public static TextSnapshotOffset SetCurrentStatement(IEditorDocument document, TextSnapshotOffset startSnapshotOffset) { if (!startSnapshotOffset.IsDeleted) { // Create search options (only allow enabled breakpoints) var options = new TagSearchOptions <BreakpointIndicatorTag>(); options.Filter = (tr => tr.Tag.IsEnabled); // Find the next breakpoint var tagRange = document.IndicatorManager.Breakpoints.FindNext(startSnapshotOffset, options); if (tagRange != null) { // Get the snapshot range of the breakpoint var snapshotRange = tagRange.VersionRange.Translate(startSnapshotOffset.Snapshot); var currentStatementSnapshotOffset = new TextSnapshotOffset(snapshotRange.Snapshot, snapshotRange.EndOffset); // Set the current statement indicator range document.IndicatorManager.CurrentStatement.SetInstance(snapshotRange); return(currentStatementSnapshotOffset); } } // Remove any current statement indicator document.IndicatorManager.CurrentStatement.Clear(); return(TextSnapshotOffset.Deleted); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // NON-PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Finds the statement AST node that contains the specified offset. /// </summary> /// <param name="parseData">The parse data.</param> /// <param name="snapshotOffset">The target snapshot offset.</param> /// <returns>The statement AST node that contains the specified offset.</returns> private static IAstNode FindContainingStatement(IDotNetParseData parseData, TextSnapshotOffset snapshotOffset) { // Get the offset relative to the AST's snapshot var offset = snapshotOffset.Offset; if (parseData.Snapshot != null) { offset = snapshotOffset.TranslateTo(parseData.Snapshot, TextOffsetTrackingMode.Negative); } // Loop upwards through the AST to find a containing statement var node = parseData.Ast.FindDescendantNode(offset); Statement statmentNode = null; while (node != null) { statmentNode = node as Statement; if (statmentNode != null) { return(statmentNode); } node = node.Parent; } return(null); }
public IStructureMatchResultSet Match(TextSnapshotOffset snapshotOffset, IStructureMatchOptions options) { var snapshot = snapshotOffset.GetDocumentView(); if (snapshot == null) { return(null); } SyntaxTree syntaxTree; if (!snapshot.Document.TryGetSyntaxTree(out syntaxTree)) { return(null); } var position = snapshot.Position; var result = syntaxTree.MatchBraces(position, Matchers); if (!result.IsValid) { return(null); } var leftRange = snapshot.ToSnapshotRange(result.Left); var rightRange = snapshot.ToSnapshotRange(result.Right); var results = new StructureMatchResultCollection { new StructureMatchResult(leftRange), new StructureMatchResult(rightRange) }; return(new StructureMatchResultSet(results)); }
public static DocumentView GetDocumentView(this TextSnapshotOffset offset) { var position = offset.ToOffset(); var document = offset.Snapshot.ToDocument(); return(new DocumentView(document, position)); }
public static int ToOffset(this TextSnapshotOffset offset) { var sourceText = offset.Snapshot.ToSourceText(); var textPosition = offset.Position; var line = sourceText.Lines[textPosition.Line]; return(line.Span.Start + textPosition.Character); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Attempts to locate structural text, such as bracket pairs, at the specified offset. /// </summary> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> to examine.</param> /// <param name="options">The <see cref="IStructureMatchOptions"/> to use.</param> /// <returns>An <see cref="IStructureMatchResultSet"/> that contains the results that were found, if any.</returns> /// <remarks> /// When the result set is empty, no structural delimiter was next to the specified offset. /// When the result set contains a single result, a structural delimiter such as a bracket was found next to the specified offset, /// but no matching structural delimiter was found. /// The result set may contain multiple entries in cases such as when a language wishes to flag <c>#if...#else...#endif</c> blocks as a structure. /// </remarks> public override IStructureMatchResultSet Match(TextSnapshotOffset snapshotOffset, IStructureMatchOptions options) { if (snapshotOffset.IsDeleted) { throw new ArgumentNullException("snapshotOffset"); } // Get a snapshot reader and configure it for quick initial lookup ITextSnapshotReader reader = snapshotOffset.Snapshot.GetReader(snapshotOffset.Offset); reader.Options.DefaultTokenLoadBufferLength = 250; reader.Options.InitialTokenLoadBufferLength = 4; IToken token = reader.Token; if (token != null) { // If the token is not a multi-line comment but is at the start of a token, check the previous token if ((token.Id != SimpleTokenId.MultiLineCommentText) && (reader.IsAtTokenStart)) { token = reader.ReadTokenReverse(); } // If the token is a multi-line comment... if (token.Id == SimpleTokenId.MultiLineCommentText) { // The Simple language programmatic lexer variant only has a single token for the entire comment so // ensure the target offset is at a delimiter (and not within the body of the comment)... // For most other languages, you'd want to scan tokens to find a matching delimiter token instead bool isAtStart = (snapshotOffset.Offset <= token.StartOffset + 2); bool isAtEnd = (snapshotOffset.Offset >= token.EndOffset - 2); if (isAtStart || isAtEnd) { // Get the token's text and ensure it ends with a proper delimiter string tokenText = reader.TokenText; if ((token.Length >= 4) && (tokenText.EndsWith("*/", StringComparison.Ordinal))) { // Found a valid match StructureMatchResultCollection results = new StructureMatchResultCollection(); results.Add(new StructureMatchResult(new TextSnapshotRange(reader.Snapshot, token.StartOffset, token.StartOffset + 2)) { IsSource = isAtStart, NavigationSnapshotOffset = new TextSnapshotOffset(reader.Snapshot, token.StartOffset) }); results.Add(new StructureMatchResult(new TextSnapshotRange(reader.Snapshot, token.EndOffset - 2, token.EndOffset)) { IsSource = !isAtStart, NavigationSnapshotOffset = new TextSnapshotOffset(reader.Snapshot, token.EndOffset) }); return(new StructureMatchResultSet(results)); } } } } // Call the base method return(base.Match(snapshotOffset, options)); }
/// <summary> /// Examines the AST data to determine the context type and insert the containing function declaration. /// </summary> /// <param name="context">The <see cref="SimpleContext"/> to update.</param> private static void UpdateFromAst(SimpleContext context) { // Get the snapshot offset TextSnapshotOffset snapshotOffset = context.SnapshotOffset; // Get the document ICodeDocument document = snapshotOffset.Snapshot.Document as ICodeDocument; if (document == null) { return; } ILLParseData parseData = document.ParseData as ILLParseData; if (parseData != null) { CompilationUnit compilationUnit = parseData.Ast as CompilationUnit; if ((compilationUnit != null) && (compilationUnit.HasMembers)) { // Translate the snapshot offset to the AST's snapshot if (parseData.Snapshot != null) { snapshotOffset = snapshotOffset.TranslateTo(parseData.Snapshot, TextOffsetTrackingMode.Negative); } // Loop through AST nodes foreach (FunctionDeclaration functionAstNode in compilationUnit.Members) { // If the child node is a function declaration with valid offsets... if ((functionAstNode.StartOffset.HasValue) && (functionAstNode.EndOffset.HasValue)) { // If the function's text range contains the offset... TextRange functionTextRange = new TextRange(functionAstNode.StartOffset.Value, functionAstNode.EndOffset.Value); if (functionTextRange.Contains(snapshotOffset.Offset)) { // Initially assume we are in a header context.Type = SimpleContextType.FunctionDeclarationHeader; context.ContainingFunctionDeclaration = functionAstNode; // If the function has a body with a range... if ((functionAstNode.Body != null) && (functionAstNode.Body.StartOffset.HasValue) && (functionAstNode.Body.EndOffset.HasValue)) { // If the block's text range contains the offset... TextRange blockTextRange = new TextRange(functionAstNode.Body.StartOffset.Value + 1, functionAstNode.Body.EndOffset.Value - 1); if (blockTextRange.Contains(snapshotOffset.Offset)) { // Mark that we are in a block instead context.Type = SimpleContextType.FunctionDeclarationBlock; } } break; } } } } } }
/// <summary> /// Occurs when the button is clicked. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param> private void OnStopDebuggingButtonClick(object sender, RoutedEventArgs e) { // Flag as not debugging currentStatementSnapshotOffset = DebuggingHelper.SetCurrentStatement(editor.Document, TextSnapshotOffset.Deleted); stopDebuggingButton.IsEnabled = false; // Focus the editor editor.Focus(); }
public static TextSpan ToTextSpan(this TextSnapshotRange range) { var startOffset = new TextSnapshotOffset(range.Snapshot, range.StartOffset); var endOffset = new TextSnapshotOffset(range.Snapshot, range.EndOffset); var start = startOffset.ToOffset(); var end = endOffset.ToOffset(); return(TextSpan.FromBounds(start, end)); }
public static DocumentView GetDocumentView(this SyntaxEditor syntaxEditor) { var document = syntaxEditor.Document.GetDocument(); var snapshot = document.Text.ToTextSnapshot(); var offset = syntaxEditor.Caret.Offset; var selection = syntaxEditor.ActiveView.Selection.SnapshotRange.TranslateTo(snapshot, TextRangeTrackingModes.Default).ToTextSpan(); var position = new TextSnapshotOffset(snapshot, offset).ToOffset(); return(new DocumentView(document, position, selection)); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // OBJECT ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes a new instance of the <c>SimpleContext</c> class. /// </summary> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> that indicates the location to examine.</param> public SimpleContext(TextSnapshotOffset snapshotOffset) { if (snapshotOffset.IsDeleted) { throw new ArgumentNullException("snapshotOffset"); } // Initialize this.snapshotOffset = snapshotOffset; }
///////////////////////////////////////////////////////////////////////////////////////////////////// // OBJECT ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes a new instance of the <c>CodeLensDeclaration</c> class. /// </summary> /// <param name="snapshotOffset">The snapshot offset at which the declaration occurs.</param> /// <param name="astNode">The <see cref="IAstNode"/> for the declaration.</param> public CodeLensDeclaration(TextSnapshotOffset snapshotOffset, IAstNode astNode) { if (astNode == null) { throw new ArgumentNullException("astNode"); } // Initialize this.VersionRange = new TextSnapshotRange(snapshotOffset).ToVersionRange(TextRangeTrackingModes.Default); this.AstNode = astNode; this.CreateKey(); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Creates a <see cref="SimpleContext"/> for the specified <see cref="TextSnapshotOffset"/>. /// </summary> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> for which to create a context.</param> /// <param name="includeArgumentInfo">Whether to populate the argument-related context properties, for use with parameter info.</param> /// <returns>The <see cref="SimpleContext"/> that was created.</returns> public SimpleContext CreateContext(TextSnapshotOffset snapshotOffset, bool includeArgumentInfo) { // Create a context SimpleContext context = new SimpleContext(snapshotOffset); // Update the context from the AST UpdateFromAst(context); // Update the context from the snapshot text UpdateFromSnapshotText(context, includeArgumentInfo); return(context); }
/// <summary> /// Occurs when the button is clicked. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param> private void OnStartDebuggingButtonClick(object sender, RoutedEventArgs e) { // If starting debugging from a stopped state, begin looking at the document start if (currentStatementSnapshotOffset.IsDeleted) { currentStatementSnapshotOffset = new TextSnapshotOffset(editor.ActiveView.CurrentSnapshot, 0); } // Flag as debugging currentStatementSnapshotOffset = DebuggingHelper.SetCurrentStatement(editor.Document, currentStatementSnapshotOffset); stopDebuggingButton.IsEnabled = !currentStatementSnapshotOffset.IsDeleted; // Focus the editor editor.Focus(); }
/// <summary> /// Translates from a generated snapshot to an editor snapshot. /// </summary> /// <param name="snapshotOffset">The snapshot offset.</param> /// <returns>The translated snapshot, if within a child language section.</returns> public TextSnapshotOffset?TranslateGeneratedToEditor(TextSnapshotOffset snapshotOffset) { if ((generatedParseData != null) && (generatedParseData.Snapshot != null)) { // Translate back to the generated parse data's snapshot snapshotOffset = snapshotOffset.TranslateTo(generatedParseData.Snapshot, TextOffsetTrackingMode.Negative); foreach (var mapping in textRangeMappings) { if (mapping.Item2.IntersectsWith(snapshotOffset.Offset)) { var editorSnapshotOffset = new TextSnapshotOffset(snapshot, mapping.Item1.StartOffset + (snapshotOffset.Offset - mapping.Item2.StartOffset)); return(editorSnapshotOffset); } } } return(null); }
/// <summary> /// Toggles a breakpoint. /// </summary> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> of the indicator.</param> /// <param name="isEnabled">Whether a new breakpoint should be enabled.</param> public static void ToggleBreakpoint(TextSnapshotOffset snapshotOffset, bool isEnabled) { var document = snapshotOffset.Snapshot.Document as IEditorDocument; if (document == null) { return; } var parseData = document.ParseData as IDotNetParseData; if (parseData == null) { return; } // Find the containing statement var node = FindContainingStatement(parseData, snapshotOffset); if ((node == null) || (!node.StartOffset.HasValue) || (!node.EndOffset.HasValue)) { MessageBox.Show("Please move the caret inside of a valid C# statement.", "Toggle Breakpoint", MessageBoxButton.OK, MessageBoxImage.Exclamation); return; } // Get the snapshot range of the statement var snapshotRange = new TextSnapshotRange(parseData.Snapshot ?? snapshotOffset.Snapshot, node.StartOffset.Value, node.EndOffset.Value); // Create a breakpoint tag var tag = new BreakpointIndicatorTag(); tag.IsEnabled = isEnabled; // Toggle the indicator var tagRange = document.IndicatorManager.Breakpoints.Toggle(snapshotRange, tag); // Set the tag's content provider (quick info for the glyph) if a tag was added if (tagRange != null) { tag.ContentProvider = new BreakpointIndicatorTagContentProvider(tagRange); } }
public override object GetContext(IEditorView view, int offset) { var documentView = view.SyntaxEditor.GetDocumentView(); var document = documentView.Document; SemanticModel semanticModel; if (!document.TryGetSemanticModel(out semanticModel)) { return(null); } var snapshot = document.Text.ToTextSnapshot(); var snapshotOffset = new TextSnapshotOffset(snapshot, offset); var position = snapshotOffset.ToOffset(); var model = semanticModel.GetQuickInfoModel(position, Providers); return(model); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Returns a set of <see cref="INavigableSymbol"/> objects that are accessible within the optional parent <see cref="INavigableSymbol"/>. /// </summary> /// <param name="context">An <see cref="INavigableRequestContext"/> that provides the context of the request.</param> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> that contains the <see cref="ITextSnapshot"/> to examine, along with a contextual offset.</param> /// <param name="parentSymbol">The optional parent <see cref="INavigableSymbol"/> to examine, or a null value if the root symbols are requested.</param> /// <returns>An <see cref="INavigableSymbolSet"/> containing the <see cref="INavigableSymbol"/> objects that were located.</returns> public INavigableSymbolSet GetSymbols(INavigableRequestContext context, TextSnapshotOffset snapshotOffset, INavigableSymbol parentSymbol) { if (context == null) { throw new ArgumentNullException("context"); } if (snapshotOffset.IsDeleted) { throw new ArgumentOutOfRangeException("snapshotOffset"); } if (context == NavigableRequestContexts.NavigableSymbolSelector) { var document = snapshotOffset.Snapshot.Document as ICodeDocument; if (document != null) { // If there is AST data... var parseData = document.ParseData as ILLParseData; if ((parseData != null) && (parseData.Ast != null)) { // Recurse into the AST var symbols = new List <INavigableSymbol>(); // NOTE: Normally here you would return either root symbols or member symbols depending on if a parentSymbol is passed... // In this Simple language though, we only ever need root symbols if (parentSymbol == null) { this.AddFunctionDeclarationSymbolsFromAst(symbols, parseData.Snapshot ?? snapshotOffset.Snapshot, parseData.Ast as CompilationUnit); } // Sort symbols.Sort(navigationSymbolComparer); return(new NavigableSymbolSet(symbols)); } } } // No results return(new NavigableSymbolSet(null)); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Returns the ideal amount of indent, always in columns, for the line containing the snapshot offset. /// </summary> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> whose line should be examined.</param> /// <param name="defaultAmount">The default indent amount, which is the amount used in <c>Block</c> mode.</param> /// <returns>The ideal amount of indent, always in columns, for the line containing the snapshot offset.</returns> /// <remarks> /// This method is called when the <see cref="IndentMode"/> is <c>Smart</c>. /// The containing <see cref="ITextDocument"/> is accessible via the snapshot range's <see cref="ITextSnapshot"/>. /// </remarks> public override int GetIndentAmount(TextSnapshotOffset snapshotOffset, int defaultAmount) { // If the snapshot offset is deleted, return the default amount if (snapshotOffset.IsDeleted) { return(defaultAmount); } // Get the ICodeDocument from the snapshot ICodeDocument document = snapshotOffset.Snapshot.Document as ICodeDocument; if (document == null) { return(defaultAmount); } // Get the tab size int tabSize = document.TabSize; // Get a reader ITextSnapshotReader reader = snapshotOffset.Snapshot.GetReader(snapshotOffset.Offset); if (reader == null) { return(defaultAmount); } // Get the indentation base line index int indentationBaseLineIndex = Math.Max(0, snapshotOffset.Line.Index - 1); // Ensure we are at the start of the current token if (!reader.IsAtTokenStart) { reader.GoToCurrentTokenStart(); } // If finding indentation for an open curly brace, move back a token bool isForOpenCurlyBrace = (reader.Token.Id == SimpleTokenId.OpenCurlyBrace); if (isForOpenCurlyBrace) { reader.GoToPreviousToken(); } // Loop backwards bool keywordFoundAfterStatement = false; bool statementFound = false; while (true) { switch (reader.Token.Id) { case SimpleTokenId.OpenCurlyBrace: { // Indent from this open curly brace return(reader.SnapshotLine.IndentAmount + tabSize); } case SimpleTokenId.CloseCurlyBrace: // Return the indent level of the matching { reader.GoToPreviousMatchingTokenById(SimpleTokenId.CloseCurlyBrace, SimpleTokenId.OpenCurlyBrace); return(reader.SnapshotLine.IndentAmount); case SimpleTokenId.CloseParenthesis: case SimpleTokenId.SemiColon: if (!statementFound) { // Flag that a statement was found statementFound = true; if (!keywordFoundAfterStatement) { // Use this line as indentation base indentationBaseLineIndex = reader.SnapshotLine.Index; } } break; default: if ((!keywordFoundAfterStatement) && (!statementFound) && (reader.Offset < snapshotOffset.Offset) && (reader.Token.Id >= SimpleTokenId.Function) && (reader.Token.Id <= SimpleTokenId.Var)) { // Flag that a keyword was found keywordFoundAfterStatement = true; // Use this line as indentation base indentationBaseLineIndex = reader.SnapshotLine.Index; } break; } // Go to the previous token if (!reader.GoToPreviousToken()) { break; } } // Indent a level if on the statement after the keyword return(reader.Snapshot.Lines[indentationBaseLineIndex].IndentAmount + (keywordFoundAfterStatement && isForOpenCurlyBrace ? tabSize : 0)); }
/// <summary> /// Examines the snapshot text to determine more detail about the context. /// </summary> /// <param name="context">The <see cref="SimpleContext"/> to update.</param> /// <param name="includeArgumentInfo">Whether to populate the argument-related context properties, for use with parameter info.</param> private static void UpdateFromSnapshotText(SimpleContext context, bool includeArgumentInfo) { // Get the snapshot offset TextSnapshotOffset snapshotOffset = context.SnapshotOffset; // Create a default initialization range context.InitializationSnapshotRange = new TextSnapshotRange(snapshotOffset); // Get a snapshot reader ITextSnapshotReader reader = snapshotOffset.Snapshot.GetReader(snapshotOffset.Offset); if (reader == null) { return; } IToken token = reader.ReadToken(); if (token != null) { // If the current token is a comment, flag no context switch (token.Id) { case SimpleTokenId.MultiLineCommentEndDelimiter: case SimpleTokenId.MultiLineCommentLineTerminator: case SimpleTokenId.MultiLineCommentStartDelimiter: case SimpleTokenId.MultiLineCommentText: case SimpleTokenId.SingleLineCommentEndDelimiter: case SimpleTokenId.SingleLineCommentStartDelimiter: case SimpleTokenId.SingleLineCommentText: context.Type = SimpleContextType.None; return; } } // If we are in a function declaration block... if (context.Type == SimpleContextType.FunctionDeclarationBlock) { // Get the AST ICodeDocument document = snapshotOffset.Snapshot.Document as ICodeDocument; if (document == null) { return; } ILLParseData parseData = document.ParseData as ILLParseData; if (parseData == null) { return; } CompilationUnit compilationUnit = parseData.Ast as CompilationUnit; if ((compilationUnit == null) || (!compilationUnit.HasMembers)) { return; } // If argument data should be scanned... if (includeArgumentInfo) { // Scan backward to look for argument data reader.Offset = snapshotOffset.Offset; reader.GoToCurrentTokenStart(); var startOffset = reader.Offset; token = reader.ReadTokenReverse(); while (token != null) { // Quit if we look behind too far (for performance reasons) - 500 is arbitrary number and could be tweaked if ((!context.ArgumentIndex.HasValue) && (startOffset - reader.Offset > 500)) { return; } switch (token.Id) { case SimpleTokenId.CloseParenthesis: // Skip over ( ... ) pair if (!reader.GoToPreviousMatchingTokenById(SimpleTokenId.CloseParenthesis, SimpleTokenId.OpenParenthesis)) { return; } break; case SimpleTokenId.Comma: // Update the context data if (context.ArgumentIndex.HasValue) { context.ArgumentIndex++; } else { context.ArgumentIndex = 1; context.ArgumentSnapshotOffset = new TextSnapshotOffset(reader.Snapshot, token.EndOffset); } break; case SimpleTokenId.OpenParenthesis: // Update the context data context.ArgumentListSnapshotOffset = new TextSnapshotOffset(reader.Snapshot, token.EndOffset); if (!context.ArgumentIndex.HasValue) { context.ArgumentIndex = 0; context.ArgumentSnapshotOffset = context.ArgumentListSnapshotOffset; } // Go to the previous token reader.GoToPreviousToken(); token = reader.Token; if ((token != null) && (token.Id == SimpleTokenId.Identifier)) { // Loop through the AST nodes to ensure that the identifier text matches a declared function name string functionName = reader.TokenText; foreach (FunctionDeclaration functionAstNode in compilationUnit.Members) { // If the name matches the function's name... if (functionAstNode.Name == functionName) { // Update the target function context.TargetFunction = functionAstNode; break; } } } return; default: // Quit if any tokens are found that aren't allowed in invocations if (!IsTokenAllowedInInvocation(token.Id)) { return; } else { break; } } // Move back a token token = reader.ReadTokenReverse(); } } else { // If the current token is an identifier... if ((token != null) && (token.Id == SimpleTokenId.Identifier)) { // Store the identifier snapshot range in case this is a function reference token TextSnapshotRange identifierSnapshotRange = new TextSnapshotRange(reader.Snapshot, token.TextRange); // Next, check to ensure the next non-whitespace token is a '(' token = reader.ReadToken(); while (!reader.IsAtSnapshotEnd) { if (token != null) { switch (token.Id) { case SimpleTokenId.Whitespace: // Continue break; case SimpleTokenId.OpenParenthesis: { // Loop through the AST nodes to ensure that the identifier text matches a declared function name foreach (FunctionDeclaration functionAstNode in compilationUnit.Members) { // If the name matches the function's name... if (functionAstNode.Name == identifierSnapshotRange.Text) { // Update the context type context.Type = SimpleContextType.FunctionReference; context.InitializationSnapshotRange = identifierSnapshotRange; context.TargetFunction = functionAstNode; break; } } return; } default: // Quit return; } } // Advance token = reader.ReadToken(); } } } } }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Translates the specified snapshot offset to the parse data's <see cref="IParseErrorProvider.Snapshot"/>, if possible, prior to containing AST node lookup. /// </summary> /// <param name="parseData">The <see cref="IDotNetParseData"/> to examine.</param> /// <param name="snapshotOffset">The <see cref="TextSnapshotOffset"/> to translate.</param> /// <returns>The translated offset.</returns> protected override TextSnapshotOffset TranslateToParseDataSnapshot(IDotNetParseData parseData, TextSnapshotOffset snapshotOffset) { var generatedSnapshotOffset = translateFunc(snapshotOffset); if (generatedSnapshotOffset.HasValue) { return(base.TranslateToParseDataSnapshot(parseData, generatedSnapshotOffset.Value)); } else { return(base.TranslateToParseDataSnapshot(parseData, snapshotOffset)); } }
private void OnStartDebuggingButtonClick(object sender, RoutedEventArgs e) { foreach (var bp in document.IndicatorManager.Breakpoints.GetInstances()) { var line = bp.VersionRange.Translate(document.CurrentSnapshot).StartPosition.Line; } if (currentStatementSnapshotOffset.IsDeleted) currentStatementSnapshotOffset = new TextSnapshotOffset(syntaxEditor.ActiveView.CurrentSnapshot, 0); var snapshotOffset = syntaxEditor.ActiveView.Selection.EndSnapshotOffset; var context = new PythonContextFactory().CreateContext(snapshotOffset); currentStatementSnapshotOffset = DebuggingHelper.SetCurrentStatement(syntaxEditor.Document, currentStatementSnapshotOffset); stopDebuggingButton.IsEnabled = !currentStatementSnapshotOffset.IsDeleted; syntaxEditor.Focus(); }
private void OnStopDebuggingButtonClick(object sender, RoutedEventArgs e) { currentStatementSnapshotOffset = DebuggingHelper.SetCurrentStatement(syntaxEditor.Document, TextSnapshotOffset.Deleted); stopDebuggingButton.IsEnabled = false; syntaxEditor.Focus(); }