async Task FormatFile(Project p, FilePath file)
        {
            string mime = DesktopService.GetMimeTypeForUri(file);

            if (mime == null)
            {
                return;
            }

            var formatter = CodeFormatterService.GetFormatter(mime);

            if (formatter != null)
            {
                try {
                    var content = await TextFileUtility.ReadAllTextAsync(file);

                    var formatted = formatter.FormatText(p.Policies, content.Text);
                    if (formatted != null)
                    {
                        TextFileUtility.WriteText(file, formatted, content.Encoding);
                    }
                } catch (Exception ex) {
                    LoggingService.LogError("File formatting failed", ex);
                }
            }
        }
예제 #2
0
        public void FormatSample()
        {
            var formatter = CodeFormatterService.GetFormatter(CSharpFormatter.MimeType);
            var parent    = new MonoDevelop.Projects.DotNetAssemblyProject();

            parent.Policies.Set <CSharpFormattingPolicy> (policy, CSharpFormatter.MimeType);
            texteditor.Document.Text = formatter.FormatText(parent.Policies, example);
        }
예제 #3
0
        // Returns a stream with the content of the file.
        // project and language parameters are optional
        public virtual Stream CreateFileContent(SolutionItem policyParent, Project project, string language, string fileName, string identifier)
        {
            Dictionary <string, string> tags = new Dictionary <string, string> ();

            ModifyTags(policyParent, project, language, identifier, fileName, ref tags);

            string content = CreateContent(project, tags, language);

            content = StringParserService.Parse(content, tags);
            string        mime      = DesktopService.GetMimeTypeForUri(fileName);
            CodeFormatter formatter = !string.IsNullOrEmpty(mime) ? CodeFormatterService.GetFormatter(mime) : null;

            if (formatter != null)
            {
                var formatted = formatter.FormatText(policyParent != null ? policyParent.Policies : null, content);
                if (formatted != null)
                {
                    content = formatted;
                }
            }

            MemoryStream ms = new MemoryStream();

            byte[] data;
            if (AddStandardHeader)
            {
                string header = StandardHeaderService.GetHeader(policyParent, fileName, true);
                data = System.Text.Encoding.UTF8.GetBytes(header);
                ms.Write(data, 0, data.Length);
            }

            Mono.TextEditor.Document doc = new Mono.TextEditor.Document();
            doc.Text = content;

            TextStylePolicy textPolicy = policyParent != null?policyParent.Policies.Get <TextStylePolicy> ("text/plain")
                                             : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy <TextStylePolicy> ("text/plain");

            string eolMarker = TextStylePolicy.GetEolMarker(textPolicy.EolMarker);

            byte[] eolMarkerBytes = System.Text.Encoding.UTF8.GetBytes(eolMarker);

            var tabToSpaces = textPolicy.TabsToSpaces? new string (' ', textPolicy.TabWidth) : null;

            foreach (Mono.TextEditor.LineSegment line in doc.Lines)
            {
                var lineText = doc.GetTextAt(line.Offset, line.EditableLength);
                if (tabToSpaces != null)
                {
                    lineText = lineText.Replace("\t", tabToSpaces);
                }
                data = System.Text.Encoding.UTF8.GetBytes(lineText);
                ms.Write(data, 0, data.Length);
                ms.Write(eolMarkerBytes, 0, eolMarkerBytes.Length);
            }

            ms.Position = 0;
            return(ms);
        }
        static CodeFormatter GetFormatter(FilePath fileName)
        {
            string mime = DesktopService.GetMimeTypeForUri(fileName);

            if (mime != null)
            {
                return(CodeFormatterService.GetFormatter(mime));
            }

            return(null);
        }
        internal void FormatDocument()
        {
            var formatter = CodeFormatterService.GetFormatter(TextXmlMimeType);

            using (var undo = Editor.OpenUndoGroup()) {
                var loc  = Editor.Caret.Location;
                var text = formatter.FormatText(Document.Project != null ? Document.Project.Policies : null, Editor.Text);
                if (text != null)
                {
                    Editor.Replace(0, Editor.Length, text);
                    Editor.Caret.Location = loc;
                }
            }
        }
