public override EnvDTE.FileCodeModel GetFileCodeModel(DocumentId documentId)
        {
            if (documentId == null)
            {
                throw new ArgumentNullException(nameof(documentId));
            }

            var project = CurrentSolution.GetProject(documentId.ProjectId);

            if (project == null)
            {
                throw new ArgumentException(ServicesVSResources.The_given_DocumentId_did_not_come_from_the_Visual_Studio_workspace, nameof(documentId));
            }

            var documentFilePath = GetFilePath(documentId);

            if (documentFilePath == null)
            {
                throw new ArgumentException(ServicesVSResources.The_given_DocumentId_did_not_come_from_the_Visual_Studio_workspace, nameof(documentId));
            }

            IProjectCodeModel projectCodeModel = _projectCodeModelFactory.Value.GetProjectCodeModel(project.Id);

            return(projectCodeModel.GetOrCreateFileCodeModel(documentFilePath));
        }
Ejemplo n.º 2
0
            public Project AddProject(string name, string language)
            {
                ProjectInfo projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(null), VersionStamp.Create(), name, name, language);

                OnProjectAdded(projectInfo);
                return(CurrentSolution.GetProject(projectInfo.Id));
            }
        public override Compilation GetCompilation(string assemblyName)
        {
            var project = CurrentSolution.GetProject(ProjectId);

            var parseOptions = CreateParseOptions();
            var trees        = project.Documents.Select(document => SyntaxFactory.ParseSyntaxTree(document.GetTextAsync().Result, parseOptions, string.Empty));

            var compilationOptions = new CSharpCompilationOptions(
                OutputKind.DynamicallyLinkedLibrary,
                mainTypeName: null,
                scriptClassName: null,
                usings: ImmutableArray <string> .Empty,
                optimizationLevel: OptimizationLevel.Debug, // TODO
                checkOverflow: false,                       // TODO
                allowUnsafe: true,                          // TODO
                platform: Platform.AnyCpu,
                warningLevel: 4,
                xmlReferenceResolver: null,
                sourceReferenceResolver: null,
                metadataReferenceResolver: null,
                assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default
                );
            //.WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes),

            var compilation = CSharpCompilation.Create(
                assemblyName, // Assembly name
                trees,
                AllReferences,
                compilationOptions);

            return(compilation);
        }
        public void TryPromoteMiscellaneousDocumentsToProject(Project project)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            var miscProjectInfos = miscDocumentsProjectInfos.Values.ToArray();

            for (var i = 0; i < miscProjectInfos.Length; i++)
            {
                var miscProject = CurrentSolution.GetProject(miscProjectInfos[i].Id);
                var documents   = miscProject.Documents.ToArray();

                for (var j = 0; j < documents.Length; j++)
                {
                    var document = documents[j];
                    if (FileBelongsToProject(document.FilePath, project))
                    {
                        var textLoader   = new DelegatingTextLoader(document);
                        var documentId   = DocumentId.CreateNewId(project.Id);
                        var documentInfo = DocumentInfo.Create(
                            documentId,
                            document.FilePath,
                            filePath: document.FilePath,
                            loader: textLoader);

                        // This transitively will remove the document from the misc project.
                        AddDocument(documentInfo);
                    }
                }
            }
        }
Ejemplo n.º 5
0
 public Task <IReadOnlyList <Diagnostic> > GetDiagnosticsAsync(DocumentId documentId, CancellationToken cancellationToken)
 {
     return(Task.Run(async() =>
     {
         var project = CurrentSolution.GetProject(documentId.ProjectId);
         var compilation = await project.GetCompilationAsync(cancellationToken);
         return (IReadOnlyList <Diagnostic>)compilation.GetDiagnostics(cancellationToken);
     }, cancellationToken));
 }
