private DiagnosticData TryCreateDocumentDiagnosticItem(ExternalError error)
        {
            var documentId = TryGetDocumentId(error.bstrFileName);

            if (documentId == null)
            {
                return(null);
            }

            var line   = error.iLine;
            var column = error.iCol;

            // something we should move to document service one day. but until then, we keep the old way.
            // build basically output error location on surface buffer and we map it back to
            // subject buffer for contained document. so that contained document can map
            // it back to surface buffer when navigate. whole problem comes in due to the mapped span.
            // unlike live error, build outputs mapped span and we save it as original span (since we
            // have no idea whether it is mapped or not). for contained document case, we do know it is
            // mapped span, so we calculate original span and put that in original span.
            var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

            if (containedDocument != null)
            {
                var span = new TextSpan
                {
                    iStartLine  = line,
                    iStartIndex = column,
                    iEndLine    = line,
                    iEndIndex   = column,
                };

                var spans = new TextSpan[1];
                Marshal.ThrowExceptionForHR(containedDocument.BufferCoordinator.MapPrimaryToSecondarySpan(
                                                span,
                                                spans));

                line   = spans[0].iStartLine;
                column = spans[0].iStartIndex;
            }

            // save error line/column (surface buffer location) as mapped line/column so that we can display
            // right location on closed Venus file.
            return(GetDiagnosticData(
                       documentId,
                       _projectId,
                       GetErrorId(error),
                       message: error.bstrText,
                       GetDiagnosticSeverity(error),
                       _language,
                       mappedFilePath: null,
                       mappedStartLine: error.iLine,
                       mappedStartColumn: error.iCol,
                       mappedEndLine: error.iLine,
                       mappedEndColumn: error.iCol,
                       originalFilePath: error.bstrFileName,
                       originalStartLine: line,
                       originalStartColumn: column,
                       originalEndLine: line,
                       originalEndColumn: column));
        }
Beispiel #2
0
        public AbstractFormattingRule CreateRule(ParsedDocument document, int position)
        {
            var containedDocument = ContainedDocument.TryGetContainedDocument(document.Id);

            if (containedDocument == null)
            {
                return(NoOpFormattingRule.Instance);
            }

            var textContainer = document.Text.Container;

            if (textContainer.TryGetTextBuffer() is not IProjectionBuffer)
            {
                return(NoOpFormattingRule.Instance);
            }

            using var pooledObject = SharedPools.Default <List <TextSpan> >().GetPooledObject();
            var spans = pooledObject.Object;

            var root = document.Root;
            var text = document.Text;

            spans.AddRange(containedDocument.GetEditorVisibleSpans());

            for (var i = 0; i < spans.Count; i++)
            {
                var visibleSpan = spans[i];
                if (visibleSpan.IntersectsWith(position) || visibleSpan.End == position)
                {
                    return(containedDocument.GetBaseIndentationRule(root, text, spans, i));
                }
            }

            // in razor (especially in @helper tag), it is possible for us to be asked for next line of visible span
            var line = text.Lines.GetLineFromPosition(position);

            if (line.LineNumber > 0)
            {
                line = text.Lines[line.LineNumber - 1];

                // find one that intersects with previous line
                for (var i = 0; i < spans.Count; i++)
                {
                    var visibleSpan = spans[i];
                    if (visibleSpan.IntersectsWith(line.Span))
                    {
                        return(containedDocument.GetBaseIndentationRule(root, text, spans, i));
                    }
                }
            }

            FatalError.ReportAndCatch(
                new InvalidOperationException($"Can't find an intersection. Visible spans count: {spans.Count}"));

            return(NoOpFormattingRule.Instance);
        }
        private bool AllowsReadOnly(DocumentId documentId)
        {
            // All documents of regular running projects are read-only until the debugger breaks the app.
            // However, ASP.NET doesn’t want its views (aspx, cshtml, or vbhtml) to be read-only, so they can be editable
            // while the code is running and get refreshed next time the web page is hit.

            // Note that Razor-like views are modelled as a ContainedDocument
            var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

            return(containedDocument == null);
        }
        public bool SupportsRename(ITextBuffer textBuffer)
        {
            var sourceTextContainer = textBuffer.AsTextContainer();

            if (Workspace.TryGetWorkspace(sourceTextContainer, out var workspace))
            {
                return(workspace.GetRelatedDocumentIds(sourceTextContainer)
                       .Select(id => ContainedDocument.TryGetContainedDocument(id))
                       .All(cd => cd == null || cd.SupportsRename));
            }

            return(false);
        }
        public static bool TryGetContainedDocument(DocumentId documentId, out VSTypeScriptContainedDocumentWrapper document)
        {
            // TypeScript only calls this to immediately check if the document is a ContainedDocument. Because of that we can just check for
            // ContainedDocuments
            var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

            if (containedDocument != null)
            {
                document = new VSTypeScriptContainedDocumentWrapper(containedDocument);
                return(true);
            }

            document = default;
            return(false);
        }
        private static ContainedDocument GetContainedDocument(ITextBuffer textBuffer)
        {
            var sourceTextContainer = textBuffer.AsTextContainer();

            if (Workspace.TryGetWorkspace(sourceTextContainer, out var workspace) &&
                workspace is VisualStudioWorkspaceImpl vsWorkspace)
            {
                var id = vsWorkspace.GetDocumentIdInCurrentContext(sourceTextContainer);
                if (id != null)
                {
                    return(ContainedDocument.TryGetContainedDocument(id));
                }
            }

            return(null);
        }