예제 #6
0
        internal void FormatDocument()
        {
            var formatter = CodeFormatterService.GetFormatter(TextXmlMimeType);

            Editor.Document.BeginAtomicUndo();
            var loc  = Editor.Caret.Location;
            var text = formatter.FormatText(Document.Project != null ? Document.Project.Policies : null, Editor.Text);

            if (text != null)
            {
                Editor.Replace(0, Editor.Length, text);
                Editor.Caret.Location = loc;
            }
            Editor.Document.EndAtomicUndo();
        }
예제 #7
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);
                });
            }
        }
예제 #8
0
        internal void InsertTemplate(CodeTemplate template, MonoDevelop.Ide.Gui.Document document)
        {
            Document.BeginAtomicUndo();
            var result = template.InsertTemplateContents(document);
            var tle    = new TextLinkEditMode(this, result.InsertPosition, result.TextLinks);

            if (PropertyService.Get("OnTheFlyFormatting", false))
            {
                var prettyPrinter = CodeFormatterService.GetFormatter(Document.MimeType);
                if (prettyPrinter != null)
                {
                    int    endOffset = result.InsertPosition + result.Code.Length;
                    string oldText   = Document.GetTextAt(result.InsertPosition, result.Code.Length);
                    var    policies  = document.Project != null ? document.Project.Policies : null;
                    string text      = prettyPrinter.FormatText(policies, Document.Text, result.InsertPosition, endOffset);

                    if (text != null)
                    {
                        Replace(result.InsertPosition, result.Code.Length, text);
                    }
                    else
                    {
                        //if formatting failed, just use the unformatted text
                        text = oldText;
                    }

                    Caret.Offset = result.InsertPosition + TranslateOffset(oldText, text, Caret.Offset - result.InsertPosition);
                    foreach (TextLink textLink in tle.Links)
                    {
                        foreach (ISegment segment in textLink.Links)
                        {
                            segment.Offset = TranslateOffset(oldText, text, segment.Offset);
                        }
                    }
                }
            }

            if (tle.ShouldStartTextLinkMode)
            {
                tle.OldMode = CurrentMode;
                tle.StartMode();
                CurrentMode = tle;
            }
            Document.EndAtomicUndo();
        }
예제 #9
0
 void HandleTextPaste(int insertionOffset, string text)
 {
     if (PropertyService.Get("OnTheFlyFormatting", false))
     {
         var prettyPrinter = CodeFormatterService.GetFormatter(Document.MimeType);
         if (prettyPrinter != null && ProjectDom != null && text != null)
         {
             try {
                 var    policies = ProjectDom != null && ProjectDom.Project != null ? ProjectDom.Project.Policies : null;
                 string newText  = prettyPrinter.FormatText(policies, Document.Text, insertionOffset, insertionOffset + text.Length);
                 if (!string.IsNullOrEmpty(newText))
                 {
                     Replace(insertionOffset, text.Length, newText);
                     Caret.Offset = insertionOffset + newText.Length;
                 }
             } catch (Exception e) {
                 LoggingService.LogError("Error formatting pasted text", e);
             }
         }
     }
 }