Ejemplo n.º 6
0
        public Document GetDocument(DocumentId documentId, CancellationToken cancellationToken = default(CancellationToken))
        {
            var project = CurrentSolution.GetProject(documentId.ProjectId);

            if (project == null)
            {
                return(null);
            }
            return(project.GetDocument(documentId));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Finds the <see cref="DocumentId"/> related to the given <see cref="DocumentId"/> that
        /// is in the current context. For regular files (non-shared and non-linked) and closed
        /// linked files, this is always the provided <see cref="DocumentId"/>. For open linked
        /// files and open shared files, the active context is already tracked by the
        /// <see cref="Workspace"/> and can be looked up directly. For closed shared files, the
        /// document in the shared project's <see cref="__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy"/>
        /// is preferred.
        /// </summary>
        internal override DocumentId GetDocumentIdInCurrentContext(DocumentId documentId)
        {
            // If the document is open, then the Workspace knows the current context for both
            // linked and shared files
            if (IsDocumentOpen(documentId))
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            var hostDocument = GetHostDocument(documentId);

            if (hostDocument == null)
            {
                // This can happen if the document was temporary and has since been closed/deleted.
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            var itemId = hostDocument.GetItemId();

            if (itemId == (uint)VSConstants.VSITEMID.Nil)
            {
                // An itemid is required to determine whether the file belongs to a Shared Project
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            // If this is a regular document or a closed linked (non-shared) document, then use the
            // default logic for determining current context.
            var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hostDocument.Project.Hierarchy, itemId);

            if (sharedHierarchy == null)
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            // This is a closed shared document, so we must determine the correct context.
            var hostProject     = LinkedFileUtilities.GetContextHostProject(sharedHierarchy, DeferredState.ProjectTracker);
            var matchingProject = CurrentSolution.GetProject(hostProject.Id);

            if (matchingProject == null || hostProject.Hierarchy == sharedHierarchy)
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            if (matchingProject.ContainsDocument(documentId))
            {
                // The provided documentId is in the current context project
                return(documentId);
            }

            // The current context document is from another project.
            var linkedDocumentIds  = CurrentSolution.GetDocument(documentId).GetLinkedDocumentIds();
            var matchingDocumentId = linkedDocumentIds.FirstOrDefault(id => id.ProjectId == matchingProject.Id);

            return(matchingDocumentId ?? base.GetDocumentIdInCurrentContext(documentId));
        }
Ejemplo n.º 8
0
            public Project AddProject(ProjectInfo projectInfo)
            {
                if (projectInfo == null)
                {
                    throw new ArgumentNullException(nameof(projectInfo));
                }

                OnProjectAdded(projectInfo);
                UpdateReferencesAfterAdd();

                return(CurrentSolution.GetProject(projectInfo.Id));
            }
Ejemplo n.º 9
0
        public async Task <(Project project, List <string> projectReferences, string targetPath)> AddProject(string solutionDir, string projectFile)
        {
            if (buildHost == null)
            {
                buildHost = new MSBuildHost(sdkPath);
            }

            var(info, projectReferences, targetPath) = await buildHost.LoadProject(solutionDir, projectFile);

            OnProjectAdded(info);

            return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath);
        }
Ejemplo n.º 10
0
            public void RemoveMetadataReferences(ProjectId projectId)
            {
                if (projectId == null)
                {
                    throw new ArgumentNullException(nameof(projectId));
                }

                var project = CurrentSolution.GetProject(projectId);

                foreach (var metadataReference in project.MetadataReferences.ToImmutableArray())
                {
                    OnMetadataReferenceRemoved(projectId, metadataReference);
                }
            }
Ejemplo n.º 11
0
        public async Task <ImmutableArray <SymbolRenameResult> > AnalyzeSolutionAsync(
            Func <Project, bool> predicate,
            CancellationToken cancellationToken = default)
        {
            ImmutableArray <ProjectId> projects = CurrentSolution
                                                  .GetProjectDependencyGraph()
                                                  .GetTopologicallySortedProjects(cancellationToken)
                                                  .ToImmutableArray();

            var       results     = new List <ImmutableArray <SymbolRenameResult> >();
            Stopwatch stopwatch   = Stopwatch.StartNew();
            TimeSpan  lastElapsed = TimeSpan.Zero;

            List <RenameScope> renameScopes = GetRenameScopes();

            for (int i = 0; i < renameScopes.Count; i++)
            {
                WriteLine($"Rename {GetPluralName(renameScopes[i])} {$"{i + 1}/{renameScopes.Count}"}", Verbosity.Minimal);

                for (int j = 0; j < projects.Length; j++)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Project project = CurrentSolution.GetProject(projects[j]);

                    if (predicate == null || predicate(project))
                    {
                        WriteLine($"  Rename {GetPluralName(renameScopes[i])} in '{project.Name}' {$"{j + 1}/{projects.Length}"}", ConsoleColors.Cyan, Verbosity.Minimal);

                        ImmutableArray <SymbolRenameResult> projectResults = await AnalyzeProjectAsync(project, renameScopes[i], cancellationToken).ConfigureAwait(false);

                        results.Add(projectResults);

                        WriteLine($"  Done renaming {GetPluralName(renameScopes[i])} in '{project.Name}' in {stopwatch.Elapsed - lastElapsed:mm\\:ss\\.ff}", Verbosity.Normal);
                    }
                    else
                    {
                        WriteLine($"  Skip '{project.Name}' {$"{j + 1}/{projects.Length}"}", ConsoleColors.DarkGray, Verbosity.Minimal);
                    }

                    lastElapsed = stopwatch.Elapsed;
                }
            }

            stopwatch.Stop();

            WriteLine($"Done renaming symbols in solution '{CurrentSolution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal);

            return(results.SelectMany(f => f).ToImmutableArray());
        }
Ejemplo n.º 12
0
        public Task <BuildResult> BuildAsync(DocumentId documentId, CancellationToken cancellationToken)
        {
            return(Task.Run(async() =>
            {
                var project = CurrentSolution.GetProject(documentId.ProjectId);
                var compilation = await project !.GetCompilationAsync(cancellationToken);

                using var peStream = new MemoryStream();
                using var pdbStream = new MemoryStream();
                var result = compilation !.Emit(peStream, pdbStream);
                var inMemoryAssembly = result.Success ? peStream.ToArray() : null;
                var inMemorySymbolStore = result.Success ? pdbStream.ToArray() : null;
                return new BuildResult(result.Diagnostics, inMemoryAssembly, inMemorySymbolStore);
            }, cancellationToken));
        }
Ejemplo n.º 13
0
            public void AddImports(ProjectId projectId, ImmutableArray <string> imports)
            {
                if (projectId == null)
                {
                    throw new ArgumentNullException(nameof(projectId));
                }

                var project            = CurrentSolution.GetProject(projectId);
                var compilationOptions = (CSharpCompilationOptions)project.CompilationOptions;

                SetCurrentSolution(
                    CurrentSolution.WithProjectCompilationOptions(
                        projectId,
                        compilationOptions.WithUsings(imports)));
            }
Ejemplo n.º 14
0
        public virtual Document CreateAndOpenDocument(SourceTextContainer textContainer, Action <SourceText> onTextUpdated)
        {
            var project     = CurrentSolution.GetProject(ProjectId);
            var documentId  = DocumentId.CreateNewId(ProjectId);
            var newSolution = project.Solution.AddDocument(documentId, project.Name, textContainer.CurrentText);

            SetCurrentSolution(newSolution);
            OpenDocument(documentId, textContainer);

            if (null != onTextUpdated)
            {
                _sourceTextChangedHandlers[documentId] = onTextUpdated;
            }

            return(newSolution.GetDocument(documentId));
        }
Ejemplo n.º 15
0
        private void ResolveChildReferences(ProjectId project, ProjectId reference)
        {
            var refer = CurrentSolution.GetProject(reference);

            foreach (var child in refer.AllProjectReferences)
            {
                var proj = CurrentSolution.GetProject(project);

                if (!proj.AllProjectReferences.Contains(child))
                {
                    OnProjectReferenceAdded(project, child);
                }

                ResolveChildReferences(project, child.ProjectId);
            }
        }
Ejemplo n.º 16
0
        protected override void ApplyDocumentAdded(DocumentInfo info, SourceText text)
        {
            var id = info.Id;

            MonoDevelop.Projects.Project mdProject = null;

            if (id.ProjectId != null)
            {
                var project = CurrentSolution.GetProject(id.ProjectId);
                mdProject = GetMonoProject(project);
                if (mdProject == null)
                {
                    LoggingService.LogWarning("Couldn't find project for newly generated file {0} (Project {1}).", info.Name, info.Id.ProjectId);
                }
            }
            var path = DetermineFilePath(info.Id, info.Name, info.FilePath, info.Folders, mdProject?.FileName.ParentDirectory, true);

            string formattedText;
            var    formatter = CodeFormatterService.GetFormatter(DesktopService.GetMimeTypeForUri(path));

            if (formatter != null && mdProject != null)
            {
                formattedText = formatter.FormatText(mdProject.Policies, text.ToString());
            }
            else
            {
                formattedText = text.ToString();
            }

            var textSource = new StringTextSource(formattedText, text.Encoding ?? System.Text.Encoding.UTF8);

            try {
                textSource.WriteTextTo(path);
            } catch (Exception e) {
                LoggingService.LogError("Exception while saving file to " + path, e);
            }

            if (mdProject != null)
            {
                var file = new MonoDevelop.Projects.ProjectFile(path);
                Application.Invoke(delegate {
                    mdProject.Files.Add(file);
                    IdeApp.ProjectOperations.SaveAsync(mdProject);
                });
            }
        }
Ejemplo n.º 17
0
        public async Task <(Project project, List <string> projectReferences, string targetPath)> AddProject(string solutionDir, string projectFile)
        {
            var buildHost = _buildNodes.Take();

            var(info, projectReferences, targetPath) = await buildHost.LoadProject(solutionDir, projectFile);

            _buildNodes.Add(buildHost);

            if (info != null)
            {
                OnProjectAdded(info);
                return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath);
            }
            else
            {
                return(null, projectReferences, targetPath);
            }
        }
        private Document AddDocumentToProject(string filePath, string language, string projectName)
        {
            var project = CurrentSolution.Projects.FirstOrDefault(p => p.Name == projectName && p.Language == language);

            if (project == null)
            {
                var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), projectName, projectName, language);
                OnManagedProjectAdded(projectInfo);
                project = CurrentSolution.GetProject(projectInfo.Id);
            }

            var docInfo = DocumentInfo.Create(DocumentId.CreateNewId(project.Id),
                                              name: Path.GetFileName(filePath),
                                              loader: new FileTextLoader(filePath, null),
                                              filePath: filePath);

            OnDocumentAdded(docInfo);
            return(CurrentSolution.GetDocument(docInfo.Id));
        }