Beispiel #7
0
            public bool TryGetTextUndoHistory(Workspace editorWorkspace, ITextBuffer textBuffer, out ITextUndoHistory undoHistory)
            {
                switch (editorWorkspace)
                {
                case VisualStudioWorkspaceImpl:

                    // TODO: Handle undo if context changes
                    var documentId = editorWorkspace.GetDocumentIdInCurrentContext(textBuffer.AsTextContainer());
                    if (documentId == null)
                    {
                        undoHistory = null;
                        return(false);
                    }

                    // In the Visual Studio case, there might be projection buffers involved for Venus,
                    // where we associate undo history with the surface buffer and not the subject buffer.
                    var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

                    if (containedDocument != null)
                    {
                        textBuffer = containedDocument.DataBuffer;
                    }

                    break;

                case MiscellaneousFilesWorkspace _:

                    // Nothing to do in this case: textBuffer is correct!

                    break;

                default:

                    undoHistory = null;
                    return(false);
                }

                return(_undoHistoryRegistry.TryGetHistory(textBuffer, out undoHistory));
            }
Beispiel #8
0
        public IEnumerable <TextChange> FilterFormattedChanges(DocumentId documentId, TextSpan span, IList <TextChange> changes)
        {
            var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

            if (containedDocument == null)
            {
                return(changes);
            }

            // in case of a Venus, when format document command is issued, Venus will call format API with each script block spans.
            // in that case, we need to make sure formatter doesn't overstep other script blocks content. in actual format selection case,
            // we need to format more than given selection otherwise, we will not adjust indentation of first token of the given selection.
            foreach (var visibleSpan in containedDocument.GetEditorVisibleSpans())
            {
                if (visibleSpan != span)
                {
                    continue;
                }

                return(changes.Where(c => span.IntersectsWith(c.Span)));
            }

            return(changes);
        }
Beispiel #9
0
        public static async Task <VsTextSpan?> MapSpanFromSecondaryBufferToPrimaryBufferAsync(
            this VsTextSpan spanInSecondaryBuffer,
            IThreadingContext threadingContext,
            DocumentId documentId,
            CancellationToken cancellationToken)
        {
            var containedDocument = ContainedDocument.TryGetContainedDocument(documentId);

            if (containedDocument == null)
            {
                return(null);
            }

            await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            var bufferCoordinator = containedDocument.BufferCoordinator;

            var primary = new VsTextSpan[1];
            var hresult = bufferCoordinator.MapSecondaryToPrimarySpan(spanInSecondaryBuffer, primary);

            var result = primary[0];

            return(ErrorHandler.Succeeded(hresult) ? result : null);
        }
Beispiel #10
0
 public bool CanPreview(Document document)
 => ContainedDocument.TryGetContainedDocument(document.Id) == null;
 public VSTypeScriptContainedDocumentWrapper(ContainedDocument underlyingObject)
 => _underlyingObject = underlyingObject;
Beispiel #12
0
 private static bool SupportsRenameWorker(ImmutableArray <DocumentId> ids)
 {
     return(ids.Select(id => ContainedDocument.TryGetContainedDocument(id))
            .All(cd => cd == null || cd.SupportsRename));
 }
Beispiel #13
0
 private static bool SupportsRefactoringsWorker(DocumentId id)
 => ContainedDocument.TryGetContainedDocument(id) == null;