예제 #10
0
        internal void InsertTemplate(CodeTemplate template, MonoDevelop.Ide.Gui.Document document)
        {
            using (var undo = Document.OpenUndoGroup()) {
                var result = template.InsertTemplateContents(document);

                var links = result.TextLinks;
                if (PropertyService.Get("OnTheFlyFormatting", true))
                {
                    var prettyPrinter = CodeFormatterService.GetFormatter(Document.MimeType);
                    if (prettyPrinter != null)
                    {
                        int endOffset = result.InsertPosition + result.Code.Length;
                        //						string oldText = Document.GetTextAt (result.InsertPosition, result.Code.Length);
                        //						var policies = document.Project != null ? document.Project.Policies : null;
                        var oldVersion = Document.Version;
                        prettyPrinter.OnTheFlyFormat(document, result.InsertPosition, endOffset);
                        foreach (var textLink in links)
                        {
                            for (int i = 0; i < textLink.Links.Count; i++)
                            {
                                var segment          = textLink.Links [i];
                                var translatedOffset = oldVersion.MoveOffsetTo(Document.Version, result.InsertPosition + segment.Offset) - result.InsertPosition;
                                textLink.Links [i] = new TextSegment(translatedOffset, segment.Length);
                            }
                        }
                    }
                }

                var tle = new TextLinkEditMode(this, result.InsertPosition, links);
                if (tle.ShouldStartTextLinkMode)
                {
                    tle.OldMode = CurrentMode;
                    tle.StartMode();
                    CurrentMode = tle;
                }
            }
        }
        // Returns a stream with the content of the file.
        // project and language parameters are optional
        public virtual Stream CreateFileContent(SolutionFolderItem policyParent, Project project, string language, string fileName, string identifier)
        {
            var model = CombinedTagModel.GetTagModel(ProjectTagModel, policyParent, project, language, identifier, fileName);

            //HACK: for API compat, CreateContent just gets the override, not the base model
            // but ProcessContent gets the entire model
            string content = CreateContent(project, model.OverrideTags, language);

            content = ProcessContent(content, model);

            string mime      = DesktopService.GetMimeTypeForUri(fileName);
            var    formatter = !string.IsNullOrEmpty(mime) ? CodeFormatterService.GetFormatter(mime) : null;

            if (formatter != null)
            {
                var formatted = formatter.FormatText(policyParent != null ? policyParent.Policies : null, content);
                if (formatted != null)
                {
                    content = formatted;
                }
            }

            var ms = new MemoryStream();

            var bom = Encoding.UTF8.GetPreamble();

            ms.Write(bom, 0, bom.Length);

            byte[] data;
            if (AddStandardHeader)
            {
                string header = StandardHeaderService.GetHeader(policyParent, fileName, true);
                data = System.Text.Encoding.UTF8.GetBytes(header);
                ms.Write(data, 0, data.Length);
            }

            var doc = TextEditorFactory.CreateNewDocument();

            doc.Text = content;

            TextStylePolicy textPolicy = policyParent != null?policyParent.Policies.Get <TextStylePolicy> ("text/plain")
                                             : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy <TextStylePolicy> ("text/plain");

            string eolMarker = TextStylePolicy.GetEolMarker(textPolicy.EolMarker);

            byte[] eolMarkerBytes = System.Text.Encoding.UTF8.GetBytes(eolMarker);

            var tabToSpaces = textPolicy.TabsToSpaces? new string (' ', textPolicy.TabWidth) : null;

            foreach (var line in doc.GetLines())
            {
                var lineText = doc.GetTextAt(line.Offset, line.Length);
                if (tabToSpaces != null)
                {
                    lineText = lineText.Replace("\t", tabToSpaces);
                }
                data = System.Text.Encoding.UTF8.GetBytes(lineText);
                ms.Write(data, 0, data.Length);
                ms.Write(eolMarkerBytes, 0, eolMarkerBytes.Length);
            }

            ms.Position = 0;
            return(ms);
        }
