mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-30 05:36:44 +00:00
clang-format-vsix: add command to format document
Bound to Ctrl+R, Ctrl+D by default. Also added section on how to debug the extension to the Readme. Differential Revision: https://reviews.llvm.org/D27501 llvm-svn: 289910
This commit is contained in:
parent
5ccb65f77d
commit
7703ddd48e
1
clang/tools/clang-format-vs/.gitignore
vendored
1
clang/tools/clang-format-vs/.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
# Visual Studio files
|
# Visual Studio files
|
||||||
.vs/
|
.vs/
|
||||||
|
*.user
|
||||||
/packages/
|
/packages/
|
||||||
/ClangFormat/obj/
|
/ClangFormat/obj/
|
||||||
/ClangFormat/bin/
|
/ClangFormat/bin/
|
||||||
|
@ -61,15 +61,21 @@
|
|||||||
<CommandFlag>DynamicVisibility</CommandFlag>
|
<CommandFlag>DynamicVisibility</CommandFlag>
|
||||||
If you do not want an image next to your command, remove the Icon node /> -->
|
If you do not want an image next to your command, remove the Icon node /> -->
|
||||||
|
|
||||||
<Button guid="guidClangFormatCmdSet" id="cmdidClangFormat" priority="0x0100" type="Button">
|
<Button guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" priority="0x0100" type="Button">
|
||||||
<Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />
|
<Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />
|
||||||
<Icon guid="guidImages" id="bmpPic1" />
|
<Icon guid="guidImages" id="bmpPic1" />
|
||||||
<Strings>
|
<Strings>
|
||||||
<ButtonText>ClangFormat</ButtonText>
|
<ButtonText>Clang Format Selection</ButtonText>
|
||||||
</Strings>
|
</Strings>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" priority="0x0101" type="Button">
|
||||||
|
<Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />
|
||||||
|
<Icon guid="guidImages" id="bmpPic2" />
|
||||||
|
<Strings>
|
||||||
|
<ButtonText>Clang Format Document</ButtonText>
|
||||||
|
</Strings>
|
||||||
|
</Button>
|
||||||
|
|
||||||
</Buttons>
|
</Buttons>
|
||||||
|
|
||||||
@ -88,7 +94,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<KeyBindings>
|
<KeyBindings>
|
||||||
<KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormat" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>
|
<KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>
|
||||||
|
<KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" editor="guidTextEditor" key1="R" mod1="Control" key2="D" mod2="Control"/>
|
||||||
</KeyBindings>
|
</KeyBindings>
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +108,8 @@
|
|||||||
<GuidSymbol name="guidClangFormatCmdSet" value="{e39cbab1-0f96-4022-a2bc-da5a9db7eb78}">
|
<GuidSymbol name="guidClangFormatCmdSet" value="{e39cbab1-0f96-4022-a2bc-da5a9db7eb78}">
|
||||||
|
|
||||||
<IDSymbol name="MyMenuGroup" value="0x1020" />
|
<IDSymbol name="MyMenuGroup" value="0x1020" />
|
||||||
<IDSymbol name="cmdidClangFormat" value="0x0100" />
|
<IDSymbol name="cmdidClangFormatSelection" value="0x0100" />
|
||||||
|
<IDSymbol name="cmdidClangFormatDocument" value="0x0101" />
|
||||||
</GuidSymbol>
|
</GuidSymbol>
|
||||||
|
|
||||||
<GuidSymbol name="guidTextEditor" value="{8B382828-6202-11d1-8870-0000F87579D2}" />
|
<GuidSymbol name="guidTextEditor" value="{8B382828-6202-11d1-8870-0000F87579D2}" />
|
||||||
|
@ -180,14 +180,43 @@ namespace LLVM.ClangFormat
|
|||||||
var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
|
var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
|
||||||
if (commandService != null)
|
if (commandService != null)
|
||||||
{
|
{
|
||||||
var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormat);
|
{
|
||||||
var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
|
var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatSelection);
|
||||||
commandService.AddCommand(menuItem);
|
var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
|
||||||
|
commandService.AddCommand(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatDocument);
|
||||||
|
var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
|
||||||
|
commandService.AddCommand(menuItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void MenuItemCallback(object sender, EventArgs args)
|
private void MenuItemCallback(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
var mc = sender as System.ComponentModel.Design.MenuCommand;
|
||||||
|
if (mc == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mc.CommandID.ID)
|
||||||
|
{
|
||||||
|
case (int)PkgCmdIDList.cmdidClangFormatSelection:
|
||||||
|
FormatSelection();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (int)PkgCmdIDList.cmdidClangFormatDocument:
|
||||||
|
FormatDocument();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs clang-format on the current selection
|
||||||
|
/// </summary>
|
||||||
|
private void FormatSelection()
|
||||||
{
|
{
|
||||||
IWpfTextView view = GetCurrentView();
|
IWpfTextView view = GetCurrentView();
|
||||||
if (view == null)
|
if (view == null)
|
||||||
@ -197,24 +226,40 @@ namespace LLVM.ClangFormat
|
|||||||
int start = view.Selection.Start.Position.GetContainingLine().Start.Position;
|
int start = view.Selection.Start.Position.GetContainingLine().Start.Position;
|
||||||
int end = view.Selection.End.Position.GetContainingLine().End.Position;
|
int end = view.Selection.End.Position.GetContainingLine().End.Position;
|
||||||
int length = end - start;
|
int length = end - start;
|
||||||
|
|
||||||
// clang-format doesn't support formatting a range that starts at the end
|
// clang-format doesn't support formatting a range that starts at the end
|
||||||
// of the file.
|
// of the file.
|
||||||
if (start >= text.Length && text.Length > 0)
|
if (start >= text.Length && text.Length > 0)
|
||||||
start = text.Length - 1;
|
start = text.Length - 1;
|
||||||
string path = GetDocumentParent(view);
|
string path = GetDocumentParent(view);
|
||||||
string filePath = GetDocumentPath(view);
|
string filePath = GetDocumentPath(view);
|
||||||
|
|
||||||
|
RunClangFormatAndApplyReplacements(text, start, length, path, filePath, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs clang-format on the current document
|
||||||
|
/// </summary>
|
||||||
|
private void FormatDocument()
|
||||||
|
{
|
||||||
|
IWpfTextView view = GetCurrentView();
|
||||||
|
if (view == null)
|
||||||
|
// We're not in a text view.
|
||||||
|
return;
|
||||||
|
|
||||||
|
string filePath = GetDocumentPath(view);
|
||||||
|
var path = Path.GetDirectoryName(filePath);
|
||||||
|
string text = view.TextBuffer.CurrentSnapshot.GetText();
|
||||||
|
|
||||||
|
RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunClangFormatAndApplyReplacements(string text, int offset, int length, string path, string filePath, IWpfTextView view)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var root = XElement.Parse(RunClangFormat(text, start, length, path, filePath));
|
string replacements = RunClangFormat(text, offset, length, path, filePath);
|
||||||
var edit = view.TextBuffer.CreateEdit();
|
ApplyClangFormatReplacements(replacements, view);
|
||||||
foreach (XElement replacement in root.Descendants("replacement"))
|
|
||||||
{
|
|
||||||
var span = new Span(
|
|
||||||
int.Parse(replacement.Attribute("offset").Value),
|
|
||||||
int.Parse(replacement.Attribute("length").Value));
|
|
||||||
edit.Replace(span, replacement.Value);
|
|
||||||
}
|
|
||||||
edit.Apply();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -304,6 +349,27 @@ namespace LLVM.ClangFormat
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the clang-format replacements (xml) to the current view
|
||||||
|
/// </summary>
|
||||||
|
private void ApplyClangFormatReplacements(string replacements, IWpfTextView view)
|
||||||
|
{
|
||||||
|
// clang-format returns no replacements if input text is empty
|
||||||
|
if (replacements.Length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var root = XElement.Parse(replacements);
|
||||||
|
var edit = view.TextBuffer.CreateEdit();
|
||||||
|
foreach (XElement replacement in root.Descendants("replacement"))
|
||||||
|
{
|
||||||
|
var span = new Span(
|
||||||
|
int.Parse(replacement.Attribute("offset").Value),
|
||||||
|
int.Parse(replacement.Attribute("length").Value));
|
||||||
|
edit.Replace(span, replacement.Value);
|
||||||
|
}
|
||||||
|
edit.Apply();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the currently active view if it is a IWpfTextView.
|
/// Returns the currently active view if it is a IWpfTextView.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
static class PkgCmdIDList
|
static class PkgCmdIDList
|
||||||
{
|
{
|
||||||
public const uint cmdidClangFormat = 0x100;
|
public const uint cmdidClangFormatSelection = 0x100;
|
||||||
|
public const uint cmdidClangFormatDocument = 0x101;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -25,3 +25,27 @@ directory so they can be bundled with the plug-in, as well as creating
|
|||||||
ClangFormat/source.extension.vsixmanifest. Once the plug-in has been built with
|
ClangFormat/source.extension.vsixmanifest. Once the plug-in has been built with
|
||||||
CMake once, it can be built manually from the ClangFormat.sln solution in Visual
|
CMake once, it can be built manually from the ClangFormat.sln solution in Visual
|
||||||
Studio.
|
Studio.
|
||||||
|
|
||||||
|
===========
|
||||||
|
Debugging
|
||||||
|
===========
|
||||||
|
|
||||||
|
Once you've built the clang_format_vsix project from LLVM.sln at least once,
|
||||||
|
open ClangFormat.sln in Visual Studio, then:
|
||||||
|
|
||||||
|
- Make sure the "Debug" target is selected
|
||||||
|
- Open the ClangFormat project properties
|
||||||
|
- Select the Debug tab
|
||||||
|
- Set "Start external program:" to where your devenv.exe is installed. Typically
|
||||||
|
it's "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
|
||||||
|
- Set "Command line arguments" to: /rootsuffix Exp
|
||||||
|
- You can now set breakpoints if you like
|
||||||
|
- Press F5 to build and run with debugger
|
||||||
|
|
||||||
|
If all goes well, a new instance of Visual Studio will be launched in a special
|
||||||
|
mode where it uses the experimental hive instead of the normal configuration hive.
|
||||||
|
By default, when you build a VSIX project in Visual Studio, it auto-registers the
|
||||||
|
extension in the experimental hive, allowing you to test it. In the new Visual Studio
|
||||||
|
instance, open or create a C++ solution, and you should now see the Clang Format
|
||||||
|
entries in the Tool menu. You can test it out, and any breakpoints you set will be
|
||||||
|
hit where you can debug as usual.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user