Ejemplo n.º 19
0
        public async Task <(Project project, List <string> projectReferences, string targetPath)> ReevaluateProject(IProject project)
        {
            var proj = project as OmniSharpProject;

            var buildHost = _buildNodes.Take();

            var(info, projectReferences, targetPath) = await buildHost.LoadProject(project.Solution.CurrentDirectory, project.Location, proj.RoslynProject.Id);

            _buildNodes.Add(buildHost);

            if (info != null)
            {
                return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath);
            }
            else
            {
                return(null, projectReferences, targetPath);
            }
        }
Ejemplo n.º 20
0
        protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptions options)
        {
            if (projectId == null)
            {
                throw new ArgumentNullException(nameof(projectId));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService <IParseOptionsService>();

            Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService));

            string newVersion = parseOptionsService.GetLanguageVersion(options);

            GetProjectData(projectId, out var hostProject, out var hierarchy, out var project);
            foreach (string configurationName in (object[])project.ConfigurationManager.ConfigurationRowNames)
            {
                switch (hostProject.Language)
                {
                case LanguageNames.CSharp:
                    var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)project.ConfigurationManager
                                           .ConfigurationRow(configurationName).Item(1).Object;

                    if (newVersion != csharpProperties.LanguageVersion)
                    {
                        csharpProperties.LanguageVersion = newVersion;
                    }
                    break;

                case LanguageNames.VisualBasic:
                    throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options);
                }
            }
        }
