Example #1
0
        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));
        }
Example #2
0
        /// <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);
        }
Example #3
0
        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());
        }
Example #4
0
        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());
        }
Example #5
0
        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);
            });
        }
Example #6
0
        /// <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);
        }
Example #7
0
        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}");
            }
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
 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);
        }
Example #14
0
        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);
                }
            });
        }
Example #15
0
        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);
        }