private ITextBuffer GetTextBuffer(IVsTextBuffer document) { IComponentModel componentModel = Shell.ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel)) as IComponentModel; IVsEditorAdaptersFactoryService adapterService = componentModel.GetService <IVsEditorAdaptersFactoryService>(); return(adapterService.GetDocumentBuffer(document)); }
private IDocumentMarkup TryGetDocumentMarkup() { VSIVsTextBuffer bufferAdapter = _editorAdaptersFactoryService.GetBufferAdapter(_textBuffer); if (bufferAdapter == null) { return(null); } IDocument document = new JetIVsTextBuffer(bufferAdapter).JetDocument.Value; if (document == null) { return(null); } IDocumentMarkup documentMarkup = DocumentMarkupManagerBase.TryGetMarkupModel(document); if (documentMarkup == null || !documentMarkup.GetType().Name.StartsWith("Vs", StringComparison.Ordinal)) { return(null); } return(documentMarkup); }
public int ValidateBreakpointLocation( IVsTextBuffer pBuffer, int iLine, int iCol, VsTextSpan[] pCodeSpan ) { using ( Logger.LogBlock( FunctionId.Debugging_VsLanguageDebugInfo_ValidateBreakpointLocation, CancellationToken.None ) ) { var result = VSConstants.E_NOTIMPL; _waitIndicator.Wait( title: ServicesVSResources.Debugger, message: ServicesVSResources.Validating_breakpoint_location, allowCancel: true, action: waitContext => { result = ValidateBreakpointLocationWorker( pBuffer, iLine, iCol, pCodeSpan, waitContext.CancellationToken ); } ); return(result); } }
public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string pbstrName, out int piLineOffset) { using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetNameOfLocation, CancellationToken.None)) { string name = null; var lineOffset = 0; var succeeded = false; if (_languageDebugInfo != null) { _waitIndicator.Wait( title: ServicesVSResources.Debugger, message: ServicesVSResources.Determining_breakpoint_location, allowCancel: true, action: waitContext => { var cancellationToken = waitContext.CancellationToken; var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var nullablePoint = textBuffer.CurrentSnapshot.TryGetPoint(iLine, iCol); if (nullablePoint.HasValue) { var point = nullablePoint.Value; var document = point.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { // NOTE(cyrusn): We have to wait here because the debuggers' // GetNameOfLocation is a blocking call. In the future, it // would be nice if they could make it async. var debugLocationInfo = _languageDebugInfo.GetLocationInfoAsync(document, point, cancellationToken).WaitAndGetResult(cancellationToken); if (!debugLocationInfo.IsDefault) { succeeded = true; name = debugLocationInfo.Name; lineOffset = debugLocationInfo.LineOffset; } } } } }); if (succeeded) { pbstrName = name; piLineOffset = lineOffset; return(VSConstants.S_OK); } } // Note(DustinCa): Docs say that GetNameOfLocation should return S_FALSE if a name could not be found. // Also, that's what the old native code does, so we should do it here. pbstrName = null; piLineOffset = 0; return(VSConstants.S_FALSE); } }
public override int ValidateBreakpointLocation(IVsTextBuffer buffer, int line, int col, TextSpan[] pCodeSpan) { var componentModel = ServiceProvider.GetComponentModel(); var adapterFactoryService = componentModel.DefaultExportProvider.GetExport <IVsEditorAdaptersFactoryService>(); ITextBuffer textBuffer = adapterFactoryService.Value.GetDataBuffer(buffer); ITextSnapshot snapshot = textBuffer.CurrentSnapshot; ITextSnapshotLine snapshotLine = snapshot.GetLineFromLineNumber(line); string lineText = snapshotLine.GetText(); IList <IParseTree> statementTrees; IList <IToken> tokens; if (!LineStatementAnalyzer.TryGetLineStatements(textBuffer, line, out statementTrees, out tokens)) { return(VSConstants.E_FAIL); } IParseTree tree = null; for (int i = statementTrees.Count - 1; i >= 0; i--) { // want the last tree ending at or after col IParseTree current = statementTrees[i]; if (current.SourceInterval.Length == 0) { continue; } IToken token = tokens[current.SourceInterval.b]; if (token.Line - 1 < line) { break; } if (token.Line - 1 == line && (token.Column + token.StopIndex - token.StartIndex + 1) < col) { break; } tree = current; } if (tree == null) { return(VSConstants.E_FAIL); } IToken startToken = tokens[tree.SourceInterval.a]; IToken stopToken = tokens[tree.SourceInterval.b]; pCodeSpan[0].iStartLine = startToken.Line - 1; pCodeSpan[0].iStartIndex = startToken.Column; pCodeSpan[0].iEndLine = stopToken.Line - 1; pCodeSpan[0].iEndIndex = stopToken.Column + stopToken.StopIndex - stopToken.StartIndex + 1; return(VSConstants.S_OK); }
public int GetDataTipText(IVsTextBuffer pBuffer, VsTextSpan[] pSpan, out string pbstrText) { using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetDataTipText, CancellationToken.None)) { pbstrText = null; if (pSpan == null || pSpan.Length != 1) { return(VSConstants.E_INVALIDARG); } int result = VSConstants.E_FAIL; string pbstrTextInternal = null; _waitIndicator.Wait( title: ServicesVSResources.Debugger, message: ServicesVSResources.Getting_DataTip_text, allowCancel: true, action: waitContext => { var debugger = _languageService.Debugger; DBGMODE[] debugMode = new DBGMODE[1]; var cancellationToken = waitContext.CancellationToken; if (ErrorHandler.Succeeded(debugger.GetMode(debugMode)) && debugMode[0] != DBGMODE.DBGMODE_Design) { var editorAdapters = _languageService.EditorAdaptersFactoryService; var textSpan = pSpan[0]; var subjectBuffer = editorAdapters.GetDataBuffer(pBuffer); var textSnapshot = subjectBuffer.CurrentSnapshot; var document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var spanOpt = textSnapshot.TryGetSpan(textSpan); if (spanOpt.HasValue) { var dataTipInfo = _languageDebugInfo.GetDataTipInfoAsync(document, spanOpt.Value.Start, cancellationToken).WaitAndGetResult(cancellationToken); if (!dataTipInfo.IsDefault) { var resultSpan = dataTipInfo.Span.ToSnapshotSpan(textSnapshot); string textOpt = dataTipInfo.Text; pSpan[0] = resultSpan.ToVsTextSpan(); result = debugger.GetDataTipValue((IVsTextLines)pBuffer, pSpan, textOpt, out pbstrTextInternal); } } } } }); pbstrText = pbstrTextInternal; return(result); } }
public int GetLanguageID( IVsTextBuffer pBuffer, int iLine, int iCol, out Guid pguidLanguageID ) { pguidLanguageID = _languageId; return(VSConstants.S_OK); }
int IVsLanguageDebugInfo.GetLanguageID(IVsTextBuffer pBuffer, int iLine, int iCol, out Guid pguidLanguageID) { try { return(LanguageDebugInfo.GetLanguageID(pBuffer, iLine, iCol, out pguidLanguageID)); } catch (Exception e) when(FatalError.ReportWithoutCrash(e) && false) { throw ExceptionUtilities.Unreachable; } }
int IVsLanguageDebugInfo.GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string pbstrName, out int piLineOffset) { try { return(LanguageDebugInfo.GetNameOfLocation(pBuffer, iLine, iCol, out pbstrName, out piLineOffset)); } catch (Exception e) when(FatalError.ReportWithoutCrash(e) && false) { throw ExceptionUtilities.Unreachable; } }
int IVsLanguageDebugInfo.GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR ppEnum) { try { return(LanguageDebugInfo.GetProximityExpressions(pBuffer, iLine, iCol, cLines, out ppEnum)); } catch (Exception e) when(FatalError.ReportWithoutCrash(e) && false) { throw ExceptionUtilities.Unreachable; } }
int IVsLanguageDebugInfo.IsMappedLocation(IVsTextBuffer pBuffer, int iLine, int iCol) { try { return(LanguageDebugInfo.IsMappedLocation(pBuffer, iLine, iCol)); } catch (Exception e) when(FatalError.ReportWithoutCrash(e) && false) { throw ExceptionUtilities.Unreachable; } }
int IVsLanguageDebugInfo.ValidateBreakpointLocation(IVsTextBuffer pBuffer, int iLine, int iCol, TextSpan[] pCodeSpan) { try { return(LanguageDebugInfo.ValidateBreakpointLocation(pBuffer, iLine, iCol, pCodeSpan)); } catch (Exception e) when(FatalError.ReportWithoutCrash(e) && false) { throw ExceptionUtilities.Unreachable; } }
public static Guid?GetLanguageServiceID([NotNull] this IVsTextBuffer textBuffer) { Requires.NotNull(textBuffer, nameof(textBuffer)); Guid id; int hr = textBuffer.GetLanguageServiceID(out id); if (hr != VSConstants.S_OK) { return(null); } return(id); }
public static Guid?GetLanguageServiceID(this IVsTextBuffer textBuffer) { Contract.Requires <ArgumentNullException>(textBuffer != null, "textBuffer"); Guid id; int hr = textBuffer.GetLanguageServiceID(out id); if (hr != VSConstants.S_OK) { return(null); } return(id); }
public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR ppEnum) { // NOTE(cyrusn): cLines is ignored. This is to match existing dev10 behavior. using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetProximityExpressions, CancellationToken.None)) { VsEnumBSTR enumBSTR = null; var succeeded = false; _waitIndicator.Wait( title: ServicesVSResources.Debugger, message: ServicesVSResources.Determining_autos, allowCancel: true, action: waitContext => { var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var snapshot = textBuffer.CurrentSnapshot; var nullablePoint = snapshot.TryGetPoint(iLine, iCol); if (nullablePoint.HasValue) { var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var point = nullablePoint.Value; var proximityExpressions = _proximityExpressionsService.GetProximityExpressionsAsync(document, point.Position, waitContext.CancellationToken).WaitAndGetResult(waitContext.CancellationToken); if (proximityExpressions != null) { enumBSTR = new VsEnumBSTR(proximityExpressions); succeeded = true; } } } } }); if (succeeded) { ppEnum = enumBSTR; return(VSConstants.S_OK); } ppEnum = null; return(VSConstants.E_FAIL); } }
public override int ValidateBreakpointLocation(IVsTextBuffer buffer, int line, int col, TextSpan[] pCodeSpan) { var componentModel = ServiceProvider.GetComponentModel(); var adapterFactoryService = componentModel.DefaultExportProvider.GetExport<IVsEditorAdaptersFactoryService>(); ITextBuffer textBuffer = adapterFactoryService.Value.GetDataBuffer(buffer); ITextSnapshot snapshot = textBuffer.CurrentSnapshot; ITextSnapshotLine snapshotLine = snapshot.GetLineFromLineNumber(line); string lineText = snapshotLine.GetText(); IList<IParseTree> statementTrees; IList<IToken> tokens; if (!LineStatementAnalyzer.TryGetLineStatements(textBuffer, line, out statementTrees, out tokens)) return VSConstants.E_FAIL; IParseTree tree = null; for (int i = statementTrees.Count - 1; i >= 0; i--) { // want the last tree ending at or after col IParseTree current = statementTrees[i]; if (current.SourceInterval.Length == 0) continue; IToken token = tokens[current.SourceInterval.b]; if (token.Line - 1 < line) break; if (token.Line - 1 == line && (token.Column + token.StopIndex - token.StartIndex + 1) < col) break; tree = current; } if (tree == null) return VSConstants.E_FAIL; IToken startToken = tokens[tree.SourceInterval.a]; IToken stopToken = tokens[tree.SourceInterval.b]; pCodeSpan[0].iStartLine = startToken.Line - 1; pCodeSpan[0].iStartIndex = startToken.Column; pCodeSpan[0].iEndLine = stopToken.Line - 1; pCodeSpan[0].iEndIndex = stopToken.Column + stopToken.StopIndex - stopToken.StartIndex + 1; return VSConstants.S_OK; }
public int ValidateBreakpointLocation(IVsTextBuffer pBuffer, int iLine, int iCol, VsTextSpan[] pCodeSpan) { using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_ValidateBreakpointLocation, CancellationToken.None)) { var result = VSConstants.E_NOTIMPL; _uiThreadOperationExecutor.Execute( title: ServicesVSResources.Debugger, defaultDescription: ServicesVSResources.Validating_breakpoint_location, allowCancellation: true, showProgress: false, action: waitContext => { result = ValidateBreakpointLocationWorker(pBuffer, iLine, iCol, pCodeSpan, waitContext.UserCancellationToken); }); return(result); } }
public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR?ppEnum) { // NOTE(cyrusn): cLines is ignored. This is to match existing dev10 behavior. using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetProximityExpressions, CancellationToken.None)) { VsEnumBSTR?enumBSTR = null; if (_proximityExpressionsService != null) { _uiThreadOperationExecutor.Execute( title: ServicesVSResources.Debugger, defaultDescription: ServicesVSResources.Determining_autos, allowCancellation: true, showProgress: false, action: context => { var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var snapshot = textBuffer.CurrentSnapshot; var nullablePoint = snapshot.TryGetPoint(iLine, iCol); if (nullablePoint.HasValue) { var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var point = nullablePoint.Value; var proximityExpressions = _proximityExpressionsService.GetProximityExpressionsAsync(document, point.Position, context.UserCancellationToken).WaitAndGetResult(context.UserCancellationToken); if (proximityExpressions != null) { enumBSTR = new VsEnumBSTR(proximityExpressions); } } } } }); } ppEnum = enumBSTR; return(ppEnum != null ? VSConstants.S_OK : VSConstants.E_FAIL); } }
private IDocumentMarkup TryGetDocumentMarkup() { VSIVsTextBuffer bufferAdapter = _editorAdaptersFactoryService.GetBufferAdapter(_textBuffer); if (bufferAdapter == null) { return(null); } IDocument document = new JetIVsTextBuffer(bufferAdapter).JetDocument.Value; if (document == null) { return(null); } IDocumentMarkup documentMarkup = DocumentMarkupManagerBase.TryGetMarkupModel(document); return(documentMarkup is IVsDocumentMarkup ? documentMarkup : null); }
public IWpfTextViewMargin CreateMargin(IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin marginContainer) { /* If a language service is registered for this content type, then the CodeWindowManager will * support the standard editor navigation margin. */ IVsTextBuffer textBufferAdapter = EditorAdaptersFactoryService.GetBufferAdapter(wpfTextViewHost.TextView.TextBuffer); if (textBufferAdapter != null) { Guid?languageService = textBufferAdapter.GetLanguageServiceID(); if (languageService.HasValue) { return(null); } } //var viewAdapter = EditorAdaptersFactoryService.GetViewAdapter(wpfTextViewHost.TextView); //var codeWindow = viewAdapter.GetCodeWindow(); //var dropdownBarManager = codeWindow as IVsDropdownBarManager; //if (dropdownBarManager != null && dropdownBarManager.GetDropdownBarClient() != null) // return null; var providers = NavigationSourceProviders.Where(provider => provider.Metadata.ContentTypes.Any(contentType => wpfTextViewHost.TextView.TextBuffer.ContentType.IsOfType(contentType))); var sources = providers .Select(provider => provider.Value.TryCreateEditorNavigationSource(wpfTextViewHost.TextView.TextBuffer)) .Where(source => source != null) .ToArray(); return(new EditorNavigationMargin(wpfTextViewHost.TextView, sources, EditorNavigationTypeRegistryService)); //var tagAggregator = BufferTagAggregatorFactoryService.CreateTagAggregator<ILanguageElementTag>(wpfTextViewHost.TextView.TextBuffer); ////var manager = LanguageElementManagerService.GetLanguageElementManager(wpfTextViewHost.TextView); ////if (manager == null) //// return null; //return new EditorNavigationMargin(wpfTextViewHost.TextView, tagAggregator, GlyphService); }
private void InsertIntoTextBuffer(IVsTextBuffer document, LibraryInstallationState libraryInstallationState, Manifest manifest) { ITextBuffer textBuffer = GetTextBuffer(document); if (textBuffer != null) { MemberNode libraries = GetLibraries(textBuffer); SortedNodeList <Node> children = JsonHelpers.GetChildren(libraries); if (children.Count > 0) { ArrayNode arrayNode = children.OfType <ArrayNode>().First(); string newLibrary = GetLibraryTextToBeInserted(libraryInstallationState, manifest); bool containsLibrary = arrayNode.BlockChildren.Any(); int insertionIndex = libraries.End - 1; string lineBreakText = GetLineBreakTextFromPreviousLine(textBuffer, insertionIndex); string insertionText; if (containsLibrary) { insertionText = "," + lineBreakText + newLibrary + lineBreakText; } else { insertionText = newLibrary + lineBreakText; } if (insertionIndex > 0) { FormatSelection(textBuffer, insertionIndex, insertionText); } } } }
private void InsertIntoTextBuffer(IVsTextBuffer document, LibraryInstallationState libraryInstallationState) { ITextBuffer textBuffer = GetTextBuffer(document); if (textBuffer != null) { JSONMember libraries = GetLibraries(textBuffer); if (libraries?.Children != null) { string insertionText; JSONArray jsonArray = libraries.Children.OfType <JSONArray>().First(); string newLibrary = GetLibraryToBeInserted(libraryInstallationState); bool containsLibrary = jsonArray.BlockItemChildren.Any(); int insertionIndex = libraries.AfterEnd - 1; string lineBreakText = GetLineBreakTextFromPreviousLine(textBuffer, insertionIndex); if (containsLibrary) { insertionText = "," + lineBreakText + newLibrary + lineBreakText; } else { insertionText = newLibrary + lineBreakText; } if (insertionIndex > 0) { FormatSelection(textBuffer, insertionIndex, insertionText); } } } }
public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string pbstrName, out int piLineOffset) { pbstrName = null; piLineOffset = 0; return VSConstants.E_NOTIMPL; }
public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR ppEnum) { ppEnum = null; return VSConstants.E_NOTIMPL; }
private async Task InstallPackageAsync() { try { bool isLibraryInstallationStateValid = await IsLibraryInstallationStateValidAsync().ConfigureAwait(false); if (isLibraryInstallationStateValid) { ILibrary selectedPackage = SelectedPackage; InstallPackageCommand.CanExecute(null); Manifest manifest = await Manifest.FromFileAsync(_configFileName, _deps, CancellationToken.None).ConfigureAwait(false); string targetPath = _targetPath; if (!string.IsNullOrEmpty(_configFileName)) { Uri configContainerUri = new Uri(_configFileName, UriKind.Absolute); Uri targetUri = new Uri(targetPath, UriKind.Absolute); targetPath = configContainerUri.MakeRelativeUri(targetUri).ToString(); } if (String.IsNullOrEmpty(manifest.Version)) { manifest.Version = Manifest.SupportedVersions.Max().ToString(); } (string name, string version) = LibraryIdToNameAndVersionConverter.Instance.GetLibraryNameAndVersion(PackageId, SelectedProvider.Id); LibraryInstallationState libraryInstallationState = new LibraryInstallationState { Name = name, Version = version, ProviderId = selectedPackage.ProviderId, DestinationPath = InstallationFolder.DestinationFolder, }; _isInstalling = true; // When "Include all files" option is checked, we don't want to write out the files to libman.json. // We will only list the files when user chose to install specific files. if (LibraryFilesToInstall == FileSelectionType.ChooseSpecificFilesToInstall) { libraryInstallationState.Files = SelectedFiles.ToList(); } manifest.AddLibrary(libraryInstallationState); await Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!File.Exists(_configFileName)) { await manifest.SaveAsync(_configFileName, CancellationToken.None); if (_project != null) { await _project.AddFileToProjectAsync(_configFileName); } } RunningDocumentTable rdt = new RunningDocumentTable(Shell.ServiceProvider.GlobalProvider); string configFilePath = Path.GetFullPath(_configFileName); IVsTextBuffer textBuffer = rdt.FindDocument(configFilePath) as IVsTextBuffer; _dispatcher.Invoke(() => { _closeDialog(true); }); // The file isn't open. So we'll write to disk directly if (textBuffer == null) { manifest.AddLibrary(libraryInstallationState); await manifest.SaveAsync(_configFileName, CancellationToken.None).ConfigureAwait(false); Telemetry.TrackUserTask("Invoke-RestoreFromAddClientLibrariesDialog"); await _libraryCommandService.RestoreAsync(_configFileName, CancellationToken.None).ConfigureAwait(false); } else { // libman.json file is open, so we will write to the textBuffer. InsertIntoTextBuffer(textBuffer, libraryInstallationState, manifest); // Save manifest file so we can restore library files. rdt.SaveFileIfDirty(configFilePath); } } } catch (Exception ex) { Telemetry.TrackException(nameof(InstallPackageAsync), ex); } }
public int IsMappedLocation(IVsTextBuffer pBuffer, int iLine, int iCol) { return VSConstants.S_FALSE; }
public int ValidateBreakpointLocation(IVsTextBuffer pBuffer, int iLine, int iCol, TextSpan[] pCodeSpan) { return VSConstants.E_NOTIMPL; }
public int GetLanguageID(IVsTextBuffer pBuffer, int iLine, int iCol, out Guid pguidLanguageID) { pguidLanguageID = typeof(MarkdownLanguageInfo).GUID; return(VSConstants.S_OK); }
public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string pbstrName, out int piLineOffset) { pbstrName = null; piLineOffset = 0; return(VSConstants.E_NOTIMPL); }
public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR ppEnum) { ppEnum = null; return(VSConstants.E_NOTIMPL); }
public int IsMappedLocation(IVsTextBuffer pBuffer, int iLine, int iCol) { return(VSConstants.S_FALSE); }
public int ValidateBreakpointLocation(IVsTextBuffer pBuffer, int iLine, int iCol, TextSpan[] pCodeSpan) { return(VSConstants.E_NOTIMPL); }
public int IsMappedLocation(IVsTextBuffer pBuffer, int iLine, int iCol) { return(VSConstants.E_NOTIMPL); }
public int GetLanguageID(IVsTextBuffer pBuffer, int iLine, int iCol, out Guid pguidLanguageID) { pguidLanguageID = typeof(MarkdownLanguageInfo).GUID; return VSConstants.S_OK; }
private int ValidateBreakpointLocationWorker( IVsTextBuffer pBuffer, int iLine, int iCol, VsTextSpan[] pCodeSpan, CancellationToken cancellationToken) { if (_breakpointService == null) { return(VSConstants.E_FAIL); } var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var snapshot = textBuffer.CurrentSnapshot; Document document = snapshot.AsText().GetDocumentWithFrozenPartialSemanticsAsync(cancellationToken).WaitAndGetResult(cancellationToken); if (document != null) { var point = snapshot.GetPoint(iLine, iCol); var length = 0; if (pCodeSpan != null && pCodeSpan.Length > 0) { // If we have a non-empty span then it means that the debugger is asking us to adjust an // existing span. In Everett we didn't do this so we had some good and some bad // behavior. For example if you had a breakpoint on: "int i;" and you changed it to "int // i = 4;", then the breakpoint wouldn't adjust. That was bad. However, if you had the // breakpoint on an open or close curly brace then it would always "stick" to that brace // which was good. // // So we want to keep the best parts of both systems. We want to appropriately "stick" // to tokens and we also want to adjust spans intelligently. // // However, it turns out the latter is hard to do when there are parse errors in the // code. Things like missing name nodes cause a lot of havoc and make it difficult to // track a closing curly brace. // // So the way we do this is that we default to not intelligently adjusting the spans // while there are parse errors. But when there are no parse errors then the span is // adjusted. var initialBreakpointSpan = snapshot.GetSpan(pCodeSpan[0]); if (initialBreakpointSpan.Length > 0 && document.SupportsSyntaxTree) { var tree = document.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); if (tree.GetDiagnostics(cancellationToken).Any(d => d.Severity == DiagnosticSeverity.Error)) { return(VSConstants.E_FAIL); } } // If a span is provided, and the requested position falls in that span, then just // move the requested position to the start of the span. // Length will be used to determine if we need further analysis, which is only required when text spans multiple lines. if (initialBreakpointSpan.Contains(point)) { point = initialBreakpointSpan.Start; length = pCodeSpan[0].iEndLine > pCodeSpan[0].iStartLine ? initialBreakpointSpan.Length : 0; } } // NOTE(cyrusn): we need to wait here because ValidateBreakpointLocation is // synchronous. In the future, it would be nice for the debugger to provide // an async entry point for this. var breakpoint = _breakpointService.ResolveBreakpointAsync(document, new CodeAnalysis.Text.TextSpan(point.Position, length), cancellationToken).WaitAndGetResult(cancellationToken); if (breakpoint == null) { // There should *not* be a breakpoint here. E_FAIL to let the debugger know // that. return(VSConstants.E_FAIL); } if (breakpoint.IsLineBreakpoint) { // Let the debugger take care of this. They'll put a line breakpoint // here. This is useful for when the user does something like put a // breakpoint in inactive code. We want to allow this as they might // just have different defines during editing versus debugging. // TODO(cyrusn): Do we need to set the pCodeSpan in this case? return(VSConstants.E_NOTIMPL); } // There should be a breakpoint at the location passed back. if (pCodeSpan != null && pCodeSpan.Length > 0) { pCodeSpan[0] = breakpoint.TextSpan.ToSnapshotSpan(snapshot).ToVsTextSpan(); } return(VSConstants.S_OK); } } return(VSConstants.E_NOTIMPL); }
public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string?pbstrName, out int piLineOffset) { using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetNameOfLocation, CancellationToken.None)) { string?name = null; var lineOffset = 0; if (_languageDebugInfo != null) { _uiThreadOperationExecutor.Execute( title: ServicesVSResources.Debugger, defaultDescription: ServicesVSResources.Determining_breakpoint_location, allowCancellation: true, showProgress: false, action: waitContext => { var cancellationToken = waitContext.UserCancellationToken; var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var nullablePoint = textBuffer.CurrentSnapshot.TryGetPoint(iLine, iCol); if (nullablePoint.HasValue) { var point = nullablePoint.Value; var document = point.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { // NOTE(cyrusn): We have to wait here because the debuggers' // GetNameOfLocation is a blocking call. In the future, it // would be nice if they could make it async. _threadingContext.JoinableTaskFactory.Run(async() => { var debugLocationInfo = await _languageDebugInfo.GetLocationInfoAsync(document, point, cancellationToken).ConfigureAwait(false); if (!debugLocationInfo.IsDefault) { name = debugLocationInfo.Name; lineOffset = debugLocationInfo.LineOffset; } }); } } } }); if (name != null) { pbstrName = name; piLineOffset = lineOffset; return(VSConstants.S_OK); } } // Note(DustinCa): Docs say that GetNameOfLocation should return S_FALSE if a name could not be found. // Also, that's what the old native code does, so we should do it here. pbstrName = null; piLineOffset = 0; return(VSConstants.S_FALSE); } }