Ejemplo n.º 21
0
        protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text)
        {
            var document = GetDocument(id);

            if (document == null)
            {
                return;
            }
            bool isOpen;
            var  filePath = document.FilePath;
            var  data     = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen);

            // Guard against already done changes in linked files.
            // This shouldn't happen but the roslyn merging seems not to be working correctly in all cases :/
            if (document.GetLinkedDocumentIds().Length > 0 && isOpen && !(text.GetType().FullName == "Microsoft.CodeAnalysis.Text.ChangedText"))
            {
                return;
            }
            SourceText formerText;

            if (changedFiles.TryGetValue(filePath, out formerText))
            {
                if (formerText.Length == text.Length && formerText.ToString() == text.ToString())
                {
                    return;
                }
            }
            changedFiles [filePath] = text;

            Projection projection = null;

            foreach (var entry in ProjectionList)
            {
                var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath));
                if (p != null)
                {
                    filePath   = entry.File.FilePath;
                    projection = p;
                    break;
                }
            }
            SourceText oldFile;

            if (!isOpen || !document.TryGetText(out oldFile))
            {
                oldFile = new MonoDevelopSourceText(data);
            }
            var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList();
            int delta   = 0;

            if (!isOpen)
            {
                delta = ApplyChanges(projection, data, changes);
                var    formatter   = CodeFormatterService.GetFormatter(data.MimeType);
                var    mp          = GetMonoProject(CurrentSolution.GetProject(id.ProjectId));
                string currentText = data.Text;

                foreach (var change in changes)
                {
                    delta -= change.Span.Length - change.NewText.Length;
                    var startOffset = change.Span.Start - delta;

                    if (projection != null)
                    {
                        int originalOffset;
                        if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset))
                        {
                            startOffset = originalOffset;
                        }
                    }

                    string str;
                    if (change.NewText.Length == 0)
                    {
                        str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1)));
                    }
                    else
                    {
                        str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length));
                    }
                    data.ReplaceText(startOffset, change.NewText.Length, str);
                }
                data.Save();
                OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue);
                FileService.NotifyFileChanged(filePath);
            }
            else
            {
                var formatter       = CodeFormatterService.GetFormatter(data.MimeType);
                var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0);
                if (documentContext != null)
                {
                    var editor = (TextEditor)data;
                    using (var undo = editor.OpenUndoGroup()) {
                        delta = ApplyChanges(projection, data, changes);

                        foreach (var change in changes)
                        {
                            delta -= change.Span.Length - change.NewText.Length;
                            var startOffset = change.Span.Start - delta;
                            if (projection != null)
                            {
                                int originalOffset;
                                if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset))
                                {
                                    startOffset = originalOffset;
                                }
                            }
                            if (change.NewText.Length == 0)
                            {
                                formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1)));
                            }
                            else
                            {
                                formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length));
                            }
                        }
                    }
                }
                OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue);
                Runtime.RunInMainThread(() => {
                    if (IdeApp.Workbench != null)
                    {
                        foreach (var w in IdeApp.Workbench.Documents)
                        {
                            w.StartReparseThread();
                        }
                    }
                });
            }
        }
        /// <inheritdoc />
        public void UpdateProjectReferences(ProjectId projectId, IEnumerable <ProjectReference> references)
        {
            var roslynProject = CurrentSolution.GetProject(projectId);

            roslynProject = roslynProject.WithProjectReferences(references);
        }
