public void TestProperties() { var projectId = ProjectId.CreateNewId(); var documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectId), "doc"); var instance = ProjectInfo.Create( name: "Name", id: ProjectId.CreateNewId(), version: VersionStamp.Default, assemblyName: "AssemblyName", language: "C#" ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithVersion(value), opt => opt.Version, VersionStamp.Create() ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithName(value), opt => opt.Name, "New", defaultThrows: true ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithAssemblyName(value), opt => opt.AssemblyName, "New", defaultThrows: true ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithFilePath(value), opt => opt.FilePath, "New" ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithOutputFilePath(value), opt => opt.OutputFilePath, "New" ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithOutputRefFilePath(value), opt => opt.OutputRefFilePath, "New" ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithCompilationOutputInfo(value), opt => opt.CompilationOutputInfo, new CompilationOutputInfo("NewPath") ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithDefaultNamespace(value), opt => opt.DefaultNamespace, "New" ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithHasAllInformation(value), opt => opt.HasAllInformation, true ); SolutionTestHelpers.TestProperty( instance, (old, value) => old.WithRunAnalyzers(value), opt => opt.RunAnalyzers, true ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithDocuments(value), opt => opt.Documents, documentInfo, allowDuplicates: false ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithAdditionalDocuments(value), opt => opt.AdditionalDocuments, documentInfo, allowDuplicates: false ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithAnalyzerConfigDocuments(value), opt => opt.AnalyzerConfigDocuments, documentInfo, allowDuplicates: false ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithAnalyzerReferences(value), opt => opt.AnalyzerReferences, (AnalyzerReference) new TestAnalyzerReference(), allowDuplicates: false ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithMetadataReferences(value), opt => opt.MetadataReferences, (MetadataReference) new TestMetadataReference(), allowDuplicates: false ); SolutionTestHelpers.TestListProperty( instance, (old, value) => old.WithProjectReferences(value), opt => opt.ProjectReferences, new ProjectReference(projectId), allowDuplicates: false ); }
public static async Task <IEnumerable <ModifiedFileResponse> > GetFileChangesAsync(Solution newSolution, Solution oldSolution, string newFileDirectory, bool wantTextChanges) { var changes = new Dictionary <string, ModifiedFileResponse>(); var solutionChanges = newSolution.GetChanges(oldSolution); foreach (var projectChange in solutionChanges.GetProjectChanges()) { foreach (var changedDocumentId in projectChange.GetAddedDocuments()) { var document = newSolution.GetDocument(changedDocumentId); var source = await document.GetTextAsync(); var modifiedFileResponse = new ModifiedFileResponse(document.Name); var change = new LinePositionSpanTextChange(); change.NewText = source.ToString(); var newPath = Path.Combine(newFileDirectory, document.Name); modifiedFileResponse.FileName = newPath; modifiedFileResponse.Changes = new[] { change }; changes[newPath] = modifiedFileResponse; // This is a little weird. The added document doesn't have a filepath // and we need one so that future operations on this document work var id = DocumentId.CreateNewId(document.Project.Id); var version = VersionStamp.Create(); var documentInfo = DocumentInfo.Create(id, document.Name, filePath: newPath, loader: TextLoader.From(TextAndVersion.Create(source, version))); var workspace = newSolution.Workspace as OmnisharpWorkspace; workspace.RemoveDocument(changedDocumentId); workspace.AddDocument(documentInfo); } foreach (var changedDocumentId in projectChange.GetChangedDocuments()) { var changedDocument = newSolution.GetDocument(changedDocumentId); ModifiedFileResponse modifiedFileResponse; var filePath = changedDocument.FilePath; if (!changes.TryGetValue(filePath, out modifiedFileResponse)) { modifiedFileResponse = new ModifiedFileResponse(filePath); changes[filePath] = modifiedFileResponse; } if (!wantTextChanges) { var changedText = await changedDocument.GetTextAsync(); modifiedFileResponse.Buffer = changedText.ToString(); } else { var originalDocument = oldSolution.GetDocument(changedDocumentId); IEnumerable <TextChange> textChanges; textChanges = await changedDocument.GetTextChangesAsync(originalDocument); var linePositionSpanTextChanges = await LinePositionSpanTextChange.Convert(originalDocument, textChanges); modifiedFileResponse.Changes = modifiedFileResponse.Changes != null ? modifiedFileResponse.Changes.Union(linePositionSpanTextChanges) : linePositionSpanTextChanges; } } } return(changes.Values); }
internal void VerifySemantics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription?activeStatements = null, IEnumerable <string>?additionalOldSources = null, IEnumerable <string>?additionalNewSources = null, SemanticEditDescription[]?expectedSemanticEdits = null, DiagnosticDescription?expectedDeclarationError = null, RudeEditDiagnosticDescription[]?expectedDiagnostics = null) { activeStatements ??= ActiveStatementsDescription.Empty; var editMap = BuildEditMap(editScript); var oldRoot = editScript.Match.OldRoot; var newRoot = editScript.Match.NewRoot; var oldSource = oldRoot.SyntaxTree.ToString(); var newSource = newRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); IEnumerable <SyntaxTree> oldTrees = new[] { oldRoot.SyntaxTree }; IEnumerable <SyntaxTree> newTrees = new[] { newRoot.SyntaxTree }; if (additionalOldSources != null) { oldTrees = oldTrees.Concat(additionalOldSources.Select(s => ParseText(s))); } if (additionalOldSources != null) { newTrees = newTrees.Concat(additionalNewSources.Select(s => ParseText(s))); } var oldCompilation = CreateLibraryCompilation("Old", oldTrees); var newCompilation = CreateLibraryCompilation("New", newTrees); var oldModel = oldCompilation.GetSemanticModel(oldRoot.SyntaxTree); var newModel = newCompilation.GetSemanticModel(newRoot.SyntaxTree); var oldActiveStatements = activeStatements.OldStatements.AsImmutable(); var updatedActiveMethodMatches = new List <UpdatedMemberInfo>(); var triviaEdits = new List <(SyntaxNode OldNode, SyntaxNode NewNode)>(); var actualLineEdits = new List <LineChange>(); var actualSemanticEdits = new List <SemanticEdit>(); var diagnostics = new List <RudeEditDiagnostic>(); var spanTracker = new TestActiveStatementSpanTracker(); var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId()); var actualNewActiveStatements = new ActiveStatement[activeStatements.OldStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [activeStatements.OldStatements.Length]; Analyzer.GetTestAccessor().AnalyzeSyntax( editScript, editMap, oldText, newText, documentId, spanTracker, oldActiveStatements, actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource); Analyzer.GetTestAccessor().AnalyzeTrivia( oldText, newText, editScript.Match, editMap, triviaEdits, actualLineEdits, diagnostics, CancellationToken.None); diagnostics.Verify(newSource); Analyzer.GetTestAccessor().AnalyzeSemantics( editScript, editMap, oldText, oldActiveStatements, triviaEdits, updatedActiveMethodMatches, oldModel, newModel, actualSemanticEdits, diagnostics, out var firstDeclarationErrorOpt, CancellationToken.None); var actualDeclarationErrors = (firstDeclarationErrorOpt != null) ? new[] { firstDeclarationErrorOpt } : Array.Empty <Diagnostic>(); var expectedDeclarationErrors = (expectedDeclarationError != null) ? new[] { expectedDeclarationError } : Array.Empty <DiagnosticDescription>(); actualDeclarationErrors.Verify(expectedDeclarationErrors); diagnostics.Verify(newSource, expectedDiagnostics); if (expectedSemanticEdits == null) { return; } Assert.Equal(expectedSemanticEdits.Length, actualSemanticEdits.Count); for (var i = 0; i < actualSemanticEdits.Count; i++) { var editKind = expectedSemanticEdits[i].Kind; Assert.Equal(editKind, actualSemanticEdits[i].Kind); var expectedOldSymbol = (editKind == SemanticEditKind.Update) ? expectedSemanticEdits[i].SymbolProvider(oldCompilation) : null; var expectedNewSymbol = expectedSemanticEdits[i].SymbolProvider(newCompilation); var actualOldSymbol = actualSemanticEdits[i].OldSymbol; var actualNewSymbol = actualSemanticEdits[i].NewSymbol; Assert.Equal(expectedOldSymbol, actualOldSymbol); Assert.Equal(expectedNewSymbol, actualNewSymbol); var expectedSyntaxMap = expectedSemanticEdits[i].SyntaxMap; var actualSyntaxMap = actualSemanticEdits[i].SyntaxMap; Assert.Equal(expectedSemanticEdits[i].PreserveLocalVariables, actualSemanticEdits[i].PreserveLocalVariables); if (expectedSyntaxMap != null) { Contract.ThrowIfNull(actualSyntaxMap); Assert.True(expectedSemanticEdits[i].PreserveLocalVariables); var newNodes = new List <SyntaxNode>(); foreach (var expectedSpanMapping in expectedSyntaxMap) { var newNode = FindNode(newRoot, expectedSpanMapping.Value); var expectedOldNode = FindNode(oldRoot, expectedSpanMapping.Key); var actualOldNode = actualSyntaxMap(newNode); Assert.Equal(expectedOldNode, actualOldNode); newNodes.Add(newNode); } } else if (!expectedSemanticEdits[i].PreserveLocalVariables) { Assert.Null(actualSyntaxMap); } } }
internal static ParameterHintingResult CreateProvider(string text) { string parsedText; string editorText; int cursorPosition = text.IndexOf('$'); int endPos = text.IndexOf('$', cursorPosition + 1); if (endPos == -1) { parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1); } else { parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1); editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1); cursorPosition = endPos - 1; } var workspace = new InspectionActionTestBase.TestWorkspace(); var projectId = ProjectId.CreateNewId(); //var solutionId = SolutionId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "TestProject", "TestProject", LanguageNames.CSharp, null, null, new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, false, "", "", "Script", null, OptimizationLevel.Debug, false, false ), new CSharpParseOptions( LanguageVersion.CSharp6, DocumentationMode.None, SourceCodeKind.Regular, ImmutableArray.Create("DEBUG", "TEST") ), new [] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(parsedText), VersionStamp.Create())) ) }, null, InspectionActionTestBase.DefaultMetadataReferences ) ); var engine = new ParameterHintingEngine(workspace, new TestFactory()); var compilation = workspace.CurrentSolution.GetProject(projectId).GetCompilationAsync().Result; if (!workspace.TryApplyChanges(workspace.CurrentSolution.WithDocumentText(documentId, SourceText.From(editorText)))) { Assert.Fail(); } var document = workspace.CurrentSolution.GetDocument(documentId); var semanticModel = document.GetSemanticModelAsync().Result; return(engine.GetParameterDataProviderAsync(document, semanticModel, cursorPosition).Result); }
private void UpdateProject(ProjectFileInfo projectFileInfo) { var project = _workspace.CurrentSolution.GetProject(projectFileInfo.WorkspaceId); var unusedDocuments = project.Documents.ToDictionary(d => d.FilePath, d => d.Id); foreach (var file in projectFileInfo.SourceFiles) { if (unusedDocuments.Remove(file)) { continue; } using (var stream = File.OpenRead(file)) { var sourceText = SourceText.From(stream, encoding: Encoding.UTF8); var id = DocumentId.CreateNewId(projectFileInfo.WorkspaceId); var version = VersionStamp.Create(); var loader = TextLoader.From(TextAndVersion.Create(sourceText, version)); _workspace.AddDocument(DocumentInfo.Create(id, file, filePath: file, loader: loader)); } } if (projectFileInfo.SpecifiedLanguageVersion.HasValue || projectFileInfo.DefineConstants != null) { var parseOptions = projectFileInfo.SpecifiedLanguageVersion.HasValue ? new CSharpParseOptions(projectFileInfo.SpecifiedLanguageVersion.Value) : new CSharpParseOptions(); if (projectFileInfo.DefineConstants != null && projectFileInfo.DefineConstants.Any()) { parseOptions = parseOptions.WithPreprocessorSymbols(projectFileInfo.DefineConstants); } _workspace.SetParseOptions(project.Id, parseOptions); } foreach (var unused in unusedDocuments) { _workspace.RemoveDocument(unused.Value); } var unusedProjectReferences = new HashSet <ProjectReference>(project.ProjectReferences); foreach (var projectReferencePath in projectFileInfo.ProjectReferences) { ProjectFileInfo projectReferenceInfo; if (_context.Projects.TryGetValue(projectReferencePath, out projectReferenceInfo)) { var reference = new ProjectReference(projectReferenceInfo.WorkspaceId); if (unusedProjectReferences.Remove(reference)) { // This reference already exists continue; } _workspace.AddProjectReference(project.Id, reference); } else { _logger.LogWarning($"Unable to resolve project reference '{projectReferencePath}' for '{projectFileInfo}'."); } } foreach (var unused in unusedProjectReferences) { _workspace.RemoveProjectReference(project.Id, unused); } var unusedAnalyzers = new Dictionary <string, AnalyzerReference>(project.AnalyzerReferences.ToDictionary(a => a.FullPath)); foreach (var analyzerPath in projectFileInfo.Analyzers) { if (!File.Exists(analyzerPath)) { _logger.LogWarning($"Unable to resolve assembly '{analyzerPath}'"); } else { if (unusedAnalyzers.Remove(analyzerPath)) { continue; } #if DNX451 var analyzerReference = new AnalyzerFileReference(analyzerPath); project.AddAnalyzerReference(analyzerReference); #endif } } foreach (var analyzerReference in unusedAnalyzers.Values) { project.RemoveAnalyzerReference(analyzerReference); } var unusedReferences = new HashSet <MetadataReference>(project.MetadataReferences); foreach (var referencePath in projectFileInfo.References) { if (!File.Exists(referencePath)) { _logger.LogWarning($"Unable to resolve assembly '{referencePath}'"); } else { var metadataReference = _metadataReferenceCache.GetMetadataReference(referencePath); if (unusedReferences.Remove(metadataReference)) { continue; } _logger.LogVerbose($"Adding reference '{referencePath}' to '{projectFileInfo.ProjectFilePath}'."); _workspace.AddMetadataReference(project.Id, metadataReference); } } foreach (var reference in unusedReferences) { _workspace.RemoveMetadataReference(project.Id, reference); } }
private void FormatDocumentCreatedFromTemplate(IVsHierarchy hierarchy, uint itemid, string filePath, CancellationToken cancellationToken) { // A file has been created on disk which the user added from the "Add Item" dialog. We need // to include this in a workspace to figure out the right options it should be formatted with. // This requires us to place it in the correct project. var workspace = _componentModel.GetService <VisualStudioWorkspace>(); var solution = workspace.CurrentSolution; ProjectId projectIdToAddTo = null; foreach (var projectId in solution.ProjectIds) { if (workspace.GetHierarchy(projectId) == hierarchy) { projectIdToAddTo = projectId; break; } } if (projectIdToAddTo == null) { // We don't have a project for this, so we'll just make up a fake project altogether var temporaryProject = solution.AddProject( name: nameof(FormatDocumentCreatedFromTemplate), assemblyName: nameof(FormatDocumentCreatedFromTemplate), language: LanguageName); solution = temporaryProject.Solution; projectIdToAddTo = temporaryProject.Id; } var documentId = DocumentId.CreateNewId(projectIdToAddTo); var forkedSolution = solution.AddDocument(DocumentInfo.Create(documentId, filePath, loader: new FileTextLoader(filePath, defaultEncoding: null), filePath: filePath)); var addedDocument = forkedSolution.GetDocument(documentId); var rootToFormat = addedDocument.GetSyntaxRootSynchronously(cancellationToken); var documentOptions = ThreadHelper.JoinableTaskFactory.Run(() => addedDocument.GetOptionsAsync(cancellationToken)); var formattedTextChanges = Formatter.GetFormattedTextChanges(rootToFormat, workspace, documentOptions, cancellationToken); var formattedText = addedDocument.GetTextSynchronously(cancellationToken).WithChanges(formattedTextChanges); // Ensure the line endings are normalized. The formatter doesn't touch everything if it doesn't need to. var targetLineEnding = documentOptions.GetOption(FormattingOptions.NewLine); var originalText = formattedText; foreach (var originalLine in originalText.Lines) { var originalNewLine = originalText.ToString(CodeAnalysis.Text.TextSpan.FromBounds(originalLine.End, originalLine.EndIncludingLineBreak)); // Check if we have a line ending, so we don't go adding one to the end if we don't need to. if (originalNewLine.Length > 0 && originalNewLine != targetLineEnding) { var currentLine = formattedText.Lines[originalLine.LineNumber]; var currentSpan = CodeAnalysis.Text.TextSpan.FromBounds(currentLine.End, currentLine.EndIncludingLineBreak); formattedText = formattedText.WithChanges(new TextChange(currentSpan, targetLineEnding)); } } IOUtilities.PerformIO(() => { using (var textWriter = new StreamWriter(filePath, append: false, encoding: formattedText.Encoding)) { // We pass null here for cancellation, since cancelling in the middle of the file write would leave the file corrupted formattedText.Write(textWriter, cancellationToken: CancellationToken.None); } }); }
public static Document AddDocument(this AdhocWorkspace workspace, Project project, string content, string fileName = "code.cs") => workspace.AddDocument(DocumentInfo.Create( DocumentId.CreateNewId(project.Id), "code.cs", loader: TextLoader.From(TextAndVersion.Create(SourceText.From(content), VersionStamp.Create()))));
static List <CodeAction> GetActions(CodeFixProvider action, string input, out DiagnosticTestBase.TestWorkspace workspace, out Document doc, CSharpParseOptions parseOptions = null) { TextSpan selectedSpan; string text = ParseText(input, out selectedSpan); workspace = new DiagnosticTestBase.TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); if (parseOptions == null) { parseOptions = new CSharpParseOptions( LanguageVersion.CSharp6, DocumentationMode.Diagnose | DocumentationMode.Parse, SourceCodeKind.Regular, ImmutableArray.Create("DEBUG", "TEST") ); } workspace.Options.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, false); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "TestProject", "TestProject", LanguageNames.CSharp, null, null, new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, false, "", "", "Script", null, OptimizationLevel.Debug, false, true ), parseOptions, new[] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text), VersionStamp.Create())) ) }, null, CSharpDiagnosticTestBase.DefaultMetadataReferences ) ); doc = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId); var actions = new List <Tuple <CodeAction, ImmutableArray <Diagnostic> > >(); var model = doc.GetSemanticModelAsync().GetAwaiter().GetResult(); var diagnostics = model.GetDiagnostics(); if (diagnostics.Length == 0) { return(new List <CodeAction>()); } foreach (var d in diagnostics) { if (action.FixableDiagnosticIds.Contains(d.Id)) { if (selectedSpan.Start > 0) { Assert.True(selectedSpan == d.Location.SourceSpan, "Activation span does not match."); } var context = new CodeFixContext(doc, d.Location.SourceSpan, diagnostics.Where(d2 => d2.Location.SourceSpan == d.Location.SourceSpan).ToImmutableArray(), (arg1, arg2) => actions.Add(Tuple.Create(arg1, arg2)), default(CancellationToken)); action.RegisterCodeFixesAsync(context); } } return(actions.Select(a => a.Item1).ToList()); }
async Task InitializeAsync(ITextBuffer buffer, string code, MetadataReference[] refs, string languageName, ISynchronousTagger <IClassificationTag> tagger, CompilationOptions compilationOptions, ParseOptions parseOptions) { using (var workspace = new AdhocWorkspace(RoslynMefHostServices.DefaultServices)) { var documents = new List <DocumentInfo>(); var projectId = ProjectId.CreateNewId(); documents.Add(DocumentInfo.Create(DocumentId.CreateNewId(projectId), "main.cs", null, SourceCodeKind.Regular, TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create()))); var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "compilecodeproj", Guid.NewGuid().ToString(), languageName, compilationOptions: compilationOptions .WithOptimizationLevel(OptimizationLevel.Release) .WithPlatform(Platform.AnyCpu) .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default), parseOptions: parseOptions, documents: documents, metadataReferences: refs, isSubmission: false, hostObjectType: null); workspace.AddProject(projectInfo); foreach (var doc in documents) { workspace.OpenDocument(doc.Id); } buffer.Replace(new Span(0, buffer.CurrentSnapshot.Length), code); { // Initialize classification code paths var spans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length)); foreach (var tagSpan in tagger.GetTags(spans, CancellationToken.None)) { } } { // Initialize completion code paths var info = CompletionInfo.Create(buffer.CurrentSnapshot); Debug.Assert(info != null); if (info != null) { var completionTrigger = CompletionTrigger.Invoke; var completionList = await info.Value.CompletionService.GetCompletionsAsync(info.Value.Document, 0, completionTrigger); } } { // Initialize signature help code paths var info = SignatureHelpInfo.Create(buffer.CurrentSnapshot); Debug.Assert(info != null); if (info != null) { int sigHelpIndex = code.IndexOf("sighelp"); Debug.Assert(sigHelpIndex >= 0); var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand); var items = await info.Value.SignatureHelpService.GetItemsAsync(info.Value.Document, sigHelpIndex, triggerInfo); } } { // Initialize quick info code paths var info = QuickInfoState.Create(buffer.CurrentSnapshot); Debug.Assert(info != null); if (info != null) { int quickInfoIndex = code.IndexOf("Equals"); Debug.Assert(quickInfoIndex >= 0); var item = await info.Value.QuickInfoService.GetItemAsync(info.Value.Document, quickInfoIndex); } } } }
public async Task PinvokeMethodReferences_VB() { var tree = Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.ParseText( @" Module Module1 Declare Function CreateDirectory Lib ""kernel32"" Alias ""CreateDirectoryA"" (ByVal lpPathName As String) As Integer Private prop As Integer Property Prop1 As Integer Get Return prop End Get Set(value As Integer) CreateDirectory(""T"") ' Method Call 1 prop = value prop = Nothing End Set End Property Sub Main() CreateDirectory(""T"") 'Method Call 2 NormalMethod() ' Method Call 1 NormalMethod() ' Method Call 2 End Sub Sub NormalMethod() End Sub End Module "); var prj1Id = ProjectId.CreateNewId(); var docId = DocumentId.CreateNewId(prj1Id); var sln = CreateWorkspace().CurrentSolution .AddProject(prj1Id, "testDeclareReferences", "testAssembly", LanguageNames.VisualBasic) .AddMetadataReference(prj1Id, MscorlibRef) .AddDocument(docId, "testFile", tree.GetText()); var prj = sln.GetProject(prj1Id).WithCompilationOptions(new VisualBasic.VisualBasicCompilationOptions(OutputKind.ConsoleApplication, embedVbCoreRuntime: true)); tree = await prj.GetDocument(docId).GetSyntaxTreeAsync(); var comp = await prj.GetCompilationAsync(); var semanticModel = comp.GetSemanticModel(tree); SyntaxNode declareMethod = tree.GetRoot().DescendantNodes().OfType <Microsoft.CodeAnalysis.VisualBasic.Syntax.DeclareStatementSyntax>().FirstOrDefault(); SyntaxNode normalMethod = tree.GetRoot().DescendantNodes().OfType <Microsoft.CodeAnalysis.VisualBasic.Syntax.MethodStatementSyntax>().ToList()[1]; // declared method calls var symbol = semanticModel.GetDeclaredSymbol(declareMethod); var references = await SymbolFinder.FindReferencesAsync(symbol, prj.Solution); Assert.Equal(expected: 2, actual: references.ElementAt(0).Locations.Count()); // normal method calls symbol = semanticModel.GetDeclaredSymbol(normalMethod); references = await SymbolFinder.FindReferencesAsync(symbol, prj.Solution); Assert.Equal(expected: 2, actual: references.ElementAt(0).Locations.Count()); }
public async Task PinvokeMethodReferences_CS() { var tree = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText( @" using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Runtime.InteropServices; static class Module1 { [DllImport(""kernel32"", EntryPoint = ""CreateDirectoryA"", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern int CreateDirectory(string lpPathName); private static int prop; public static int Prop1 { get { return prop; } set { CreateDirectory(""T""); // Method Call 1 prop = value; prop = null; } } public static void Main() { CreateDirectory(""T""); // Method Call 2 NormalMethod(); // Method Call 1 NormalMethod(); // Method Call 2 } public static void NormalMethod() { } } "); var prj1Id = ProjectId.CreateNewId(); var docId = DocumentId.CreateNewId(prj1Id); var sln = CreateWorkspace().CurrentSolution .AddProject(prj1Id, "testDeclareReferences", "testAssembly", LanguageNames.CSharp) .AddMetadataReference(prj1Id, MscorlibRef) .AddDocument(docId, "testFile", tree.GetText()); var prj = sln.GetProject(prj1Id).WithCompilationOptions(new CSharp.CSharpCompilationOptions(OutputKind.ConsoleApplication)); tree = await prj.GetDocument(docId).GetSyntaxTreeAsync(); var comp = await prj.GetCompilationAsync(); var semanticModel = comp.GetSemanticModel(tree); var methodlist = tree.GetRoot().DescendantNodes().OfType <Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax>().ToList(); SyntaxNode declareMethod = methodlist.ElementAt(0); SyntaxNode normalMethod = methodlist.ElementAt(2); // pinvoke method calls var symbol = semanticModel.GetDeclaredSymbol(declareMethod); var references = await SymbolFinder.FindReferencesAsync(symbol, prj.Solution); Assert.Equal(2, references.ElementAt(0).Locations.Count()); // normal method calls symbol = semanticModel.GetDeclaredSymbol(normalMethod); references = await SymbolFinder.FindReferencesAsync(symbol, prj.Solution); Assert.Equal(2, references.ElementAt(0).Locations.Count()); }
protected static void AnalyzeWithRule <T>(string input, string ruleId, string output = null, int issueToFix = -1, int actionToRun = 0, Action <int, Diagnostic> diagnosticCheck = null) where T : DiagnosticAnalyzer, new() { var text = new StringBuilder(); var expectedDiagnosics = new List <TextSpan> (); int start = -1; for (int i = 0; i < input.Length; i++) { char ch = input [i]; if (ch == '$') { if (start < 0) { start = text.Length; continue; } expectedDiagnosics.Add(TextSpan.FromBounds(start, text.Length)); start = -1; } else { text.Append(ch); } } var syntaxTree = CSharpSyntaxTree.ParseText(text.ToString()); Compilation compilation = CreateCompilationWithMscorlib(new [] { syntaxTree }); var diagnostics = new List <Diagnostic>(); var compilationWithAnalyzers = compilation.WithAnalyzers(System.Collections.Immutable.ImmutableArray <DiagnosticAnalyzer> .Empty.Add(new T())); diagnostics.AddRange(compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result); if (expectedDiagnosics.Count != diagnostics.Count) { Console.WriteLine("Diagnostics: " + diagnostics.Count); foreach (var diag in diagnostics) { Console.WriteLine(diag.Id + "/" + diag.GetMessage()); } Assert.Fail("Diagnostic count mismatch expected: " + expectedDiagnosics.Count + " but was:" + diagnostics.Count); } for (int i = 0; i < expectedDiagnosics.Count; i++) { var d = diagnostics [i]; var wholeSpan = GetWholeSpan(d); if (wholeSpan != expectedDiagnosics [i]) { Assert.Fail("Diagnostic " + i + " span mismatch expected: " + expectedDiagnosics[i] + " but was " + wholeSpan); } if (diagnosticCheck != null) { diagnosticCheck(i, d); } } if (output == null) { return; } var workspace = new TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "", "", LanguageNames.CSharp, null, null, null, null, new [] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text.ToString()), VersionStamp.Create()))) } )); if (issueToFix < 0) { diagnostics.Reverse(); foreach (var v in diagnostics) { RunFix(workspace, projectId, documentId, v); } } else { RunFix(workspace, projectId, documentId, diagnostics.ElementAt(issueToFix), actionToRun); } var txt = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId).GetTextAsync().Result.ToString(); if (output != txt) { Console.WriteLine("expected:"); Console.WriteLine(output); Console.WriteLine("got:"); Console.WriteLine(txt); Assert.Fail(); } }
public async Task CreateSolutionSnapshotId_Incremental() { var solution = CreateFullSolution(); var snapshotService = (new SolutionChecksumServiceFactory()).CreateService(solution.Workspace.Services) as ISolutionChecksumService; // snapshot1 builds graph using (var snapshot1 = await snapshotService.CreateChecksumAsync(solution, CancellationToken.None).ConfigureAwait(false)) { // now test whether we are rebuilding assets correctly. var solutionId1 = snapshot1.SolutionChecksum; { VerifyChecksumObjectInService(snapshotService, solutionId1); VerifyChecksumInService(snapshotService, solutionId1.Info, WellKnownChecksumObjects.SolutionChecksumObjectInfo); VerifyChecksumObjectInService(snapshotService, solutionId1.Projects); Assert.Equal(solutionId1.Projects.Count, 2); var projects = solutionId1.Projects.ToProjectObjects(snapshotService); VerifySnapshotInService(snapshotService, projects[0], 1, 1, 1, 1, 1); VerifySnapshotInService(snapshotService, projects[1], 1, 0, 0, 0, 0); } // update solution var solution2 = solution.AddDocument(DocumentId.CreateNewId(solution.ProjectIds.First(), "incremental"), "incremental", "incremental"); // snapshot2 reuse some data cached from snapshot1 using (var snapshot2 = await snapshotService.CreateChecksumAsync(solution2, CancellationToken.None).ConfigureAwait(false)) { // now test whether we are rebuilding assets correctly. var solutionId2 = snapshot2.SolutionChecksum; { VerifyChecksumObjectInService(snapshotService, solutionId2); VerifyChecksumInService(snapshotService, solutionId2.Info, WellKnownChecksumObjects.SolutionChecksumObjectInfo); VerifyChecksumObjectInService(snapshotService, solutionId2.Projects); Assert.Equal(solutionId2.Projects.Count, 2); var projects = solutionId2.Projects.ToProjectObjects(snapshotService); VerifySnapshotInService(snapshotService, projects[0], 2, 1, 1, 1, 1); VerifySnapshotInService(snapshotService, projects[1], 1, 0, 0, 0, 0); } // make sure solutionSnapshots are changed Assert.False(object.ReferenceEquals(solutionId1, solutionId2)); Assert.False(object.ReferenceEquals(solutionId1.Projects, solutionId2.Projects)); // this is due to we not having a key that make sure things are not changed in the info Assert.False(object.ReferenceEquals(solutionId1.Info, solutionId2.Info)); // make sure projectSnapshots are changed var projectId1 = solutionId1.Projects.ToProjectObjects(snapshotService)[0]; var projectId2 = solutionId2.Projects.ToProjectObjects(snapshotService)[0]; Assert.False(object.ReferenceEquals(projectId1, projectId2)); Assert.False(object.ReferenceEquals(projectId1.Documents, projectId2.Documents)); Assert.False(object.ReferenceEquals(projectId1.Info, projectId2.Info)); Assert.True(object.ReferenceEquals(projectId1.ProjectReferences, projectId2.ProjectReferences)); Assert.True(object.ReferenceEquals(projectId1.MetadataReferences, projectId2.MetadataReferences)); Assert.True(object.ReferenceEquals(projectId1.AnalyzerReferences, projectId2.AnalyzerReferences)); Assert.True(object.ReferenceEquals(projectId1.AdditionalDocuments, projectId2.AdditionalDocuments)); // actual elements are same Assert.True(object.ReferenceEquals(projectId1.CompilationOptions, projectId2.CompilationOptions)); Assert.True(object.ReferenceEquals(projectId1.ParseOptions, projectId2.ParseOptions)); Assert.True(object.ReferenceEquals(projectId1.Documents[0], projectId2.Documents[0])); Assert.True(object.ReferenceEquals(projectId1.ProjectReferences[0], projectId2.ProjectReferences[0])); Assert.True(object.ReferenceEquals(projectId1.MetadataReferences[0], projectId2.MetadataReferences[0])); Assert.True(object.ReferenceEquals(projectId1.AnalyzerReferences[0], projectId2.AnalyzerReferences[0])); Assert.True(object.ReferenceEquals(projectId1.AdditionalDocuments[0], projectId2.AdditionalDocuments[0])); // project unchanged are same Assert.True(object.ReferenceEquals(solutionId1.Projects[1], solutionId2.Projects[1])); } } }
public void Create_Errors_DuplicateItems() { var pid = ProjectId.CreateNewId(); var documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(pid), "doc"); Assert.Throws <ArgumentException>( "documents[1]", () => ProjectInfo.Create( pid, VersionStamp.Default, "proj", "assembly", "C#", documents: new[] { documentInfo, documentInfo } ) ); Assert.Throws <ArgumentNullException>( () => ProjectInfo.Create( pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", additionalDocuments: new DocumentInfo[] { null } ) ); Assert.Throws <ArgumentException>( "additionalDocuments[1]", () => ProjectInfo.Create( pid, VersionStamp.Default, "proj", "assembly", "C#", additionalDocuments: new[] { documentInfo, documentInfo } ) ); Assert.Throws <ArgumentNullException>( () => ProjectInfo.Create( pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", projectReferences: new ProjectReference[] { null } ) ); var projectReference = new ProjectReference(ProjectId.CreateNewId()); Assert.Throws <ArgumentException>( "projectReferences[1]", () => ProjectInfo.Create( pid, VersionStamp.Default, "proj", "assembly", "C#", projectReferences: new[] { projectReference, projectReference } ) ); Assert.Throws <ArgumentNullException>( "analyzerReferences[0]", () => ProjectInfo.Create( pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", analyzerReferences: new AnalyzerReference[] { null } ) ); var analyzerReference = new TestAnalyzerReference(); Assert.Throws <ArgumentException>( "analyzerReferences[1]", () => ProjectInfo.Create( pid, VersionStamp.Default, "proj", "assembly", "C#", analyzerReferences: new[] { analyzerReference, analyzerReference } ) ); Assert.Throws <ArgumentNullException>( () => ProjectInfo.Create( pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", metadataReferences: new MetadataReference[] { null } ) ); var metadataReference = new TestMetadataReference(); Assert.Throws <ArgumentException>( "metadataReferences[1]", () => ProjectInfo.Create( pid, VersionStamp.Default, "proj", "assembly", "C#", metadataReferences: new[] { metadataReference, metadataReference } ) ); }
/// <summary> /// Create a <see cref="Solution"/> for <paramref name="code"/> /// Each unique namespace in <paramref name="code"/> is added as a project. /// </summary> /// <param name="code">The code to create the solution from.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> /// <param name="metadataReferences">The metadata references.</param> /// <param name="languageVersion">The <see cref="LanguageVersion"/>.</param> /// <returns>A <see cref="Solution"/>.</returns> public static Solution CreateSolution(IEnumerable <string> code, CSharpCompilationOptions compilationOptions, IEnumerable <MetadataReference> metadataReferences = null, LanguageVersion languageVersion = LanguageVersion.Latest) { var solutionInfo = SolutionInfo.Create( SolutionId.CreateNewId("Test.sln"), VersionStamp.Default, projects: GetProjectInfos()); var solution = EmptySolution; foreach (var projectInfo in solutionInfo.Projects) { solution = solution.AddProject(projectInfo.WithProjectReferences(FindReferences(projectInfo))); } return(solution); IEnumerable <ProjectInfo> GetProjectInfos() { var byNamespace = new SortedDictionary <string, List <string> >(); foreach (var document in code) { var ns = CodeReader.Namespace(document); if (byNamespace.TryGetValue(ns, out var doc)) { doc.Add(document); } else { byNamespace[ns] = new List <string> { document }; } } var byProject = new SortedDictionary <string, List <KeyValuePair <string, List <string> > > >(); foreach (var kvp in byNamespace) { var last = byProject.Keys.LastOrDefault(); var ns = kvp.Key; if (last != null && ns.Contains(last)) { byProject[last].Add(kvp); } else { byProject.Add(ns, new List <KeyValuePair <string, List <string> > > { kvp }); } } foreach (var kvp in byProject) { var assemblyName = kvp.Key; var projectId = ProjectId.CreateNewId(assemblyName); yield return(ProjectInfo.Create( projectId, VersionStamp.Default, assemblyName, assemblyName, LanguageNames.CSharp, compilationOptions: compilationOptions, metadataReferences: metadataReferences, documents: kvp.Value.SelectMany(x => x.Value) .Select( x => { var documentName = CodeReader.FileName(x); return DocumentInfo.Create( DocumentId.CreateNewId(projectId, documentName), documentName, sourceCodeKind: SourceCodeKind.Regular, loader: new StringLoader(x)); })) .WithParseOptions(CSharpParseOptions.Default.WithLanguageVersion(languageVersion))); } } IEnumerable <ProjectReference> FindReferences(ProjectInfo projectInfo) { var references = new List <ProjectReference>(); foreach (var other in solutionInfo.Projects.Where(x => x.Id != projectInfo.Id)) { if (projectInfo.Documents.Any(x => x.TextLoader is StringLoader stringLoader && (stringLoader.Code.Contains($"using {other.Name};") || stringLoader.Code.Contains($"{other.Name}.")))) { references.Add(new ProjectReference(other.Id)); } } return(references); } }
public async Task UpdateBuffer_TransientDocumentsDisappearWhenProjectAddsThem() { var testFile = new TestFile("test.cs", "class C {}"); using (var host = CreateOmniSharpHost(testFile)) { await host.Workspace.BufferManager.UpdateBufferAsync(new Request() { FileName = "transient.cs", Buffer = "interface I {}" }); var docIds = host.Workspace.CurrentSolution.GetDocumentIdsWithFilePath("transient.cs"); Assert.Single(docIds); // simulate a project system adding the file for real var project1 = host.Workspace.CurrentSolution.Projects.First(); var document = DocumentInfo.Create(DocumentId.CreateNewId(project1.Id), "transient.cs", loader: TextLoader.From(TextAndVersion.Create(SourceText.From("enum E{}"), VersionStamp.Create())), filePath: "transient.cs"); // apply changes - this raises workspaceChanged event asynchronously. var newSolution = host.Workspace.CurrentSolution.AddDocument(document); host.Workspace.TryApplyChanges(newSolution); // wait for workspaceChange event to be raised. var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(10)); while (!cts.IsCancellationRequested) { await Task.Yield(); docIds = host.Workspace.CurrentSolution.GetDocumentIdsWithFilePath("transient.cs"); if (docIds.Count() <= 1) { break; } } // assert that only one document with "transient.cs" filePath remains Assert.Single(docIds); // assert that the remaining document is part of project1 project1 = host.Workspace.CurrentSolution.GetProject(project1.Id); Assert.Contains(docIds[0], project1.DocumentIds); // assert that the remaining document is not transient. Assert.False(host.Workspace.BufferManager.IsTransientDocument(docIds[0])); await host.Workspace.BufferManager.UpdateBufferAsync(new Request() { FileName = "transient.cs", Buffer = "enum E {}" }); var sourceText = await host.Workspace.CurrentSolution.GetDocument(docIds.First()).GetTextAsync(); Assert.Equal("enum E {}", sourceText.ToString()); sourceText = await host.Workspace.CurrentSolution.GetDocument(docIds.Last()).GetTextAsync(); Assert.Equal("enum E {}", sourceText.ToString()); } }
public void AddSubmission(ScriptState scriptState) { _currentCompilation = scriptState.Script.GetCompilation(); _previousSubmissionProjectId = _currentSubmissionProjectId; _committedTextContainer.AppendText(scriptState.Script.Code); var assemblyName = $"Submission#{_submissionCount++}"; var debugName = assemblyName; #if DEBUG debugName += $": {scriptState.Script.Code}"; #endif _currentSubmissionProjectId = ProjectId.CreateNewId(debugName: debugName); var projectInfo = ProjectInfo.Create( _currentSubmissionProjectId, VersionStamp.Create(), name: debugName, assemblyName: assemblyName, language: LanguageNames.CSharp, parseOptions: _parseOptions, compilationOptions: _currentCompilation.Options, metadataReferences: _currentCompilation.References); _solution = _solution.AddProject(projectInfo); var currentSubmissionDocumentId = DocumentId.CreateNewId( _currentSubmissionProjectId, debugName: debugName); // add the code submission to the current project var submissionSourceText = SourceText.From(scriptState.Script.Code); _solution = _solution.AddDocument( currentSubmissionDocumentId, debugName, submissionSourceText); if (_previousSubmissionProjectId != null) { _solution = _solution.AddProjectReference( _currentSubmissionProjectId, new ProjectReference(_previousSubmissionProjectId)); } // remove rollup and working document from project if (_committedDocumentId != null) { _solution = _solution.RemoveDocument(_committedDocumentId); } // create new ids and reuse buffers _committedTextContainer.AppendText(scriptState.Script.Code); var workingProjectName = $"Rollup through #{_submissionCount - 1}"; _committedDocumentId = DocumentId.CreateNewId( _currentSubmissionProjectId, workingProjectName); _solution = _solution.AddDocument( _committedDocumentId, workingProjectName, TextLoader.From(_committedTextContainer, new VersionStamp())); }
public static async Task <CompilerInvocation> CreateFromJsonAsync(string jsonContents) { var invocationInfo = JsonConvert.DeserializeObject <CompilerInvocationInfo>(jsonContents); // We will use a Workspace to simplify the creation of the compilation, but will be careful not to return the Workspace instance from this class. // We will still provide the language services which are used by the generator itself, but we don't tie it to a Workspace object so we can // run this as an in-proc source generator if one day desired. var workspace = new AdhocWorkspace(); var languageName = GetLanguageName(invocationInfo); var languageServices = workspace.Services.GetLanguageServices(languageName); var mapPath = GetPathMapper(invocationInfo); var splitCommandLine = CommandLineParser.SplitCommandLineIntoArguments(invocationInfo.Arguments, removeHashComments: false).ToList(); // Unfortunately for us there are a few paths that get directly read by the command line parse which we need to remap, // such as /ruleset files. So let's go through and process them now. for (var i = 0; i < splitCommandLine.Count; i++) { const string RuleSetSwitch = "/ruleset:"; if (splitCommandLine[i].StartsWith(RuleSetSwitch, StringComparison.Ordinal)) { var rulesetPath = splitCommandLine[i].Substring(RuleSetSwitch.Length); var quoted = rulesetPath.Length > 2 && rulesetPath.StartsWith("\"", StringComparison.Ordinal) && rulesetPath.EndsWith("\"", StringComparison.Ordinal); if (quoted) { rulesetPath = rulesetPath.Substring(1, rulesetPath.Length - 2); } rulesetPath = mapPath(rulesetPath); if (quoted) { rulesetPath = "\"" + rulesetPath + "\""; } splitCommandLine[i] = RuleSetSwitch + rulesetPath; } } var commandLineParserService = languageServices.GetRequiredService <ICommandLineParserService>(); var parsedCommandLine = commandLineParserService.Parse(splitCommandLine, Path.GetDirectoryName(invocationInfo.ProjectFilePath), isInteractive: false, sdkDirectory: null); var analyzerLoader = new DefaultAnalyzerAssemblyLoader(); var projectId = ProjectId.CreateNewId(invocationInfo.ProjectFilePath); var projectInfo = ProjectInfo.Create( projectId, VersionStamp.Default, name: Path.GetFileNameWithoutExtension(invocationInfo.ProjectFilePath), assemblyName: parsedCommandLine.CompilationName !, language: languageName, filePath: invocationInfo.ProjectFilePath, outputFilePath: parsedCommandLine.OutputFileName, parsedCommandLine.CompilationOptions, parsedCommandLine.ParseOptions, parsedCommandLine.SourceFiles.Select(s => CreateDocumentInfo(unmappedPath: s.Path)), metadataReferences: parsedCommandLine.MetadataReferences.Select(r => MetadataReference.CreateFromFile(mapPath(r.Reference), r.Properties)), additionalDocuments: parsedCommandLine.AdditionalFiles.Select(f => CreateDocumentInfo(unmappedPath: f.Path)), analyzerReferences: parsedCommandLine.AnalyzerReferences.Select(r => new AnalyzerFileReference(r.FilePath, analyzerLoader))) .WithAnalyzerConfigDocuments(parsedCommandLine.AnalyzerConfigPaths.Select(CreateDocumentInfo)); workspace.AddProject(projectInfo); var compilation = await workspace.CurrentSolution.GetProject(projectId) !.GetRequiredCompilationAsync(CancellationToken.None); return(new CompilerInvocation(compilation, languageServices, invocationInfo.ProjectFilePath, workspace.CurrentSolution.Options)); // Local methods: DocumentInfo CreateDocumentInfo(string unmappedPath) { var mappedPath = mapPath(unmappedPath); return(DocumentInfo.Create( DocumentId.CreateNewId(projectId, mappedPath), name: mappedPath, filePath: mappedPath, loader: new FileTextLoader(mappedPath, parsedCommandLine.Encoding))); } }
/// <summary> /// Creates a <see cref="StandardTextDocument"/>. /// <para>Note: getFolderNames maps from a VSITEMID to the folders this document should be contained in.</para> /// </summary> public StandardTextDocument( DocumentProvider documentProvider, IVisualStudioHostProject project, DocumentKey documentKey, Func <uint, IReadOnlyList <string> > getFolderNames, SourceCodeKind sourceCodeKind, ITextUndoHistoryRegistry textUndoHistoryRegistry, IVsFileChangeEx fileChangeService, ITextBuffer openTextBuffer, DocumentId id, EventHandler updatedOnDiskHandler, EventHandler <bool> openedHandler, EventHandler <bool> closingHandler) { Contract.ThrowIfNull(documentProvider); this.Project = project; this.Id = id ?? DocumentId.CreateNewId(project.Id, documentKey.Moniker); _itemMoniker = documentKey.Moniker; var itemid = this.GetItemId(); this.Folders = itemid == (uint)VSConstants.VSITEMID.Nil ? SpecializedCollections.EmptyReadOnlyList <string>() : getFolderNames(itemid); _documentProvider = documentProvider; this.Key = documentKey; this.SourceCodeKind = sourceCodeKind; _textUndoHistoryRegistry = textUndoHistoryRegistry; _fileChangeTracker = new FileChangeTracker(fileChangeService, this.FilePath); _fileChangeTracker.UpdatedOnDisk += OnUpdatedOnDisk; _openTextBuffer = openTextBuffer; _snapshotTracker = new ReiteratedVersionSnapshotTracker(openTextBuffer); // The project system does not tell us the CodePage specified in the proj file, so // we use null to auto-detect. _doNotAccessDirectlyLoader = new FileTextLoader(documentKey.Moniker, defaultEncoding: null); // If we aren't already open in the editor, then we should create a file change notification if (openTextBuffer == null) { _fileChangeTracker.StartFileChangeListeningAsync(); } if (updatedOnDiskHandler != null) { UpdatedOnDisk += updatedOnDiskHandler; } if (openedHandler != null) { Opened += openedHandler; } if (closingHandler != null) { Closing += closingHandler; } }
public async void ChangeBuffer_InsertRemoveChanges() { var workspace = new OmnisharpWorkspace(); var controller = new OmnisharpController(workspace); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "ProjectNameVal", "AssemblyNameVal", LanguageNames.CSharp); var document = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "test.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From("class C {}"), VersionStamp.Create())), "test.cs"); workspace.AddProject(projectInfo); workspace.AddDocument(document); // insert edit await controller.ChangeBuffer(new Models.ChangeBufferRequest() { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 1, NewText = "farboo", FileName = "test.cs" }); var sourceText = await workspace.CurrentSolution.GetDocument(document.Id).GetTextAsync(); Assert.Equal("farbooclass C {}", sourceText.ToString()); // remove edit await controller.ChangeBuffer(new Models.ChangeBufferRequest() { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 7, NewText = "", FileName = "test.cs" }); sourceText = await workspace.CurrentSolution.GetDocument(document.Id).GetTextAsync(); Assert.Equal("class C {}", sourceText.ToString()); // modification edit await controller.ChangeBuffer(new Models.ChangeBufferRequest() { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 6, NewText = "interface", FileName = "test.cs" }); sourceText = await workspace.CurrentSolution.GetDocument(document.Id).GetTextAsync(); Assert.Equal("interface C {}", sourceText.ToString()); }
public void TestDocumentId() { VerifyJsonSerialization(DocumentId.CreateNewId(ProjectId.CreateNewId("project"), "document")); }
/// <summary> /// Creates a solution that will be used as parent for the sources that need to be checked. /// </summary> /// <param name="projectId">The project identifier to use.</param> /// <param name="language">The language for which the solution is being created.</param> /// <returns>The created solution.</returns> protected virtual Solution CreateSolution(ProjectId projectId, string language) { var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true); Solution solution = new AdhocWorkspace() .CurrentSolution .AddProject(projectId, TestProjectName, TestProjectName, language) .WithProjectCompilationOptions(projectId, compilationOptions) .AddMetadataReference(projectId, MetadataReferences.CorlibReference) .AddMetadataReference(projectId, MetadataReferences.SystemReference) .AddMetadataReference(projectId, MetadataReferences.SystemCoreReference) .AddMetadataReference(projectId, MetadataReferences.CSharpSymbolsReference) .AddMetadataReference(projectId, MetadataReferences.CodeAnalysisReference); solution.Workspace.Options = solution.Workspace.Options .WithChangedOption(FormattingOptions.IndentationSize, language, this.IndentationSize) .WithChangedOption(FormattingOptions.TabSize, language, this.TabSize) .WithChangedOption(FormattingOptions.UseTabs, language, this.UseTabs); var settings = this.GetSettings(); StyleCopSettings defaultSettings = new StyleCopSettings(); if (this.IndentationSize != defaultSettings.Indentation.IndentationSize || this.UseTabs != defaultSettings.Indentation.UseTabs || this.TabSize != defaultSettings.Indentation.TabSize) { var indentationSettings = $@" {{ ""settings"": {{ ""indentation"": {{ ""indentationSize"": {this.IndentationSize}, ""useTabs"": {this.UseTabs.ToString().ToLowerInvariant()}, ""tabSize"": {this.TabSize} }} }} }} "; if (string.IsNullOrEmpty(settings)) { settings = indentationSettings; } else { JObject mergedSettings = JsonConvert.DeserializeObject <JObject>(settings); mergedSettings.Merge(JsonConvert.DeserializeObject <JObject>(indentationSettings)); settings = JsonConvert.SerializeObject(mergedSettings); } } if (!string.IsNullOrEmpty(settings)) { var documentId = DocumentId.CreateNewId(projectId); solution = solution.AddAdditionalDocument(documentId, SettingsHelper.SettingsFileName, settings); } ParseOptions parseOptions = solution.GetProject(projectId).ParseOptions; return(solution.WithProjectParseOptions(projectId, parseOptions.WithDocumentationMode(DocumentationMode.Diagnose))); }
public async Task <Dictionary <string, AssemblyInfo> > Execute([CallerFilePath] string sourceFile = null) { if (sourceFile == null) { throw new ArgumentNullException(nameof(sourceFile)); } var builtAssemblies = new Dictionary <string, AssemblyInfo>(); IEnumerable <AssemblyInfo> GetAssemblies() { var assemblyRegex = new Regex(@"<\s*assembly(:\s*(?<Name>\w+))?\s*/?>"); var endAssemblyRegex = new Regex(@"</\s*assembly\s*>"); var typeRegex = new Regex(@"<\s*type:\s*(?<Name>\w+)\s*/>"); var referenceRegex = new Regex(@"<\s*ref:\s*(?<Name>[\w_\.]+)\s*/>"); var weaverRegex = new Regex(@"<\s*weaver:\s*(?<Name>[\w_\.]+)\s*/>"); using (var sr = new StreamReader(sourceFile)) { AssemblyInfo currentAssembly = null; while (!sr.EndOfStream) { string line = sr.ReadLine(); if (line == null) { continue; } string trimmed = line.Trim(); if (trimmed.StartsWith("//") || trimmed.StartsWith("/*")) { // ReSharper disable TooWideLocalVariableScope Match assemblyStartMatch, typeMatch, referenceMatch, weaverMatch; // ReSharper restore TooWideLocalVariableScope if ((assemblyStartMatch = assemblyRegex.Match(trimmed)).Success) { if (currentAssembly != null) { yield return(currentAssembly); } currentAssembly = new AssemblyInfo(assemblyStartMatch.Groups["Name"]?.Value); } else if (currentAssembly != null) { if (endAssemblyRegex.IsMatch(trimmed)) { yield return(currentAssembly); currentAssembly = null; } else if ((typeMatch = typeRegex.Match(trimmed)).Success) { if (Enum.TryParse(typeMatch.Groups["Name"].Value, true, out OutputKind output)) { currentAssembly.OutputKind = output; } } else if ((referenceMatch = referenceRegex.Match(trimmed)).Success) { MetadataReference GetReference(string name) { if (builtAssemblies.TryGetValue(name, out AssemblyInfo builtAssembly)) { return(MetadataReference.CreateFromFile(builtAssembly.Assembly.Location)); } string filePath = $@".\{name}.dll"; if (File.Exists(filePath)) { return(MetadataReference.CreateFromFile(filePath)); } //Assembly loadedAssembly = Assembly.Load(new AssemblyName(name)); //if (loadedAssembly != null) //{ // return MetadataReference.CreateFromFile(loadedAssembly.Location); //} return(null); } MetadataReference reference = GetReference(referenceMatch.Groups["Name"].Value); if (reference != null) { currentAssembly.AddReference(reference); } //TODO: Else } else if ((weaverMatch = weaverRegex.Match(trimmed)).Success) { Weaver weaver = Weaver.FindWeaver(weaverMatch.Groups["Name"].Value); if (weaver != null) { WeaverAdded?.Invoke(this, new WeaverAddedEventArgs(weaver)); currentAssembly.AddWeaver(weaver); } //TODO: Else } } } currentAssembly?.AppendLine(line); } if (currentAssembly != null) { yield return(currentAssembly); } } } var workspace = new AdhocWorkspace(); foreach (AssemblyInfo assemblyInfo in GetAssemblies()) { string assemblyName = $"AssemblyToTest{_instanceCount++}"; var projectId = ProjectId.CreateNewId(); var document = DocumentInfo.Create(DocumentId.CreateNewId(projectId), "Generated.cs", loader: TextLoader.From(TextAndVersion.Create(SourceText.From(assemblyInfo.GetContents(), System.Text.Encoding.Unicode), VersionStamp.Create()))); var project = workspace.AddProject(ProjectInfo.Create(projectId, VersionStamp.Create(), assemblyName, assemblyName, LanguageNames.CSharp, compilationOptions: new CSharpCompilationOptions(assemblyInfo.OutputKind), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3), documents: new[] { document }, metadataReferences: assemblyInfo.References, filePath: Path.GetFullPath( $"{Path.GetFileNameWithoutExtension(Path.GetRandomFileName())}.csproj"))); Compilation compile = await project.GetCompilationAsync(); assemblyInfo.FilePath = Path.GetFullPath($"{assemblyName}.dll"); string pdbPath = Path.ChangeExtension(assemblyInfo.FilePath, ".pdb"); using (var file = File.Create(assemblyInfo.FilePath)) using (var pdbFile = File.Create(pdbPath)) { var emitResult = compile.Emit(file, pdbFile); if (emitResult.Success) { foreach (Weaver weaver in assemblyInfo.Weavers) { file.Position = 0; weaver.ApplyToAssembly(file); } } else { throw new CompileException(emitResult.Diagnostics); } } assemblyInfo.Assembly = Assembly.LoadFile(assemblyInfo.FilePath); builtAssemblies.Add(assemblyInfo.Name ?? assemblyName, assemblyInfo); } return(builtAssemblies); }
private static async Task <Solution> GetTransformedSolutionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); BaseTypeDeclarationSyntax baseTypeDeclarationSyntax = node as BaseTypeDeclarationSyntax; DelegateDeclarationSyntax delegateDeclarationSyntax = node as DelegateDeclarationSyntax; if (baseTypeDeclarationSyntax == null && delegateDeclarationSyntax == null) { return(document.Project.Solution); } DocumentId extractedDocumentId = DocumentId.CreateNewId(document.Project.Id); string extractedDocumentName = baseTypeDeclarationSyntax.Identifier.ValueText; if (baseTypeDeclarationSyntax != null) { TypeDeclarationSyntax typeDeclarationSyntax = baseTypeDeclarationSyntax as TypeDeclarationSyntax; if (typeDeclarationSyntax?.TypeParameterList?.Parameters.Count > 0) { extractedDocumentName += "`" + typeDeclarationSyntax.TypeParameterList.Parameters.Count; } } else { if (delegateDeclarationSyntax.TypeParameterList?.Parameters.Count > 0) { extractedDocumentName += "`" + delegateDeclarationSyntax.TypeParameterList.Parameters.Count; } } extractedDocumentName += ".cs"; List <SyntaxNode> nodesToRemoveFromExtracted = new List <SyntaxNode>(); SyntaxNode previous = node; for (SyntaxNode current = node.Parent; current != null; previous = current, current = current.Parent) { foreach (SyntaxNode child in current.ChildNodes()) { if (child == previous) { continue; } switch (child.Kind()) { case SyntaxKind.NamespaceDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.DelegateDeclaration: nodesToRemoveFromExtracted.Add(child); break; default: break; } } } SyntaxNode extractedDocumentNode = root.RemoveNodes(nodesToRemoveFromExtracted, SyntaxRemoveOptions.KeepUnbalancedDirectives); Solution updatedSolution = document.Project.Solution.AddDocument(extractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders); // Make sure to also add the file to linked projects foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { DocumentId linkedExtractedDocumentId = DocumentId.CreateNewId(linkedDocumentId.ProjectId); updatedSolution = updatedSolution.AddDocument(linkedExtractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders); } // Remove the type from its original location updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, root.RemoveNode(node, SyntaxRemoveOptions.KeepUnbalancedDirectives)); return(updatedSolution); }
private async Task <IEnumerable <CodeActionOperation> > GetGenerateInNewFileOperationsAsync( INamedTypeSymbol namedType, string documentName, IList <string> folders, bool areFoldersValidIdentifiers, string fullFilePath, Project projectToBeUpdated, Project triggeringProject, bool isDialog) { // First, we fork the solution with a new, empty, file in it. var newDocumentId = DocumentId.CreateNewId(projectToBeUpdated.Id, debugName: documentName); var newSolution = projectToBeUpdated.Solution.AddDocument(newDocumentId, documentName, string.Empty, folders, fullFilePath); // Now we get the semantic model for that file we just added. We do that to get the // root namespace in that new document, along with location for that new namespace. // That way, when we use the code gen service we can say "add this symbol to the // root namespace" and it will pick the one in the new file. var newDocument = newSolution.GetDocument(newDocumentId); var newSemanticModel = await newDocument.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false); var enclosingNamespace = newSemanticModel.GetEnclosingNamespace(0, _cancellationToken); var namespaceContainersAndUsings = GetNamespaceContainersAndAddUsingsOrImport( isDialog, folders, areFoldersValidIdentifiers, projectToBeUpdated, triggeringProject); var containers = namespaceContainersAndUsings.containers; var includeUsingsOrImports = namespaceContainersAndUsings.usingOrImport; var rootNamespaceOrType = namedType.GenerateRootNamespaceOrType(containers); // Now, actually ask the code gen service to add this namespace or type to the root // namespace in the new file. This will properly generate the code, and add any // additional niceties like imports/usings. var codeGenResult = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( newSolution, enclosingNamespace, rootNamespaceOrType, new CodeGenerationOptions(newSemanticModel.SyntaxTree.GetLocation(new TextSpan())), _cancellationToken).ConfigureAwait(false); // containers is determined to be // 1: folders -> if triggered from Dialog // 2: containers -> if triggered not from a Dialog but from QualifiedName // 3: triggering document folder structure -> if triggered not from a Dialog and a SimpleName var adjustedContainer = isDialog ? folders : _state.SimpleName != _state.NameOrMemberAccessExpression ? containers.ToList() : _semanticDocument.Document.Folders.ToList(); // Now, take the code that would be generated and actually create an edit that would // produce a document with that code in it. var newRoot = await codeGenResult.GetSyntaxRootAsync(_cancellationToken).ConfigureAwait(false); if (newDocument.Project.Language == _semanticDocument.Document.Project.Language) { var syntaxFacts = _semanticDocument.Document.GetLanguageService <ISyntaxFactsService>(); var fileBanner = syntaxFacts.GetFileBanner(_semanticDocument.Root); newRoot = newRoot.WithPrependedLeadingTrivia(fileBanner); } return(await CreateAddDocumentAndUpdateUsingsOrImportsOperationsAsync( projectToBeUpdated, triggeringProject, documentName, newRoot, includeUsingsOrImports, adjustedContainer, SourceCodeKind.Regular, _cancellationToken).ConfigureAwait(false)); }
public async Task AnalyzeDocumentAsync_InsignificantChangesInMethodBody() { string source1 = @" class C { public static void Main() { // comment System.Console.WriteLine(1); } } "; string source2 = @" class C { public static void Main() { System.Console.WriteLine(1); } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); using (var workspace = TestWorkspace.CreateCSharp(source1)) { var documentId = workspace.CurrentSolution.Projects.First().Documents.First().Id; var oldSolution = workspace.CurrentSolution; var newSolution = workspace.CurrentSolution.WithDocumentText(documentId, SourceText.From(source2)); var oldDocument = oldSolution.GetDocument(documentId); var oldText = await oldDocument.GetTextAsync(); var oldSyntaxRoot = await oldDocument.GetSyntaxRootAsync(); var newDocument = newSolution.GetDocument(documentId); var newText = await newDocument.GetTextAsync(); var newSyntaxRoot = await newDocument.GetSyntaxRootAsync(); const string oldStatementSource = "System.Console.WriteLine(1);"; var oldStatementPosition = source1.IndexOf(oldStatementSource, StringComparison.Ordinal); var oldStatementTextSpan = new TextSpan(oldStatementPosition, oldStatementSource.Length); var oldStatementSpan = oldText.Lines.GetLinePositionSpan(oldStatementTextSpan); var oldStatementSyntax = oldSyntaxRoot.FindNode(oldStatementTextSpan); var baseActiveStatements = ImmutableArray.Create(ActiveStatementsDescription.CreateActiveStatement(ActiveStatementFlags.IsLeafFrame, oldStatementSpan, DocumentId.CreateNewId(ProjectId.CreateNewId()))); var result = await analyzer.AnalyzeDocumentAsync(oldSolution, baseActiveStatements, newDocument, CancellationToken.None); Assert.True(result.HasChanges); Assert.True(result.SemanticEdits[0].PreserveLocalVariables); var syntaxMap = result.SemanticEdits[0].SyntaxMap; var newStatementSpan = result.ActiveStatements[0].Span; var newStatementTextSpan = newText.Lines.GetTextSpan(newStatementSpan); var newStatementSyntax = newSyntaxRoot.FindNode(newStatementTextSpan); var oldStatementSyntaxMapped = syntaxMap(newStatementSyntax); Assert.Same(oldStatementSyntax, oldStatementSyntaxMapped); } }
public void Initalize() { var runtimePath = _aspNet5Paths.RuntimePath; _context.RuntimePath = runtimePath.Value; if (!ScanForProjects()) { // No ASP.NET 5 projects found so do nothing _logger.WriteInformation("No project.json based projects found"); return; } if (_context.RuntimePath == null) { // There is no default k found so do nothing _logger.WriteInformation("No default runtime found"); _emitter.Emit(EventTypes.Error, runtimePath.Error); return; } var wh = new ManualResetEventSlim(); _designTimeHostManager.Start(_context.HostId, port => { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Loopback, port)); var networkStream = new NetworkStream(socket); _logger.WriteInformation("Connected"); _context.DesignTimeHostPort = port; _context.Connection = new ProcessingQueue(networkStream, _logger); _context.Connection.OnReceive += m => { var project = _context.Projects[m.ContextId]; if (m.MessageType == "ProjectInformation") { var val = m.Payload.ToObject <ProjectMessage>(); project.Name = val.Name; project.GlobalJsonPath = val.GlobalJsonPath; project.Configurations = val.Configurations; project.Commands = val.Commands; project.ProjectSearchPaths = val.ProjectSearchPaths; this._emitter.Emit(EventTypes.ProjectChanged, new ProjectInformationResponse() { AspNet5Project = new AspNet5Project(project) }); var unprocessed = project.ProjectsByFramework.Keys.ToList(); foreach (var frameworkData in val.Frameworks) { unprocessed.Remove(frameworkData.FrameworkName); var frameworkProject = project.ProjectsByFramework.GetOrAdd(frameworkData.FrameworkName, framework => { return(new FrameworkProject(project, framework)); }); var id = frameworkProject.ProjectId; if (_workspace.CurrentSolution.ContainsProject(id)) { continue; } else { var projectInfo = ProjectInfo.Create( id, VersionStamp.Create(), val.Name + "+" + frameworkData.ShortName, val.Name, LanguageNames.CSharp, project.Path); _workspace.AddProject(projectInfo); _context.WorkspaceMapping[id] = frameworkProject; } lock (frameworkProject.PendingProjectReferences) { var reference = new Microsoft.CodeAnalysis.ProjectReference(id); foreach (var referenceId in frameworkProject.PendingProjectReferences) { _workspace.AddProjectReference(referenceId, reference); } frameworkProject.PendingProjectReferences.Clear(); } } // Remove old projects foreach (var frameworkName in unprocessed) { FrameworkProject frameworkProject; project.ProjectsByFramework.TryRemove(frameworkName, out frameworkProject); _workspace.RemoveProject(frameworkProject.ProjectId); } } // This is where we can handle messages and update the // language service else if (m.MessageType == "References") { // References as well as the dependency graph information var val = m.Payload.ToObject <ReferencesMessage>(); var frameworkProject = project.ProjectsByFramework[val.Framework.FrameworkName]; var projectId = frameworkProject.ProjectId; var metadataReferences = new List <MetadataReference>(); var projectReferences = new List <Microsoft.CodeAnalysis.ProjectReference>(); var removedFileReferences = frameworkProject.FileReferences.ToDictionary(p => p.Key, p => p.Value); var removedRawReferences = frameworkProject.RawReferences.ToDictionary(p => p.Key, p => p.Value); var removedProjectReferences = frameworkProject.ProjectReferences.ToDictionary(p => p.Key, p => p.Value); foreach (var file in val.FileReferences) { if (removedFileReferences.Remove(file)) { continue; } var metadataReference = _metadataFileReferenceCache.GetMetadataReference(file); frameworkProject.FileReferences[file] = metadataReference; metadataReferences.Add(metadataReference); } foreach (var rawReference in val.RawReferences) { if (removedRawReferences.Remove(rawReference.Key)) { continue; } var metadataReference = MetadataReference.CreateFromImage(rawReference.Value); frameworkProject.RawReferences[rawReference.Key] = metadataReference; metadataReferences.Add(metadataReference); } foreach (var projectReference in val.ProjectReferences) { if (removedProjectReferences.Remove(projectReference.Path)) { continue; } int projectReferenceContextId; if (!_context.ProjectContextMapping.TryGetValue(projectReference.Path, out projectReferenceContextId)) { projectReferenceContextId = AddProject(projectReference.Path); } var referencedProject = _context.Projects[projectReferenceContextId]; var referencedFrameworkProject = referencedProject.ProjectsByFramework.GetOrAdd(projectReference.Framework.FrameworkName, framework => { return(new FrameworkProject(referencedProject, framework)); }); var projectReferenceId = referencedFrameworkProject.ProjectId; if (_workspace.CurrentSolution.ContainsProject(projectReferenceId)) { projectReferences.Add(new Microsoft.CodeAnalysis.ProjectReference(projectReferenceId)); } else { lock (referencedFrameworkProject.PendingProjectReferences) { referencedFrameworkProject.PendingProjectReferences.Add(projectId); } } referencedFrameworkProject.ProjectDependeees[project.Path] = projectId; frameworkProject.ProjectReferences[projectReference.Path] = projectReferenceId; } foreach (var reference in metadataReferences) { _workspace.AddMetadataReference(projectId, reference); } foreach (var projectReference in projectReferences) { _workspace.AddProjectReference(projectId, projectReference); } foreach (var pair in removedProjectReferences) { _workspace.RemoveProjectReference(projectId, new Microsoft.CodeAnalysis.ProjectReference(pair.Value)); frameworkProject.ProjectReferences.Remove(pair.Key); // TODO: Update the dependee's list } foreach (var pair in removedFileReferences) { _workspace.RemoveMetadataReference(projectId, pair.Value); frameworkProject.FileReferences.Remove(pair.Key); } foreach (var pair in removedRawReferences) { _workspace.RemoveMetadataReference(projectId, pair.Value); frameworkProject.RawReferences.Remove(pair.Key); } } else if (m.MessageType == "Dependencies") { var val = m.Payload.ToObject <DependenciesMessage>(); var unresolvedDependencies = val.Dependencies.Values .Where(dep => dep.Type == "Unresolved"); if (unresolvedDependencies.Any()) { _logger.WriteInformation("Project {0} has these unresolved references: {1}", project.Path, string.Join(", ", unresolvedDependencies.Select(d => d.Name))); _emitter.Emit(EventTypes.UnresolvedDependencies, new UnresolvedDependenciesMessage() { FileName = project.Path, UnresolvedDependencies = unresolvedDependencies.Select(d => new PackageDependency() { Name = d.Name, Version = d.Version }) }); _packagesRestoreTool.Run(project); } } else if (m.MessageType == "CompilerOptions") { // Configuration and compiler options var val = m.Payload.ToObject <CompilationOptionsMessage>(); var projectId = project.ProjectsByFramework[val.Framework.FrameworkName].ProjectId; var options = val.CompilationOptions.CompilationOptions; var specificDiagnosticOptions = options.SpecificDiagnosticOptions .ToDictionary(p => p.Key, p => (ReportDiagnostic)p.Value); var csharpOptions = new CSharpCompilationOptions( outputKind: (OutputKind)options.OutputKind, optimizationLevel: (OptimizationLevel)options.OptimizationLevel, platform: (Platform)options.Platform, generalDiagnosticOption: (ReportDiagnostic)options.GeneralDiagnosticOption, warningLevel: options.WarningLevel, allowUnsafe: options.AllowUnsafe, concurrentBuild: options.ConcurrentBuild, specificDiagnosticOptions: specificDiagnosticOptions ); var parseOptions = new CSharpParseOptions(val.CompilationOptions.LanguageVersion, preprocessorSymbols: val.CompilationOptions.Defines); _workspace.SetCompilationOptions(projectId, csharpOptions); _workspace.SetParseOptions(projectId, parseOptions); } else if (m.MessageType == "Sources") { // The sources to feed to the language service var val = m.Payload.ToObject <SourcesMessage>(); project.SourceFiles = val.Files; var frameworkProject = project.ProjectsByFramework[val.Framework.FrameworkName]; var projectId = frameworkProject.ProjectId; var unprocessed = new HashSet <string>(frameworkProject.Documents.Keys); foreach (var file in val.Files) { if (unprocessed.Remove(file)) { continue; } using (var stream = File.OpenRead(file)) { var sourceText = SourceText.From(stream, encoding: Encoding.UTF8); var id = DocumentId.CreateNewId(projectId); var version = VersionStamp.Create(); frameworkProject.Documents[file] = id; var loader = TextLoader.From(TextAndVersion.Create(sourceText, version)); _workspace.AddDocument(DocumentInfo.Create(id, file, filePath: file, loader: loader)); } } foreach (var file in unprocessed) { var docId = frameworkProject.Documents[file]; frameworkProject.Documents.Remove(file); _workspace.RemoveDocument(docId); } frameworkProject.Loaded = true; } else if (m.MessageType == "Error") { var val = m.Payload.ToObject <Microsoft.Framework.DesignTimeHost.Models.OutgoingMessages.ErrorMessage>(); _logger.WriteError(val.Message); } if (project.ProjectsByFramework.Values.All(p => p.Loaded)) { wh.Set(); } }; // Start the message channel _context.Connection.Start(); // Initialize the ASP.NET 5 projects Initialize(); }); wh.Wait(); }
private async Task <ProjectId> LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, LoadState loadedProjects, CancellationToken cancellationToken) { Debug.Assert(projectFilePath != null); Debug.Assert(loader != null); var projectId = loadedProjects.GetOrCreateProjectId(projectFilePath); var projectName = Path.GetFileNameWithoutExtension(projectFilePath); var projectFile = await loader.LoadProjectFileAsync(projectFilePath, _properties, cancellationToken).ConfigureAwait(false); var projectFileInfo = await projectFile.GetProjectFileInfoAsync(cancellationToken).ConfigureAwait(false); var projectDirectory = Path.GetDirectoryName(projectFilePath); var outputFilePath = projectFileInfo.OutputFilePath; var outputDirectory = Path.GetDirectoryName(outputFilePath); VersionStamp version; if (!string.IsNullOrEmpty(projectFilePath) && File.Exists(projectFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(projectFilePath)); } else { version = VersionStamp.Create(); } // translate information from command line args var commandLineParser = _workspace.Services.GetLanguageServices(loader.Language).GetService <ICommandLineParserService>(); var metadataService = _workspace.Services.GetService <IMetadataService>(); var analyzerService = _workspace.Services.GetService <IAnalyzerService>(); var commandLineArgs = commandLineParser.Parse( arguments: projectFileInfo.CommandLineArgs, baseDirectory: projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory()); // we only support file paths in /r command line arguments var resolver = new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory)); var metadataReferences = commandLineArgs.ResolveMetadataReferences(resolver); var analyzerLoader = analyzerService.GetLoader(); foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath)) { analyzerLoader.AddDependencyLocation(path); } var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader); var defaultEncoding = commandLineArgs.Encoding; // docs & additional docs var docFileInfos = projectFileInfo.Documents.ToImmutableArrayOrEmpty(); var additionalDocFileInfos = projectFileInfo.AdditionalDocuments.ToImmutableArrayOrEmpty(); // check for duplicate documents var allDocFileInfos = docFileInfos.AddRange(additionalDocFileInfos); CheckDocuments(allDocFileInfos, projectFilePath, projectId); var docs = new List <DocumentInfo>(); foreach (var docFileInfo in docFileInfos) { string name; ImmutableArray <string> folders; GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders); docs.Add(DocumentInfo.Create( DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath), name, folders, projectFile.GetSourceCodeKind(docFileInfo.FilePath), new FileTextLoader(docFileInfo.FilePath, defaultEncoding), docFileInfo.FilePath, docFileInfo.IsGenerated)); } var additionalDocs = new List <DocumentInfo>(); foreach (var docFileInfo in additionalDocFileInfos) { string name; ImmutableArray <string> folders; GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders); additionalDocs.Add(DocumentInfo.Create( DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath), name, folders, SourceCodeKind.Regular, new FileTextLoader(docFileInfo.FilePath, defaultEncoding), docFileInfo.FilePath, docFileInfo.IsGenerated)); } // project references var resolvedReferences = await ResolveProjectReferencesAsync( projectId, projectFilePath, projectFileInfo.ProjectReferences, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false); // add metadata references for project refs converted to metadata refs metadataReferences = metadataReferences.Concat(resolvedReferences.MetadataReferences); // if the project file loader couldn't figure out an assembly name, make one using the project's file path. var assemblyName = commandLineArgs.CompilationName; if (string.IsNullOrWhiteSpace(assemblyName)) { assemblyName = Path.GetFileNameWithoutExtension(projectFilePath); // if this is still unreasonable, use a fixed name. if (string.IsNullOrWhiteSpace(assemblyName)) { assemblyName = "assembly"; } } // make sure that doc-comments at least get parsed. var parseOptions = commandLineArgs.ParseOptions; if (parseOptions.DocumentationMode == DocumentationMode.None) { parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Parse); } // add all the extra options that are really behavior overrides var compOptions = commandLineArgs.CompilationOptions .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory)) .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray <string> .Empty, projectDirectory)) // TODO: https://github.com/dotnet/roslyn/issues/4967 .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray <string> .Empty, projectDirectory))) .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath))) .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); loadedProjects.Add( ProjectInfo.Create( projectId, version, projectName, assemblyName, loader.Language, projectFilePath, outputFilePath, compilationOptions: compOptions, parseOptions: parseOptions, documents: docs, projectReferences: resolvedReferences.ProjectReferences, metadataReferences: metadataReferences, analyzerReferences: analyzerReferences, additionalDocuments: additionalDocs, isSubmission: false, hostObjectType: null)); return(projectId); }
internal void VerifyRudeDiagnostics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription description, RudeEditDiagnosticDescription[] expectedDiagnostics) { var oldActiveStatements = description.OldStatements; if (description.OldTrackingSpans != null) { Assert.Equal(oldActiveStatements.Length, description.OldTrackingSpans.Length); } var newSource = editScript.Match.NewRoot.SyntaxTree.ToString(); var oldSource = editScript.Match.OldRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new ActiveStatement[oldActiveStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [oldActiveStatements.Length]; var updatedActiveMethodMatches = new List <UpdatedMemberInfo>(); var editMap = BuildEditMap(editScript); var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId("TestEnCProject"), "TestEnCDocument"); var spanTracker = new TestActiveStatementSpanTracker( (description.OldTrackingSpans != null) ? new Dictionary <DocumentId, TextSpan?[]> { { documentId, description.OldTrackingSpans } } : null); Analyzer.GetTestAccessor().AnalyzeSyntax( editScript, editMap, oldText, newText, documentId, spanTracker, oldActiveStatements.AsImmutable(), actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource, expectedDiagnostics); // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements.Select(s => s.Span), newSource, newText); if (diagnostics.Count == 0) { // check old exception regions: for (var i = 0; i < oldActiveStatements.Length; i++) { var actualOldExceptionRegions = Analyzer.GetExceptionRegions( oldText, editScript.Match.OldRoot, oldActiveStatements[i].Span, isNonLeaf: oldActiveStatements[i].IsNonLeaf, out _); AssertSpansEqual(description.OldRegions[i], actualOldExceptionRegions, oldSource, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Length); for (var i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newSource, newText); } } else { for (var i = 0; i < oldActiveStatements.Length; i++) { Assert.Equal(0, description.NewRegions[i].Length); } } }
public async Task Run() { var op = new AzureAsyncOperation(); var restOp = new RestException(); var files = Settings.Instance.FileSystem.GetFiles(Settings.Instance.OutputDirectory, "*.cs", SearchOption.AllDirectories). ToDictionary(each => each, each => Settings.Instance.FileSystem.ReadFileAsText(each)); var assemblies = new[] { typeof(IAzureClient).GetAssembly().Location, typeof(RestException).GetAssembly().Location, typeof(Uri).GetAssembly().Location, typeof(File).GetAssembly().Location, typeof(HttpStatusCode).GetAssembly().Location, typeof(System.Net.Http.HttpClient).GetAssembly().Location, typeof(object).GetAssembly().Location, typeof(XElement).GetAssembly().Location, typeof(JsonConvert).GetAssembly().Location }; var projectId = ProjectId.CreateNewId(); var solution = new AdhocWorkspace().CurrentSolution .AddProject(projectId, "MyProject", "MyProject", LanguageNames.CSharp); // add assemblies solution = assemblies.Aggregate(solution, (current, asm) => current.AddMetadataReference(projectId, MetadataReference.CreateFromFile(asm))); // Add existing files foreach (var file in files.Keys) { var documentId = DocumentId.CreateNewId(projectId); solution = solution.AddDocument(documentId, file, SourceText.From(files[file])); } // Simplify docs and add to foreach (var proj in solution.Projects) { foreach (var document in proj.Documents) { var newRoot = await document.GetSyntaxRootAsync(); // get the namespaces used in the file var names = new GetQualifiedNames().GetNames(newRoot).Where(each => each != "System.Security.Permissions").ToArray(); // add the usings that we found newRoot = new AddUsingsRewriter(names).Visit(newRoot); // tell roslyn to simplify where it can newRoot = new SimplifyNamesRewriter().Visit(newRoot); var doc = document.WithSyntaxRoot(newRoot); // reduce the code var text = Simplifier.ReduceAsync(doc) .Result.GetTextAsync() .Result.ToString() // get rid of any BOMs .Trim('\x00EF', '\x00BB', '\x00BF', '\uFEFF', '\u200B'); // special cases the simplifier can't handle. text = text. Replace("[Newtonsoft.Json.JsonConverter(", "[JsonConverter("). Replace("[System.Runtime.Serialization.EnumMember(", "[EnumMember("). Replace("[Newtonsoft.Json.JsonProperty(", "[JsonProperty("). Replace("[Newtonsoft.Json.JsonProperty]", "[JsonProperty]"). Replace("[Newtonsoft.Json.JsonObject]", "[JsonObject]"). Replace("[Microsoft.Rest.Serialization.JsonTransformation]", "[JsonTransformation]"). Replace("[Newtonsoft.Json.JsonExtensionData]", "[JsonExtensionData]"); // Write out the files back to their original location var output = Path.Combine(Settings.Instance.FileSystem.CurrentDirectory, document.Name); Settings.Instance.FileSystem.WriteFile(output, text); } } }