예제 #12
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();
                        }
                    }
                });
            }
        }
        /// <summary>
        /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead.
        /// </summary>
        public TemplateResult InsertTemplateContents(MonoDevelop.Ide.Gui.Document document)
        {
            Mono.TextEditor.TextEditorData data = document.Editor;

            int offset = data.Caret.Offset;
//			string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine);

            var context = new TemplateContext
            {
                Template       = this,
                Document       = document,
                ParsedDocument = document.ParsedDocument != null ? document.ParsedDocument.ParsedFile : null,
                InsertPosition = data.Caret.Location,
                LineIndent     = data.Document.GetLineIndent(data.Caret.Line),
                TemplateCode   = Code
            };

            if (data.IsSomethingSelected)
            {
                int start = data.SelectionRange.Offset;
                while (Char.IsWhiteSpace(data.Document.GetCharAt(start)))
                {
                    start++;
                }
                int end = data.SelectionRange.EndOffset;
                while (Char.IsWhiteSpace(data.Document.GetCharAt(end - 1)))
                {
                    end--;
                }
                context.LineIndent   = data.Document.GetLineIndent(data.Document.OffsetToLineNumber(start));
                context.SelectedText = RemoveIndent(data.Document.GetTextBetween(start, end), context.LineIndent);
                data.Remove(start, end - start);
                offset = start;
            }
            else
            {
                string word = GetWordBeforeCaret(data).Trim();
                if (word.Length > 0)
                {
                    offset = DeleteWordBeforeCaret(data);
                }
            }

            TemplateResult template = FillVariables(context);

            template.InsertPosition = offset;
            document.Editor.Insert(offset, template.Code);

            int newoffset;

            if (template.CaretEndOffset >= 0)
            {
                newoffset = offset + template.CaretEndOffset;
            }
            else
            {
                newoffset = offset + template.Code.Length;
            }

            document.Editor.Caret.Location = document.Editor.OffsetToLocation(newoffset);

            var prettyPrinter = CodeFormatterService.GetFormatter(data.MimeType);

            if (prettyPrinter != null)
            {
                int endOffset  = template.InsertPosition + template.Code.Length;
                var oldVersion = data.Version;
                prettyPrinter.OnTheFlyFormat(document, template.InsertPosition, endOffset);
                foreach (var textLink in template.TextLinks)
                {
                    for (int i = 0; i < textLink.Links.Count; i++)
                    {
                        var segment          = textLink.Links [i];
                        var translatedOffset = oldVersion.MoveOffsetTo(data.Version, template.InsertPosition + segment.Offset) - template.InsertPosition;
                        textLink.Links [i] = new TextSegment(translatedOffset, segment.Length);
                    }
                }
            }
            return(template);
        }
예제 #14
0
        public TemplateResult FillVariables(TemplateContext context)
        {
            var    expansion  = CodeTemplateService.GetExpansionObject(this);
            var    result     = new TemplateResult();
            var    sb         = new StringBuilder();
            int    lastOffset = 0;
            string code       = context.Document.Editor.FormatString(context.InsertPosition, context.TemplateCode);

            result.TextLinks = new List <TextLink> ();
            foreach (Match match in variableRegEx.Matches(code))
            {
                string name = match.Groups [1].Value;
                sb.Append(code.Substring(lastOffset, match.Index - lastOffset));
                lastOffset = match.Index + match.Length;
                if (string.IsNullOrEmpty(name))                    // $$ is interpreted as $
                {
                    sb.Append("$");
                }
                else if (name == "end")
                {
                    result.CaretEndOffset = sb.Length;
                }
                else if (name == "selected")
                {
                    if (!string.IsNullOrEmpty(context.SelectedText))
                    {
                        string indent    = GetIndent(sb);
                        string selection = Reindent(context.SelectedText, indent);
                        sb.Append(selection);
                    }
                }
                if (!variableDecarations.ContainsKey(name))
                {
                    continue;
                }
                TextLink link  = result.TextLinks.Find(l => l.Name == name);
                bool     isNew = link == null;
                if (isNew)
                {
                    link = new TextLink(name);
                    if (!string.IsNullOrEmpty(variableDecarations [name].ToolTip))
                    {
                        link.Tooltip = GettextCatalog.GetString(variableDecarations [name].ToolTip);
                    }
                    link.Values = new CodeTemplateListDataProvider(variableDecarations [name].Values);
                    if (!string.IsNullOrEmpty(variableDecarations [name].Function))
                    {
                        link.Values = expansion.RunFunction(context, null, variableDecarations [name].Function);
                    }
                    result.TextLinks.Add(link);
                }
                link.IsEditable   = variableDecarations [name].IsEditable;
                link.IsIdentifier = variableDecarations [name].IsIdentifier;
                if (!string.IsNullOrEmpty(variableDecarations [name].Function))
                {
                    IListDataProvider <string> functionResult = expansion.RunFunction(context, null, variableDecarations [name].Function);
                    if (functionResult != null && functionResult.Count > 0)
                    {
                        string s = (string)functionResult [functionResult.Count - 1];
                        if (s == null)
                        {
                            if (variableDecarations.ContainsKey(name))
                            {
                                s = variableDecarations [name].Default;
                            }
                        }
                        if (s != null)
                        {
                            link.AddLink(new TextSegment(sb.Length, s.Length));
                            if (isNew)
                            {
                                link.GetStringFunc = delegate(Func <string, string> callback) {
                                    return(expansion.RunFunction(context, callback, variableDecarations [name].Function));
                                };
                            }
                            sb.Append(s);
                        }
                    }
                    else
                    {
                        AddDefaultValue(sb, link, name);
                    }
                }
                else
                {
                    AddDefaultValue(sb, link, name);
                }
            }
            sb.Append(code.Substring(lastOffset, code.Length - lastOffset));

            // format & indent template code
            var data = new TextEditorData();

            data.Text = sb.ToString();
            data.Document.TextReplaced += delegate(object sender, DocumentChangeEventArgs e) {
                int delta = e.ChangeDelta;

                foreach (var link in result.TextLinks)
                {
                    link.Links = new List <TextSegment> (link.Links.AdjustSegments(e));
                }
                if (result.CaretEndOffset > e.Offset)
                {
                    result.CaretEndOffset += delta;
                }
            };

            var formatter = CodeFormatterService.GetFormatter(context.Document.Editor.Document.MimeType);

            if (formatter != null && context.Document.HasProject)
            {
                formatter.OnTheFlyFormat(context.Document, 0, data.Length);
            }

            IndentCode(data, context.LineIndent);
            result.Code = data.Text;
            data.Dispose();
            return(result);
        }
