public void InputWithIncident_MemberAccesses_SurfacesDiagnostic(string accessedInstance) { var test = $@"using FakeNamespace; namespace SampleTestProject.CsSamples {{ public class SampleClass {{ public void SampleMethod() {{ var instance = new FakeClass(); var a1 = {accessedInstance}.FakeMethod(); var a2 = {accessedInstance}?.FakeMethod(); var b1 = {accessedInstance}.FakeMethod().Substring(0); var b2 = {accessedInstance}.FakeMethod()?.Substring(0); var b3 = {accessedInstance}?.FakeMethod().Substring(0); var b4 = {accessedInstance}?.FakeMethod()?.Substring(0); }} }} }}"; var sources = new[] { test, _fakeClassSource }; var documents = ProjectCompilation.GetDocuments(sources, null, null); var analyzer = CSharpDiagnosticAnalyzer; var diagnostics = AnalyzerExecution.GetSortedDiagnosticsFromDocuments(analyzer, documents); Assert.AreEqual(6, diagnostics.Length); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(9, 22), diagnostics.ElementAt(0)); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(10, 22), diagnostics.ElementAt(1)); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(12, 22), diagnostics.ElementAt(2)); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(13, 22), diagnostics.ElementAt(3)); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(14, 22), diagnostics.ElementAt(4)); AssertBestEfforDiagnostic(analyzer, CreateDiagnosticResult(string.Empty).WithMessage(".FakeMethod()").WithLocation(15, 22), diagnostics.ElementAt(5)); }
/// <summary> /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run, /// then verifies each of them. /// </summary> /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param> /// <param name="analyzer">The analyzer to be run on the source code</param> /// <param name="references">An array of additional metadata references, source files are dependent on</param> /// <param name="fakeFileInfo">Fake file info generated files should have</param> /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param> private static void VerifyDiagnostics(string[] sources, DiagnosticAnalyzer analyzer, MetadataReference[] references, FakeFileInfo fakeFileInfo = null, params DiagnosticResult[] expected) { var documents = ProjectCompilation.GetDocuments(sources, references, fakeFileInfo); var diagnostics = AnalyzerExecution.GetSortedDiagnosticsFromDocuments(analyzer, documents); VerifyDiagnosticResults(diagnostics, analyzer, expected); }
private void HostReferences(object sender, ReferencesEventArgs e) { var proj = _state.Workspace.Projects.SingleOrDefault(p => p.Id == e.ContextId); if (proj == null) { return; } UpdateNode <ProjectEntry>(proj.RelativePath, (p, c) => p.WithReferences(e, c)); _compilations.AddOrUpdate(proj.Id, id => ProjectCompilation.Create(proj.Name, proj.Id), (id, old) => old.InvalidateReferences()); }
private void HostConfigurations(object sender, ConfigurationsEventArgs e) { var proj = _state.Workspace.Projects.SingleOrDefault(p => p.Id == e.ContextId); if (proj == null) { return; } // TODO: Keep commands UpdateNode <ProjectEntry>(proj.RelativePath, (p, c) => p.WithConfigurations(e.ProjectName, e.Configurations)); _compilations.AddOrUpdate(proj.Id, id => ProjectCompilation.Create(proj.Name, proj.Id), (id, old) => old.InvalidateConfiguration()); }
public void UpdateCode(string contentId, string text) { Task.Run(() => { // updates needs to be processed in the same order they are generated // this method might wait for the next update, thus running in background // thread Content content, old; var dict = _contentDictionary; lock (dict) { if (!_contentDictionary.TryGetValue(contentId, out content)) { throw new Exception("Content wasn't in dictionary. Illegal code::update sent"); } old = content; content = content.WithText(text); if (!_contentDictionary.TryUpdate(contentId, content, old)) { throw new Exception("Content has been updated by other method. State inconclusive."); } } // mark dirty if (old.ContentString == content.ContentString) { return; } var workspace = _state.Workspace; if (workspace == null) { return; } var proj = workspace.Projects.SingleOrDefault(p => content.RelativePath.StartsWith(p.RelativePath, StringComparison.OrdinalIgnoreCase)); if (proj == null) { return; } _compilations.AddOrUpdate(proj.Id, id => ProjectCompilation.Create(proj.Name, proj.Id), (i, p) => p.InvalidateSources()); MarkTab(contentId, dirty: true); }); }
/// <summary> /// Runs C# project compilation and fills <see cref="ProjectCompilation">ProjectCompilation</see> /// and <see cref="CompiledAssembly">CompiledAssembly</see>. /// </summary> /// <param name="sandbox"></param> /// <param name="dllFilename"></param> /// <returns></returns> public EmitResult CompileCSharpProject(AssemblySandbox sandbox, string dllFilename) { // must be public !!!!!!!!!! ProjectCompilation = _cSharpProject.GetCompilationAsync().Result; ProjectCompilation = ProjectCompilation.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); ProjectCompilation = ProjectCompilation.WithReferences(_cSharpProject.MetadataReferences); foreach (var i in ProjectCompilation.References) { Console.WriteLine(" linked with {0}", i.Display); } var tmp = sandbox.EmitCompiledAssembly(ProjectCompilation, out var result, dllFilename); CompiledAssembly = tmp?.WrappedAssembly; return(result); }
private static async Task InstrumentThenCompileProject( Project project, Config config, string outputFilePath, Func <long> memberIdGenerator, IDictionary <string, string> memberIdsToNames) { var originalSyntaxTrees = new List <SyntaxTree>(); var modifiedSyntaxTrees = new List <SyntaxTree>(); var documentsToInstrument = project.Documents .Where(d => Filtering.ShouldMutateDocument(d, config)) .Where(d => !d.IsAutomaticallyGenerated()); foreach (var originalDocument in documentsToInstrument) { var originalSyntaxTree = await originalDocument.GetSyntaxTreeAsync().ConfigureAwait(false); var modifiedSyntaxTree = await Instrumentation.InstrumentDocument( originalSyntaxTree, originalDocument, memberIdsToNames.Add, memberIdGenerator); originalSyntaxTrees.Add(originalSyntaxTree); modifiedSyntaxTrees.Add(modifiedSyntaxTree); } var compilation = (await project.GetCompilationAsync().ConfigureAwait(false)) .RemoveSyntaxTrees(originalSyntaxTrees) .AddSyntaxTrees(modifiedSyntaxTrees); var compilationResult = ProjectCompilation.CompileProject( outputFilePath, compilation); if (!compilationResult.Success) { var diagnostics = string.Join(Environment.NewLine, compilationResult.Diagnostics); throw new Exception( $"Failed to compile project {compilation.AssemblyName}{Environment.NewLine}{diagnostics}"); } }
public TranslationInfo ParseCsSource() { // must be public var knownTypes = GetKnownTypes(); CheckRequiredTranslator(); var translationInfo = new TranslationInfo(Sandbox); translationInfo.TranslationAssemblies.AddRange(_translationAssemblies); translationInfo.Prepare(); // Console.WriteLine("======================"); foreach (var tree in ProjectCompilation.SyntaxTrees) { var now = DateTime.Now; Console.WriteLine("parse file {0}", tree.FilePath); var root = (CompilationUnitSyntax)tree.GetRoot(); var state = new CompileState { Context = { RoslynCompilation = ProjectCompilation, RoslynModel = ProjectCompilation.GetSemanticModel(tree) } }; translationInfo.State = state; var langVisitor = new LangVisitor(state) { throwNotImplementedException = true }; state.Context.KnownTypes = knownTypes; var compilationUnit = langVisitor.Visit(root) as CompilationUnit; translationInfo.Compiled.Add(compilationUnit); Console.WriteLine(" {0:0.0} sek", DateTime.Now.Subtract(now).TotalSeconds); } Console.WriteLine("Parsowanie c# skończone, mamy drzewo definicji"); translationInfo.FillClassTranslations(knownTypes); return(translationInfo); }
private bool UpdateProjectCompilation(ProjectWorld project, out ProjectCompilation compilation) { var export = project.ApplicationHostContext.LibraryManager.GetLibraryExport(_local.ProjectInformation.Name); ProjectCompilation oldCompilation; if (!_compilations.TryGetValue(project.TargetFramework, out oldCompilation) || export != oldCompilation?.Export) { compilation = new ProjectCompilation(); compilation.Export = export; compilation.EmbeddedReferences = new Dictionary <string, byte[]>(); foreach (var reference in compilation.Export.MetadataReferences) { if (compilation.ProjectReference == null) { compilation.ProjectReference = reference as IMetadataProjectReference; } var embedded = reference as IMetadataEmbeddedReference; if (embedded != null) { compilation.EmbeddedReferences[embedded.Name] = embedded.Contents; } } var diagnostics = compilation.ProjectReference.GetDiagnostics(); compilation.Errors = diagnostics.Errors.ToList(); compilation.Warnings = diagnostics.Warnings.ToList(); _compilations[project.TargetFramework] = compilation; return(true); } compilation = oldCompilation; return(false); }
private bool UpdateProjectCompilation(ProjectWorld project, out ProjectCompilation compilation) { var exporter = _compilationEngine.CreateProjectExporter(_local.Project, project.TargetFramework, _configuration.Value); var export = exporter.GetExport(_local.ProjectInformation.Name); ProjectCompilation oldCompilation; if (!_compilations.TryGetValue(project.TargetFramework, out oldCompilation) || export != oldCompilation?.Export) { compilation = new ProjectCompilation(); compilation.Export = export; compilation.EmbeddedReferences = new Dictionary <string, byte[]>(); foreach (var reference in compilation.Export.MetadataReferences) { if (compilation.ProjectReference == null) { compilation.ProjectReference = reference as IMetadataProjectReference; } var embedded = reference as IMetadataEmbeddedReference; if (embedded != null) { compilation.EmbeddedReferences[embedded.Name] = embedded.Contents; } } var diagnostics = compilation.ProjectReference.GetDiagnostics(); compilation.Diagnostics = diagnostics.Diagnostics.ToList(); _compilations[project.TargetFramework] = compilation; return(true); } compilation = oldCompilation; return(false); }
private bool DoStageTwo() { bool calculateDiagnostics = _requiresCompilation.WasAssigned; if (calculateDiagnostics) { _requiresCompilation.ClearAssigned(); } foreach (var pair in _local.Projects) { var project = pair.Value; var projectCompilationChanged = false; ProjectCompilation compilation = null; if (calculateDiagnostics) { projectCompilationChanged = UpdateProjectCompilation(project, out compilation); project.Diagnostics = new DiagnosticsMessage { Framework = project.Sources.Framework, Errors = compilation.Errors, Warnings = compilation.Warnings }; } Trigger <Void> requiresAssemblies; if ((_requiresAssemblies.TryGetValue(pair.Key, out requiresAssemblies) && requiresAssemblies.WasAssigned)) { requiresAssemblies.ClearAssigned(); // If we didn't already update the compilation then do it on demand if (compilation == null) { projectCompilationChanged = UpdateProjectCompilation(project, out compilation); } // Only emit the assembly if there are no errors and // this is the very first time or there were changes if (!compilation.Errors.Any() && (!compilation.HasOutputs || projectCompilationChanged)) { var engine = new NonLoadingLoadContext(); compilation.ProjectReference.Load(engine); compilation.AssemblyBytes = engine.AssemblyBytes ?? new byte[0]; compilation.PdbBytes = engine.PdbBytes ?? new byte[0]; compilation.AssemblyPath = engine.AssemblyPath; } project.Outputs = new OutputsMessage { FrameworkData = project.Sources.Framework, AssemblyBytes = compilation.AssemblyBytes ?? new byte[0], PdbBytes = compilation.PdbBytes ?? new byte[0], AssemblyPath = compilation.AssemblyPath, EmbeddedReferences = compilation.EmbeddedReferences }; if (project.Diagnostics == null) { project.Diagnostics = new DiagnosticsMessage { Framework = project.Sources.Framework, Errors = compilation.Errors, Warnings = compilation.Warnings }; } } } return(true); }
public Highlighter(ProjectCompilation compilation) { _compilation = compilation; }
private void InitializeRoot([NotNull] ProjectRootElement element) { const string profileConditionFlag = "'$(Configuration)|$(Platform)' =="; RootElement = element; BasePropertys = new ProjectBasePropertys(element); ReferenceManager = new ReferenceManager(RootElement); ProjectCompilation = new ProjectCompilation(RootElement, ReferenceManager.UsedItemGroupElements); _projectProfiles = new List<SimpleProjectProfile>(); foreach ( var propertyGroup in element.PropertyGroups.Where( propertyGroup => propertyGroup.Condition.Trim().StartsWith(profileConditionFlag, StringComparison.Ordinal))) { _projectProfiles.Add(new SimpleProjectProfile(this, propertyGroup.Condition.Replace(profileConditionFlag, string.Empty).Trim(' ', '\t', '\''), propertyGroup)); } _projectCollection.Add(this); }
public void UpdateCode(string contentId, TextDiff update, bool highlight) { Task.Run(() => { // updates needs to be processed in the same order they are generated // this method might wait for the next update, thus running in background // thread Content content; var dict = _contentDictionary; lock (dict) { while (update.Update != Volatile.Read(ref _nextUpdate)) { Monitor.Wait(dict); } Interlocked.Increment(ref _nextUpdate); if (!_contentDictionary.TryGetValue(contentId, out content)) { throw new Exception("Content wasn't in dictionary. Illegal code::update sent"); } if (update.Start == 0 && update.Added == content.ContentString.Length && update.Text == content.ContentString) { goto highlight; // editor sends updates when files are opened } var text = content.ContentString; var sb = new StringBuilder().Append(text, 0, update.Start); sb.Append(update.Text); sb.Append(text, update.Start + update.Removed, text.Length - update.Start - update.Removed); text = sb.ToString(); Content old = content; content = content.WithText(text); if (!_contentDictionary.TryUpdate(contentId, content, old)) { throw new Exception("Content has been updated by other method. State inconclusive."); } } // mark dirty MarkTab(contentId, dirty: true); var workspace = _state.Workspace; if (workspace == null) { return; } var proj = workspace.Projects.SingleOrDefault(p => content.RelativePath.StartsWith(p.RelativePath, StringComparison.OrdinalIgnoreCase)); if (proj == null) { return; } _compilations.AddOrUpdate(proj.Id, id => ProjectCompilation.Create(proj.Name, proj.Id), (i, p) => p.InvalidateSources()); highlight: if (highlight) { Highlight(content); } }); }
ProjectCompilation GetCompilation(int id) { Contract.Ensures(Contract.Result <ProjectCompilation>().IsValid); var state = _state; var compilation = _compilations.GetOrAdd(id, i => ProjectCompilation.Create(_state.Workspace.Projects.Single(p => p.Id == i).Name, i)); List <MetadataReference> references = null; Dictionary <int, int> projRefs = null; List <SyntaxTree> sources = null; ProjectEntry proj = null; ConfigurationData configData = null; CSharpParseOptions config = null; ProjectCompilation refComp; if (compilation.IsValid) { foreach (var projectRef in compilation.ProjectReferences) { refComp = GetCompilation(projectRef.Key); if (refComp.Version == projectRef.Value) { continue; } if (references == null) { references = new List <MetadataReference>(); } if (projRefs == null) { projRefs = new Dictionary <int, int>(); } references.Add(refComp.GetMetadataReference()); projRefs.Add(refComp.Id, refComp.Version); } if (references == null) { return(compilation); } } Workspace workspace = state.Workspace; proj = workspace.Projects.Single(p => p.Id == id); // TODO: Use "current configuration" configData = proj.Configurations.Single(c => c.FrameworkName == "net45"); Action <string> addAssembly = path => { if (!File.Exists(path)) { return; } DocumentationProvider doc = null; var docFile = Path.ChangeExtension(path, ".xml"); if (File.Exists(docFile)) { doc = XmlDocumentationProvider.Create(docFile); } references.Add(new MetadataFileReference(path, documentation: doc)); }; if (references != null || compilation.NeedsReferences) { if (references == null) { references = new List <MetadataReference>(); } if (projRefs == null) { projRefs = new Dictionary <int, int>(); } foreach (var package in proj.References) { if (package.Unresolved) { continue; } switch (package.Type) { case "Package": var path = Path.Combine(package.Path, "lib", proj.Configurations.Single(c => c.LongFrameworkName == package.Framework).FrameworkName); if (Directory.Exists(path)) { foreach (var file in Directory.EnumerateFiles(path, "*.dll", SearchOption.TopDirectoryOnly)) { addAssembly(file); } foreach (var file in Directory.EnumerateFiles(path, "*.exe", SearchOption.TopDirectoryOnly)) { addAssembly(file); } } break; case "Assembly": if (File.Exists(package.Path)) { addAssembly(package.Path); } else { // TODO: Implement assemblyneutral types } break; case "Project": // path is dir/project.json var pid = _projectLookup[Path.GetDirectoryName(package.Path)]; if (!projRefs.ContainsKey(pid)) { refComp = GetCompilation(pid); references.Add(refComp.GetMetadataReference()); projRefs.Add(pid, refComp.Version); } break; default: throw new ArgumentException("Unknown reference type"); } } } if (sources != null || compilation.NeedsSources) { if (config == null) { config = CSharpParseOptions.Default .WithLanguageVersion((LanguageVersion)configData.CompilationSettings.LanguageVersion) .WithPreprocessorSymbols(configData.CompilationSettings.Defines) .WithDocumentationMode(DocumentationMode.Parse); } if (sources == null) { sources = new List <SyntaxTree>(); } // TODO: Support generated files foreach (var source in proj.Sources) { var content = _contentDictionary.Values.SingleOrDefault(c => Path.Combine(workspace.Path, c.RelativePath) == source); if (content != null) { sources.Add(CSharpSyntaxTree.ParseText(content.ContentString, path: source, options: config)); } else { sources.Add(CSharpSyntaxTree.ParseFile(source, options: config)); } } } var newComp = compilation.Update(projRefs, references, sources); _compilations.TryUpdate(id, newComp, compilation); return(newComp); }