internal static TestHostDocument CreateDocument( XElement documentElement, ExportProvider exportProvider, HostLanguageServices languageServiceProvider, ImmutableArray <string> roles) { string markupCode = documentElement.NormalizedValue(); var folders = GetFolders(documentElement); var optionsElement = documentElement.Element(ParseOptionsElementName); var codeKind = SourceCodeKind.Regular; if (optionsElement != null) { var attr = optionsElement.Attribute(KindAttributeName); codeKind = attr == null ? SourceCodeKind.Regular : (SourceCodeKind)Enum.Parse(typeof(SourceCodeKind), attr.Value); } MarkupTestFile.GetPositionAndSpans(markupCode, out var code, out var cursorPosition, out IDictionary <string, ImmutableArray <TextSpan> > spans); var documentServiceProvider = GetDocumentServiceProvider(documentElement); return(new TestHostDocument( exportProvider, languageServiceProvider, code, filePath: string.Empty, cursorPosition, spans, codeKind, folders, isLinkFile: false, documentServiceProvider, roles: roles)); }
private static void VerifyResolution(string markup, string[] fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope scope, string language, string rootNamespace) { // Parse out the span containing the declaration of the expected symbol MarkupTestFile.GetPositionAndSpans(markup, out var source, out var pos, out IDictionary <string, ImmutableArray <TextSpan> > spans); Assert.True(pos != null || spans.Count > 0, "Must specify a position or spans marking expected symbols for resolution"); // Get the expected symbol from the given position var syntaxTree = CreateSyntaxTree(source, language); var compilation = CreateCompilation(syntaxTree, language, rootNamespace); var model = compilation.GetSemanticModel(syntaxTree); var expectedSymbols = new List <ISymbol>(); bool shouldResolveSingleSymbol = pos != null; if (shouldResolveSingleSymbol) { expectedSymbols.Add(GetSymbolAtPosition(model, pos.Value)); } else { foreach (var span in spans.Values.First()) { expectedSymbols.Add(GetSymbolAtPosition(model, span.Start)); } } // Resolve the symbol based on each given FxCop fully-qualified name foreach (var fxCopName in fxCopFullyQualifiedNames) { var symbols = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, fxCopName, scope); if (shouldResolveSingleSymbol) { var expectedSymbol = expectedSymbols.Single(); if (symbols.Count() > 1) { Assert.True(false, string.Format("Expected to resolve FxCop fully-qualified name '{0}' to '{1}': got multiple symbols:\r\n{2}", fxCopName, expectedSymbol, string.Join("\r\n", symbols))); } var symbol = symbols.SingleOrDefault(); Assert.True(expectedSymbol == symbol, string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbol '{1}': got '{2}'", fxCopName, expectedSymbol, symbol)); } else { foreach (var symbol in symbols) { Assert.True(expectedSymbols.Contains(symbol), string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbols:\r\n{1}\r\nResolved to unexpected symbol '{2}'", fxCopName, string.Join("\r\n", expectedSymbols), symbol)); } } } }
protected void TestTrivia(string expectedRegionName, string code, SyntaxKind expectedKind, bool autoCollapse) { int caretPosition; IList <TextSpan> spans; MarkupTestFile.GetPositionAndSpans(code, out code, out caretPosition, out spans); var tree = ParseCode(code); var trivia = tree.GetRoot().FindTrivia(caretPosition); var directive = trivia.GetStructure() as TSyntaxNode; Assert.NotNull(directive); Assert.Equal(expectedKind, directive.Kind()); var actualRegions = GetRegions(directive).ToArray(); if (spans.Count == 0) { Assert.Equal(0, actualRegions.Length); return; } Assert.Equal(1, actualRegions.Length); var expectedRegion = new OutliningSpan( spans[0], expectedRegionName, autoCollapse); AssertRegion(expectedRegion, actualRegions[0]); }
protected async Task SetUpEditorAsync(string markupCode, CancellationToken cancellationToken) { MarkupTestFile.GetPositionAndSpans(markupCode, out var code, out int?caretPosition, out var spans); Assert.True(caretPosition.HasValue || spans.ContainsKey("selection"), "Must specify either a caret position ($$) or at least one selection span ({|selection:|})"); await TestServices.Editor.DismissCompletionSessionsAsync(cancellationToken); await TestServices.Editor.DismissLightBulbSessionAsync(cancellationToken); var originalValue = await TestServices.Workspace.IsPrettyListingOnAsync(LanguageName, cancellationToken); await TestServices.Workspace.SetPrettyListingAsync(LanguageName, false, cancellationToken); try { await TestServices.Editor.SetTextAsync(code, cancellationToken); if (caretPosition.HasValue) { await TestServices.Editor.MoveCaretAsync(caretPosition.Value, cancellationToken); } else { await TestServices.Editor.SetMultiSelectionAsync(spans["selection"], cancellationToken); } await TestServices.Editor.ActivateAsync(cancellationToken); } finally { await TestServices.Workspace.SetPrettyListingAsync(LanguageName, originalValue, cancellationToken); } }
protected async Task TestBraceHighlightingAsync( string markup, ParseOptions options = null, bool swapAnglesWithBrackets = false ) { MarkupTestFile.GetPositionAndSpans( markup, out var text, out int cursorPosition, out var expectedSpans ); // needed because markup test file can't support [|[|] to indicate selecting // just an open bracket. if (swapAnglesWithBrackets) { text = text.Replace("<", "[").Replace(">", "]"); } using (var workspace = CreateWorkspace(text, options)) { WpfTestRunner.RequireWpfFact( $"{nameof(AbstractBraceHighlightingTests)}.{nameof(TestBraceHighlightingAsync)} creates asynchronous taggers" ); var provider = new BraceHighlightingViewTaggerProvider( workspace.GetService <IThreadingContext>(), GetBraceMatchingService(workspace), workspace.GetService <IForegroundNotificationService>(), AsynchronousOperationListenerProvider.NullProvider ); var testDocument = workspace.Documents.First(); var buffer = testDocument.GetTextBuffer(); var document = buffer.CurrentSnapshot .GetRelatedDocumentsWithChanges() .FirstOrDefault(); var context = new TaggerContext <BraceHighlightTag>( document, buffer.CurrentSnapshot, new SnapshotPoint(buffer.CurrentSnapshot, cursorPosition) ); await provider.GetTestAccessor().ProduceTagsAsync(context); var expectedHighlights = expectedSpans .Select(ts => ts.ToSpan()) .OrderBy(s => s.Start) .ToList(); var actualHighlights = context.tagSpans .Select(ts => ts.Span.Span) .OrderBy(s => s.Start) .ToList(); Assert.Equal(expectedHighlights, actualHighlights); } }
private static IList <TestHostProject> CreateSubmissions( TestWorkspace workspace, IEnumerable <XElement> submissionElements, ExportProvider exportProvider) { var submissions = new List <TestHostProject>(); var submissionIndex = 0; foreach (var submissionElement in submissionElements) { var submissionName = "Submission" + (submissionIndex++); var languageName = GetLanguage(workspace, submissionElement); // The document var markupCode = submissionElement.NormalizedValue(); string code; int? cursorPosition; IDictionary <string, IList <TextSpan> > spans; MarkupTestFile.GetPositionAndSpans(markupCode, out code, out cursorPosition, out spans); var languageServices = workspace.Services.GetLanguageServices(languageName); var contentTypeLanguageService = languageServices.GetService <IContentTypeLanguageService>(); var contentType = contentTypeLanguageService.GetDefaultContentType(); var textBuffer = EditorFactory.CreateBuffer(contentType.TypeName, exportProvider, code); // The project var document = new TestHostDocument(exportProvider, languageServices, textBuffer, submissionName, cursorPosition, spans, SourceCodeKind.Interactive); var syntaxFactory = languageServices.GetService <ISyntaxTreeFactoryService>(); var compilationFactory = languageServices.GetService <ICompilationFactoryService>(); var compilationOptions = compilationFactory.GetDefaultCompilationOptions().WithOutputKind(OutputKind.DynamicallyLinkedLibrary); var parseOptions = syntaxFactory.GetDefaultParseOptions().WithKind(SourceCodeKind.Interactive); var references = CreateCommonReferences(workspace, submissionElement); var project = new TestHostProject( languageServices, compilationOptions, parseOptions, submissionName, references, new List <TestHostDocument> { document }, isSubmission: true); submissions.Add(project); } return(submissions); }
private async Task TestSignatureHelpWorkerAsync( string markupWithPositionAndOptSpan, SourceCodeKind sourceCodeKind, bool experimental, IEnumerable <SignatureHelpTestItem> expectedOrderedItemsOrNull = null, bool usePreviousCharAsTrigger = false) { markupWithPositionAndOptSpan = markupWithPositionAndOptSpan.NormalizeLineEndings(); string code; int cursorPosition; IList <TextSpan> textSpans; TextSpan? textSpan = null; MarkupTestFile.GetPositionAndSpans( markupWithPositionAndOptSpan, out code, out cursorPosition, out textSpans); if (textSpans.Any()) { textSpan = textSpans.First(); } var parseOptions = CreateExperimentalParseOptions(); // regular var document1 = await workspaceFixture.UpdateDocumentAsync(code, sourceCodeKind); if (experimental) { document1 = document1.Project.WithParseOptions(parseOptions).GetDocument(document1.Id); } await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, sourceCodeKind, document1, textSpan, expectedOrderedItemsOrNull, usePreviousCharAsTrigger); // speculative semantic model if (await CanUseSpeculativeSemanticModelAsync(document1, cursorPosition)) { var document2 = await workspaceFixture.UpdateDocumentAsync(code, sourceCodeKind, cleanBeforeUpdate : false); if (experimental) { document2 = document2.Project.WithParseOptions(parseOptions).GetDocument(document2.Id); } await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, sourceCodeKind, document2, textSpan, expectedOrderedItemsOrNull, usePreviousCharAsTrigger); } }
private static async Task TestAsync(string markup, string output) { MarkupTestFile.GetPositionAndSpans(markup, out var text, out var cursorPosition, out IDictionary <string, ImmutableArray <TextSpan> > placeholderDictionary); var stringSpan = placeholderDictionary[""].First(); var textChange = new TextChange(new TextSpan(stringSpan.Start, 0), text.Substring(stringSpan.Start, stringSpan.Length)); var placeholders = GetSnippetPlaceholders(text, placeholderDictionary); using var workspace = CreateWorkspaceFromCode(markup); var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id); var lspSnippetString = await RoslynLSPSnippetConverter.GenerateLSPSnippetAsync(document, cursorPosition !.Value, placeholders, textChange, stringSpan.Start, CancellationToken.None).ConfigureAwait(false); AssertEx.EqualOrDiff(output, lspSnippetString); }
internal void AssertCodeIs(string expectedCode) { MarkupTestFile.GetPositionAndSpans(expectedCode, out var massaged, out int?caretPosition, out var spans); Assert.Equal(massaged, TextView.TextSnapshot.GetText()); Assert.Equal(caretPosition !.Value, TextView.Caret.Position.BufferPosition.Position); var virtualSpaces = spans.SingleOrDefault(kvp => kvp.Key.StartsWith("VirtualSpaces#")); if (virtualSpaces.Key != null) { var virtualOffset = int.Parse(virtualSpaces.Key.Substring("VirtualSpaces-".Length)); Assert.True(TextView.Caret.InVirtualSpace); Assert.Equal(virtualOffset, TextView.Caret.Position.VirtualBufferPosition.VirtualSpaces); } }
private static TestHostDocument CreateDocument( TestWorkspace workspace, XElement workspaceElement, XElement documentElement, string language, ExportProvider exportProvider, HostLanguageServices languageServiceProvider, Dictionary <string, ITextBuffer> filePathToTextBufferMap, ref int documentId) { string markupCode; string filePath; var isLinkFileAttribute = documentElement.Attribute(IsLinkFileAttributeName); bool isLinkFile = isLinkFileAttribute != null && ((bool?)isLinkFileAttribute).HasValue && ((bool?)isLinkFileAttribute).Value; if (isLinkFile) { // This is a linked file. Use the filePath and markup from the referenced document. var originalProjectName = documentElement.Attribute(LinkAssemblyNameAttributeName); var originalDocumentPath = documentElement.Attribute(LinkFilePathAttributeName); if (originalProjectName == null || originalDocumentPath == null) { throw new ArgumentException("Linked file specified without LinkAssemblyName or LinkFilePath."); } var originalProjectNameStr = originalProjectName.Value; var originalDocumentPathStr = originalDocumentPath.Value; var originalProject = workspaceElement.Elements(ProjectElementName).First(p => { var assemblyName = p.Attribute(AssemblyNameAttributeName); return(assemblyName != null && assemblyName.Value == originalProjectNameStr); }); if (originalProject == null) { throw new ArgumentException("Linked file's LinkAssemblyName '{0}' project not found.", originalProjectNameStr); } var originalDocument = originalProject.Elements(DocumentElementName).First(d => { var documentPath = d.Attribute(FilePathAttributeName); return(documentPath != null && documentPath.Value == originalDocumentPathStr); }); if (originalDocument == null) { throw new ArgumentException("Linked file's LinkFilePath '{0}' file not found.", originalDocumentPathStr); } markupCode = originalDocument.NormalizedValue(); filePath = GetFilePath(workspace, originalDocument, ref documentId); } else { markupCode = documentElement.NormalizedValue(); filePath = GetFilePath(workspace, documentElement, ref documentId); } var folders = GetFolders(documentElement); var optionsElement = documentElement.Element(ParseOptionsElementName); // TODO: Allow these to be specified. var codeKind = SourceCodeKind.Regular; if (optionsElement != null) { var attr = optionsElement.Attribute(KindAttributeName); codeKind = attr == null ? SourceCodeKind.Regular : (SourceCodeKind)Enum.Parse(typeof(SourceCodeKind), attr.Value); } var contentTypeLanguageService = languageServiceProvider.GetService <IContentTypeLanguageService>(); var contentType = contentTypeLanguageService.GetDefaultContentType(); string code; int? cursorPosition; IDictionary <string, IList <TextSpan> > spans; MarkupTestFile.GetPositionAndSpans(markupCode, out code, out cursorPosition, out spans); // For linked files, use the same ITextBuffer for all linked documents ITextBuffer textBuffer; if (!filePathToTextBufferMap.TryGetValue(filePath, out textBuffer)) { textBuffer = EditorFactory.CreateBuffer(contentType.TypeName, exportProvider, code); filePathToTextBufferMap.Add(filePath, textBuffer); } return(new TestHostDocument(exportProvider, languageServiceProvider, textBuffer, filePath, cursorPosition, spans, codeKind, folders, isLinkFile)); }
private static void GetSpansAndCaretFromSurfaceBufferMarkup( string markup, IList <TestHostDocument> baseDocuments, out IList <object> projectionBufferSpans, out Dictionary <string, ImmutableArray <TextSpan> > mappedMarkupSpans, out int?mappedCaretLocation) { projectionBufferSpans = new List <object>(); var projectionBufferSpanStartingPositions = new List <int>(); mappedCaretLocation = null; MarkupTestFile.GetPositionAndSpans(markup, out var inertText, out int?markupCaretLocation, out var markupSpans); var namedSpans = markupSpans.Where(kvp => kvp.Key != string.Empty); var sortedAndNamedSpans = namedSpans.OrderBy(kvp => kvp.Value.Single().Start) .ThenBy(kvp => markup.IndexOf("{|" + kvp.Key + ":", StringComparison.Ordinal)); var currentPositionInInertText = 0; var currentPositionInProjectionBuffer = 0; // If the markup points to k spans, these k spans divide the inert text into k + 1 // possibly empty substrings. When handling each span, also handle the inert text that // immediately precedes it. At the end, handle the trailing inert text foreach (var spanNameToListMap in sortedAndNamedSpans) { var spanName = spanNameToListMap.Key; var spanLocation = spanNameToListMap.Value.Single().Start; // Get any inert text between this and the previous span if (currentPositionInInertText < spanLocation) { var textToAdd = inertText.Substring(currentPositionInInertText, spanLocation - currentPositionInInertText); projectionBufferSpans.Add(textToAdd); projectionBufferSpanStartingPositions.Add(currentPositionInProjectionBuffer); // If the caret is in the markup and in this substring, calculate the final // caret location if (mappedCaretLocation == null && markupCaretLocation != null && currentPositionInInertText + textToAdd.Length >= markupCaretLocation) { var caretOffsetInCurrentText = markupCaretLocation.Value - currentPositionInInertText; mappedCaretLocation = currentPositionInProjectionBuffer + caretOffsetInCurrentText; } currentPositionInInertText += textToAdd.Length; currentPositionInProjectionBuffer += textToAdd.Length; } // Find and insert the span from the corresponding document var documentWithSpan = baseDocuments.FirstOrDefault(d => d.AnnotatedSpans.ContainsKey(spanName)); if (documentWithSpan == null) { continue; } markupSpans.Remove(spanName); var matchingSpan = documentWithSpan.AnnotatedSpans[spanName].Single(); var span = new Span(matchingSpan.Start, matchingSpan.Length); var trackingSpan = documentWithSpan.GetTextBuffer().CurrentSnapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeExclusive); projectionBufferSpans.Add(trackingSpan); projectionBufferSpanStartingPositions.Add(currentPositionInProjectionBuffer); // If the caret is not in markup but is in this span, then calculate the final // caret location. Note - if we find the caret marker in this document, then // we DO want to map it up, even if it's at the end of the span for this document. // This is not ambiguous for us, since we have explicit delimiters between the buffer // so it's clear which document the caret is in. if (mappedCaretLocation == null && markupCaretLocation == null && documentWithSpan.CursorPosition.HasValue && (matchingSpan.Contains(documentWithSpan.CursorPosition.Value) || matchingSpan.End == documentWithSpan.CursorPosition.Value)) { var caretOffsetInSpan = documentWithSpan.CursorPosition.Value - matchingSpan.Start; mappedCaretLocation = currentPositionInProjectionBuffer + caretOffsetInSpan; } currentPositionInProjectionBuffer += matchingSpan.Length; } // Handle any inert text after the final projected span if (currentPositionInInertText < inertText.Length - 1) { projectionBufferSpans.Add(inertText.Substring(currentPositionInInertText)); projectionBufferSpanStartingPositions.Add(currentPositionInProjectionBuffer); if (mappedCaretLocation == null && markupCaretLocation != null && markupCaretLocation >= currentPositionInInertText) { var caretOffsetInCurrentText = markupCaretLocation.Value - currentPositionInInertText; mappedCaretLocation = currentPositionInProjectionBuffer + caretOffsetInCurrentText; } } MapMarkupSpans(markupSpans, out mappedMarkupSpans, projectionBufferSpans, projectionBufferSpanStartingPositions); }
private static TestHostDocument CreateDocument( TestWorkspace workspace, XElement workspaceElement, XElement documentElement, string language, ExportProvider exportProvider, HostLanguageServices languageServiceProvider, Dictionary <string, ITextBuffer> filePathToTextBufferMap, IDocumentServiceProvider documentServiceProvider, ref int documentId) { string markupCode; string filePath; var isLinkFileAttribute = documentElement.Attribute(IsLinkFileAttributeName); var isLinkFile = isLinkFileAttribute != null && ((bool?)isLinkFileAttribute).HasValue && ((bool?)isLinkFileAttribute).Value; if (isLinkFile) { // This is a linked file. Use the filePath and markup from the referenced document. var originalAssemblyName = documentElement.Attribute(LinkAssemblyNameAttributeName)?.Value; var originalProjectName = documentElement.Attribute(LinkProjectNameAttributeName)?.Value; if (originalAssemblyName == null && originalProjectName == null) { throw new ArgumentException($"Linked files must specify either a {LinkAssemblyNameAttributeName} or {LinkProjectNameAttributeName}"); } var originalProject = workspaceElement.Elements(ProjectElementName).FirstOrDefault(p => { if (originalAssemblyName != null) { return(p.Attribute(AssemblyNameAttributeName)?.Value == originalAssemblyName); } else { return(p.Attribute(ProjectNameAttribute)?.Value == originalProjectName); } }); if (originalProject == null) { if (originalProjectName != null) { throw new ArgumentException($"Linked file's {LinkProjectNameAttributeName} '{originalProjectName}' project not found."); } else { throw new ArgumentException($"Linked file's {LinkAssemblyNameAttributeName} '{originalAssemblyName}' project not found."); } } var originalDocumentPath = documentElement.Attribute(LinkFilePathAttributeName)?.Value; if (originalDocumentPath == null) { throw new ArgumentException($"Linked files must specify a {LinkFilePathAttributeName}"); } documentElement = originalProject.Elements(DocumentElementName).FirstOrDefault(d => { return(d.Attribute(FilePathAttributeName)?.Value == originalDocumentPath); }); if (documentElement == null) { throw new ArgumentException($"Linked file's LinkFilePath '{originalDocumentPath}' file not found."); } } markupCode = documentElement.NormalizedValue(); filePath = GetFilePath(workspace, documentElement, ref documentId); var folders = GetFolders(documentElement); var optionsElement = documentElement.Element(ParseOptionsElementName); // TODO: Allow these to be specified. var codeKind = SourceCodeKind.Regular; if (optionsElement != null) { var attr = optionsElement.Attribute(KindAttributeName); codeKind = attr == null ? SourceCodeKind.Regular : (SourceCodeKind)Enum.Parse(typeof(SourceCodeKind), attr.Value); } var contentTypeLanguageService = languageServiceProvider.GetService <IContentTypeLanguageService>(); var contentType = contentTypeLanguageService.GetDefaultContentType(); MarkupTestFile.GetPositionAndSpans(markupCode, out var code, out var cursorPosition, out IDictionary <string, ImmutableArray <TextSpan> > spans); var testDocumentServiceProvider = GetDocumentServiceProvider(documentElement); if (documentServiceProvider == null) { documentServiceProvider = testDocumentServiceProvider; } else if (testDocumentServiceProvider != null) { AssertEx.Fail($"The document attributes on file {filePath} conflicted"); } return(new TestHostDocument( exportProvider, languageServiceProvider, code, filePath, cursorPosition, spans, codeKind, folders, isLinkFile, documentServiceProvider)); }
private static IList <TestHostProject> CreateSubmissions( TestWorkspace workspace, IEnumerable <XElement> submissionElements, ExportProvider exportProvider) { var submissions = new List <TestHostProject>(); var submissionIndex = 0; foreach (var submissionElement in submissionElements) { var submissionName = "Submission" + (submissionIndex++); var languageName = GetLanguage(workspace, submissionElement); // The document var markupCode = submissionElement.NormalizedValue(); MarkupTestFile.GetPositionAndSpans(markupCode, out var code, out var cursorPosition, out IDictionary <string, ImmutableArray <TextSpan> > spans); var languageServices = workspace.Services.GetLanguageServices(languageName); // The project var document = new TestHostDocument(exportProvider, languageServices, code, submissionName, cursorPosition, spans, SourceCodeKind.Script); var documents = new List <TestHostDocument> { document }; if (languageName == NoCompilationConstants.LanguageName) { submissions.Add( new TestHostProject( languageServices, compilationOptions: null, parseOptions: null, assemblyName: submissionName, projectName: submissionName, references: null, documents: documents, isSubmission: true)); continue; } var syntaxFactory = languageServices.GetService <ISyntaxTreeFactoryService>(); var compilationFactory = languageServices.GetService <ICompilationFactoryService>(); var compilationOptions = compilationFactory.GetDefaultCompilationOptions().WithOutputKind(OutputKind.DynamicallyLinkedLibrary); var parseOptions = syntaxFactory.GetDefaultParseOptions().WithKind(SourceCodeKind.Script); var references = CreateCommonReferences(workspace, submissionElement); var project = new TestHostProject( languageServices, compilationOptions, parseOptions, submissionName, submissionName, references, documents, isSubmission: true); submissions.Add(project); } return(submissions); }
private static TestHostProject CreateProject( XElement workspaceElement, XElement projectElement, ExportProvider exportProvider, TestWorkspace workspace, IDocumentServiceProvider documentServiceProvider, ref int projectId, ref int documentId) { AssertNoChildText(projectElement); var language = GetLanguage(workspace, projectElement); var assemblyName = GetAssemblyName(workspace, projectElement, ref projectId); string filePath; var projectName = projectElement.Attribute(ProjectNameAttribute)?.Value ?? assemblyName; if (projectElement.Attribute(FilePathAttributeName) != null) { filePath = projectElement.Attribute(FilePathAttributeName).Value; if (string.Compare(filePath, NullFilePath, StringComparison.Ordinal) == 0) { // allow explicit null file path filePath = null; } } else { filePath = projectName + (language == LanguageNames.CSharp ? ".csproj" : language == LanguageNames.VisualBasic ? ".vbproj" : ("." + language)); } var languageServices = workspace.Services.GetLanguageServices(language); var parseOptions = GetParseOptions(projectElement, language, languageServices); var compilationOptions = CreateCompilationOptions(workspace, projectElement, language, parseOptions); var rootNamespace = GetRootNamespace(workspace, compilationOptions, projectElement); var references = CreateReferenceList(workspace, projectElement); var analyzers = CreateAnalyzerList(projectElement); var documents = new List <TestHostDocument>(); var documentElements = projectElement.Elements(DocumentElementName).ToList(); foreach (var documentElement in documentElements) { var document = CreateDocument( workspace, workspaceElement, documentElement, exportProvider, languageServices, documentServiceProvider, ref documentId); documents.Add(document); } foreach (var sourceGeneratedDocumentElement in projectElement.Elements(DocumentFromSourceGeneratorElementName)) { var name = GetFileName(workspace, sourceGeneratedDocumentElement, ref documentId); var markupCode = sourceGeneratedDocumentElement.NormalizedValue(); MarkupTestFile.GetPositionAndSpans(markupCode, out var code, out var cursorPosition, out IDictionary <string, ImmutableArray <TextSpan> > spans); var documentFilePath = typeof(SingleFileTestGenerator).Assembly.GetName().Name + '\\' + typeof(SingleFileTestGenerator).FullName + '\\' + name; var document = new TestHostDocument(exportProvider, languageServices, code, name, documentFilePath, cursorPosition, spans, isSourceGenerated: true); documents.Add(document); analyzers.Add(new TestGeneratorReference(new SingleFileTestGenerator(code, name))); } var additionalDocuments = new List <TestHostDocument>(); var additionalDocumentElements = projectElement.Elements(AdditionalDocumentElementName).ToList(); foreach (var additionalDocumentElement in additionalDocumentElements) { var document = CreateDocument( workspace, workspaceElement, additionalDocumentElement, exportProvider, languageServices, documentServiceProvider, ref documentId); additionalDocuments.Add(document); } var analyzerConfigDocuments = new List <TestHostDocument>(); var analyzerConfigElements = projectElement.Elements(AnalyzerConfigDocumentElementName).ToList(); foreach (var analyzerConfigElement in analyzerConfigElements) { var document = CreateDocument( workspace, workspaceElement, analyzerConfigElement, exportProvider, languageServices, documentServiceProvider, ref documentId); analyzerConfigDocuments.Add(document); } return(new TestHostProject(languageServices, compilationOptions, parseOptions, assemblyName, projectName, references, documents, additionalDocuments, analyzerConfigDocuments, filePath: filePath, analyzerReferences: analyzers, defaultNamespace: rootNamespace)); }