Beispiel #14
0
 private static bool SupportsCodeFixesWorker(DocumentId id)
 => ContainedDocument.TryGetContainedDocument(id) == null;
Beispiel #15
0
 private static bool SupportsNavigationToAnyPositionWorker(DocumentId id)
 => ContainedDocument.TryGetContainedDocument(id) == null;
        public bool TryGetProjectId(IVsHierarchyItem hierarchyItem, string targetFrameworkMoniker, out ProjectId projectId)
        {
            // A project node is represented in two different hierarchies: the solution's IVsHierarchy (where it is a leaf node)
            // and the project's own IVsHierarchy (where it is the root node). The IVsHierarchyItem joins them together for the
            // purpose of creating the tree displayed in Solution Explorer. The project's hierarchy is what is passed from the
            // project system to the language service, so that's the one the one to query here. To do that we need to get
            // the "nested" hierarchy from the IVsHierarchyItem.
            var nestedHierarchy   = hierarchyItem.HierarchyIdentity.NestedHierarchy;
            var nestedHierarchyId = hierarchyItem.HierarchyIdentity.NestedItemID;

            if (!nestedHierarchy.TryGetCanonicalName(nestedHierarchyId, out string nestedCanonicalName) ||
                !nestedHierarchy.TryGetItemName(nestedHierarchyId, out string nestedName))
            {
                projectId = default(ProjectId);
                return(false);
            }

            // First filter the projects by matching up properties on the input hierarchy against properties on each
            // project's hierarchy.
            var candidateProjects = _workspace.CurrentSolution.Projects
                                    .Where(p =>
            {
                // We're about to access various properties of the IVsHierarchy associated with the project.
                // The properties supported and the interpretation of their values varies from one project system
                // to another. This code is designed with C# and VB in mind, so we need to filter out everything
                // else.
                if (p.Language != LanguageNames.CSharp &&
                    p.Language != LanguageNames.VisualBasic)
                {
                    return(false);
                }

                // Here we try to match the hierarchy from Solution Explorer to a hierarchy from the Roslyn project.
                // The canonical name of a hierarchy item must be unique _within_ an hierarchy, but since we're
                // examining multiple hierarchies the canonical name could be the same. Indeed this happens when two
                // project files are in the same folder--they both use the full path to the _folder_ as the canonical
                // name. To distinguish them we also examine the "regular" name, which will necessarily be different
                // if the two projects are in the same folder.
                // Note that if a project has been loaded with Lightweight Solution Load it won't even have a
                // hierarchy, so we need to check for null first.
                var hierarchy = _workspace.GetHierarchy(p.Id);

                if (hierarchy != null &&
                    hierarchy.TryGetCanonicalName((uint)VSConstants.VSITEMID.Root, out string projectCanonicalName) &&
                    hierarchy.TryGetItemName((uint)VSConstants.VSITEMID.Root, out string projectName) &&
                    projectCanonicalName.Equals(nestedCanonicalName, System.StringComparison.OrdinalIgnoreCase) &&
                    projectName.Equals(nestedName))
                {
                    if (targetFrameworkMoniker == null)
                    {
                        return(true);
                    }

                    return(hierarchy.TryGetTargetFrameworkMoniker((uint)VSConstants.VSITEMID.Root, out string projectTargetFrameworkMoniker) &&
                           projectTargetFrameworkMoniker.Equals(targetFrameworkMoniker));
                }

                return(false);
            })
                                    .ToArray();

            // If we only have one candidate then no further checks are required.
            if (candidateProjects.Length == 1)
            {
                projectId = candidateProjects[0].Id;
                return(true);
            }

            // If we have multiple candidates then we might be dealing with Web Application Projects. In this case
            // there will be one main project plus one project for each open aspx/cshtml/vbhtml file, all with
            // identical properties on their hierarchies. We can find the main project by taking the first project
            // without a ContainedDocument.
            foreach (var candidateProject in candidateProjects)
            {
                if (!candidateProject.DocumentIds.Any(id => ContainedDocument.TryGetContainedDocument(id) != null))
                {
                    projectId = candidateProject.Id;
                    return(true);
                }
            }

            projectId = default(ProjectId);
            return(false);
        }
Beispiel #17
0
 private static bool IsContainedDocument(DocumentId documentId)
 => ContainedDocument.TryGetContainedDocument(documentId) != null;