Ejemplo n.º 23
0
        protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text)
        {
            var document = GetDocument(id);

            if (document == null)
            {
                return;
            }
            bool isOpen;
            var  filePath = document.FilePath;

            Projection projection = null;

            foreach (var entry in ProjectionList)
            {
                var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath));
                if (p != null)
                {
                    filePath   = entry.File.FilePath;
                    projection = p;
                    break;
                }
            }

            var data    = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen);
            var oldFile = isOpen ? document.GetTextAsync().Result : new MonoDevelopSourceText(data);
            var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList();
            int delta   = 0;

            if (!isOpen)
            {
                delta = ApplyChanges(projection, data, changes);
                var    formatter   = CodeFormatterService.GetFormatter(data.MimeType);
                var    mp          = GetMonoProject(CurrentSolution.GetProject(id.ProjectId));
                string currentText = data.Text;

                foreach (var change in changes)
                {
                    delta -= change.Span.Length - change.NewText.Length;
                    var startOffset = change.Span.Start - delta;

                    if (projection != null)
                    {
                        int originalOffset;
                        if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset))
                        {
                            startOffset = originalOffset;
                        }
                    }


                    string str;
                    if (change.NewText.Length == 0)
                    {
                        str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1)));
                    }
                    else
                    {
                        str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length));
                    }
                    data.ReplaceText(startOffset, change.NewText.Length, str);
                }
                data.Save();
                OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue);
                FileService.NotifyFileChanged(filePath);
            }
            else
            {
                var formatter       = CodeFormatterService.GetFormatter(data.MimeType);
                var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0);
                if (documentContext != null)
                {
                    var editor = (TextEditor)data;
                    using (var undo = editor.OpenUndoGroup()) {
                        delta = ApplyChanges(projection, data, changes);

                        foreach (var change in changes)
                        {
                            delta -= change.Span.Length - change.NewText.Length;
                            var startOffset = change.Span.Start - delta;

                            if (projection != null)
                            {
                                int originalOffset;
                                if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset))
                                {
                                    startOffset = originalOffset;
                                }
                            }
                            if (change.NewText.Length == 0)
                            {
                                formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1)));
                            }
                            else
                            {
                                formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length));
                            }
                        }
                    }
                }
                OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue);
                Runtime.RunInMainThread(() => {
                    if (IdeApp.Workbench != null)
                    {
                        foreach (var w in IdeApp.Workbench.Documents)
                        {
                            w.StartReparseThread();
                        }
                    }
                });
            }
        }