Example #1
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 #2
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 #3
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 #4
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 #5
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);
        }