예제 #15
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();
                        }
                    }
                });
            }
        }
예제 #16
0
        /// <summary>
        /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead.
        /// </summary>
        public TemplateResult InsertTemplateContents(TextEditor editor, DocumentContext context)
        {
            var data = editor;

            int offset = data.CaretOffset;
//			string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine);

            var templateCtx = new TemplateContext {
                Template        = this,
                DocumentContext = context,
                Editor          = editor,
                //ParsedDocument = context.ParsedDocument != null ? context.ParsedDocument.ParsedFile : null,
                InsertPosition = data.CaretLocation,
                LineIndent     = data.GetLineIndent(data.CaretLocation.Line),
                TemplateCode   = Code
            };

            if (data.IsSomethingSelected)
            {
                int start = data.SelectionRange.Offset;
                while (Char.IsWhiteSpace(data.GetCharAt(start)))
                {
                    start++;
                }
                int end = data.SelectionRange.EndOffset;
                while (Char.IsWhiteSpace(data.GetCharAt(end - 1)))
                {
                    end--;
                }
                templateCtx.LineIndent   = data.GetLineIndent(data.OffsetToLineNumber(start));
                templateCtx.SelectedText = RemoveIndent(data.GetTextBetween(start, end), templateCtx.LineIndent);
                data.RemoveText(start, end - start);
                offset = start;
            }
            else
            {
                string word = GetTemplateShortcutBeforeCaret(data).Trim();
                if (word.Length > 0)
                {
                    offset = DeleteTemplateShortcutBeforeCaret(data);
                }
            }

            TemplateResult template = FillVariables(templateCtx);

            template.InsertPosition = offset;
            editor.InsertText(offset, template.Code);

            int newoffset;

            if (template.CaretEndOffset >= 0)
            {
                newoffset = offset + template.CaretEndOffset;
            }
            else
            {
                newoffset = offset + template.Code.Length;
            }

            editor.CaretLocation = editor.OffsetToLocation(newoffset);

            var prettyPrinter = CodeFormatterService.GetFormatter(data.MimeType);

            if (prettyPrinter != null && prettyPrinter.SupportsOnTheFlyFormatting)
            {
                int endOffset  = template.InsertPosition + template.Code.Length;
                var oldVersion = data.Version;
                prettyPrinter.OnTheFlyFormat(editor, context, TextSegment.FromBounds(template.InsertPosition, editor.CaretOffset));
                if (editor.CaretOffset < endOffset)
                {
                    prettyPrinter.OnTheFlyFormat(editor, context, TextSegment.FromBounds(editor.CaretOffset, endOffset));
                }

                foreach (var textLink in template.TextLinks)
                {
                    for (int i = 0; i < textLink.Links.Count; i++)
                    {
                        var segment          = textLink.Links [i];
                        var translatedOffset = oldVersion.MoveOffsetTo(data.Version, template.InsertPosition + segment.Offset) - template.InsertPosition;
                        textLink.Links [i] = new TextSegment(translatedOffset, segment.Length);
                    }
                }
            }
            return(template);
        }
        // Returns a stream with the content of the file.
        // project and language parameters are optional
        public virtual async Task <Stream> CreateFileContentAsync(SolutionFolderItem policyParent, Project project, string language, string fileName, string identifier)
        {
            var model = CombinedTagModel.GetTagModel(ProjectTagModel, policyParent, project, language, identifier, fileName);

            //HACK: for API compat, CreateContent just gets the override, not the base model
            // but ProcessContent gets the entire model
            string content = CreateContent(project, model.OverrideTags, language);

            content = ProcessContent(content, model);

            string mime      = DesktopService.GetMimeTypeForUri(fileName);
            var    formatter = !string.IsNullOrEmpty(mime) ? CodeFormatterService.GetFormatter(mime) : null;

            if (formatter != null)
            {
                var formatted = formatter.FormatText(policyParent != null ? policyParent.Policies : null, content);
                if (formatted != null)
                {
                    content = formatted;
                }
            }

            var             ms         = new MemoryStream();
            Encoding        encoding   = null;
            TextStylePolicy textPolicy = policyParent != null?policyParent.Policies.Get <TextStylePolicy> (mime ?? "text/plain")
                                             : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy <TextStylePolicy> (mime ?? "text/plain");

            string eolMarker = TextStylePolicy.GetEolMarker(textPolicy.EolMarker);

            var ctx = await EditorConfigService.GetEditorConfigContext(fileName);

            if (ctx != null)
            {
                ctx.CurrentConventions.UniversalConventions.TryGetEncoding(out encoding);
                if (ctx.CurrentConventions.UniversalConventions.TryGetLineEnding(out string lineEnding))
                {
                    eolMarker = lineEnding;
                }
            }
            if (encoding == null)
            {
                encoding = System.Text.Encoding.UTF8;
            }
            var bom = encoding.GetPreamble();

            if (bom != null && bom.Length > 0)
            {
                ms.Write(bom, 0, bom.Length);
            }

            byte[] data;
            if (AddStandardHeader)
            {
                string header = StandardHeaderService.GetHeader(policyParent, fileName, true);
                data = encoding.GetBytes(header);
                ms.Write(data, 0, data.Length);
            }

            var doc = TextEditorFactory.CreateNewDocument();

            doc.Text = content;


            byte[] eolMarkerBytes = encoding.GetBytes(eolMarker);

            var           tabToSpaces = textPolicy.TabsToSpaces? new string (' ', textPolicy.TabWidth) : null;
            IDocumentLine lastLine    = null;

            foreach (var line in doc.GetLines())
            {
                var lineText = doc.GetTextAt(line.Offset, line.Length);
                if (tabToSpaces != null)
                {
                    lineText = lineText.Replace("\t", tabToSpaces);
                }
                if (line.LengthIncludingDelimiter > 0)
                {
                    data = encoding.GetBytes(lineText);
                    ms.Write(data, 0, data.Length);
                    ms.Write(eolMarkerBytes, 0, eolMarkerBytes.Length);
                }
                lastLine = line;
            }
            if (ctx != null && lastLine != null && lastLine.Length > 0)
            {
                if (ctx.CurrentConventions.UniversalConventions.TryGetRequireFinalNewline(out bool requireNewLine))
                {
                    if (requireNewLine)
                    {
                        ms.Write(eolMarkerBytes, 0, eolMarkerBytes.Length);
                    }
                }
            }

            ms.Position = 0;
            return(ms);
        }