Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Code Formatter
#1
Library to format code with a lot of build in options and styles. OC site to all avaliable options: https://astyle.sourceforge.net/astyle.ht...ace_Styles
 
Code:
Copy      Help
// AStyleInterface.cs
/// AStyleInterface contains methods to call the Artistic Style formatter.
public class AStyleInterface
{
    // Dll name
private const string SOLIBVER = "3.2.0";
private const string dllName = "AStyle32.dll";
    /// AStyleGetVersion DllImport.
    /// Cannot use string as a return value because Mono runtime will attempt to
    /// free the returned pointer resulting in a runtime crash.
    /// NOTE: CharSet.Unicode is NOT used here.
    [DllImport(dllName)]
    private static extern IntPtr AStyleGetVersion();

    /// AStyleMainUtf16 DllImport.
    /// Cannot use string as a return value because Mono runtime will attempt to
    /// free the returned pointer resulting in a runtime crash.
    /// NOTE: CharSet.Unicode and wide strings ARE used here.
    [DllImport(dllName, CharSet = CharSet.Unicode)]
    private static extern IntPtr AStyleMainUtf16(
        [
MarshalAs(UnmanagedType.LPWStr)] string textIn,
        [
MarshalAs(UnmanagedType.LPWStr)] string options,
        AStyleErrorDelgate AStyleError,
        AStyleMemAllocDelgate AStyleMemAlloc
    );

    /// AStyleMainUtf16 callbacks.
    /// NOTE: Wide strings are NOT used here.
    private delegate void AStyleErrorDelgate(
        int errorNum,
        [
MarshalAs(UnmanagedType.LPStr)] string error
    );
    private delegate IntPtr AStyleMemAllocDelgate(int size);

    /// Error handler to abort the program.
    private void Error(string message)
    {

        print.it(message);
        print.it("The program has terminated!");
        Environment.Exit(1);
    }


    /// Call the AStyleMainUtf16 function in Artistic Style.
    /// An empty string is returned on error.
    public string FormatSource(string textIn, string options)
    {

        // Return the allocated string
        // Memory space is allocated by AStyleMemAlloc, a callback function

        string sTextOut = String.Empty;

        try
        {
            IntPtr pText = AStyleMainUtf16(textIn, options,
                                           AStyleError, AStyleMemAlloc);

            if (pText != IntPtr.Zero)
            {

                sTextOut = Marshal.PtrToStringUni(pText);
                Marshal.FreeHGlobal(pText);
            }
        }

        catch (BadImageFormatException e)
        {

            print.it(e.ToString());
            Error("You may be mixing 32 and 64 bit code!");
        }

        catch (DllNotFoundException)
        {

            //print.it(e.ToString());
            Error("Cannot load native library: " + dllName);
        }

        catch (Exception e)
        {

            Error(e.ToString());
        }


        return sTextOut;
    }


    /// Get the Artistic Style version number.
    public string GetVersion()
    {

        string sVersion = String.Empty;

        try
        {
            IntPtr pVersion = AStyleGetVersion();

            if (pVersion != IntPtr.Zero)
            {

                sVersion = Marshal.PtrToStringAnsi(pVersion);
            }
        }

        catch (BadImageFormatException e)
        {

            print.it(e.ToString());
            Error("You may be mixing 32 and 64 bit code!");
        }

        catch (DllNotFoundException)
        {

            //print.it(e.ToString());
            Error("Cannot load native library: " + dllName);
        }

        catch (Exception e)
        {

            Error(e.ToString());
        }


        return sVersion;
    }


    /// AStyleMainUtf16 callback to allocate memory for the return string.
    private IntPtr AStyleMemAlloc(int size)
    {

        return Marshal.AllocHGlobal(size);
    }


    /// AStyleMainUtf16 callback to display errors from Artistic Style.
    private void AStyleError(int errorNumber, string error)
    {

        print.it("AStyle error " + errorNumber + "\n" + error);
    }

}
   // class AStyleInterface

Usage example, formatting the active doc in LA:
 
Code:
Copy      Help
/*/
role editorExtension;
testInternal Au.Editor;
r Au.Editor.dll;
r Au.Controls.dll;
c \AStyleInterface.cs;
/*/


using Au.Controls;

var activeDoc = Panels.Editor.ZActiveDoc;
var aStyle = new AStyleInterface();

activeDoc.zText = aStyle.FormatSource(activeDoc.zText, "style=allman");


Attached Files
.zip   AStyle.zip (Size: 3.6 MB / Downloads: 144)
#2
In LA 0.13 renamed some functions used in the example.

Code:
Copy      Help
/*/
role editorExtension;
testInternal Au.Editor;
r Au.Editor.dll;
r Au.Controls.dll;
c \AStyleInterface.cs;
/*/


using Au.Controls;

var activeDoc = Panels.Editor.ActiveDoc;
var aStyle = new AStyleInterface();

activeDoc.aaaText = aStyle.FormatSource(activeDoc.aaaText, "style=allman");
#3
AStyle does not support some C# features, for example verbatim and raw strings. Damages these strings.

Workaround: with Roslyn find these strings and replace with safe strings. After formatting restore.

Code:
Copy      Help
// script "AStyle.cs"
/*/
role editorExtension;
testInternal Au.Editor;
r Au.Editor.dll;
r Au.Controls.dll;
c \AStyleInterface.cs;
r Roslyn\Microsoft.CodeAnalysis.dll;
r Roslyn\Microsoft.CodeAnalysis.CSharp.dll;
/*/

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.CSharp.Syntax;

//print.clear();
if (!CodeInfo.GetContextAndDocument(out var cd, metaToo: true)) return;
var text = cd.code;

var a = new List<(TextSpan, string)>();
foreach (var n in cd.syntaxRoot.DescendantNodes()) {
    //CiUtil.PrintNode(n);
    switch (n) {
    case LiteralExpressionSyntax when n.Kind() is SyntaxKind.StringLiteralExpression or SyntaxKind.Utf8StringLiteralExpression:
    case InterpolatedStringExpressionSyntax:
        //CiUtil.PrintNode(n.GetFirstToken());
        var span = n.Span;
        if (n.GetFirstToken().Kind() is SyntaxKind.StringLiteralToken && text[span.Start] != '@') continue; //simple string
        a.Add((span, text[span.Start..span.End]));
        break;
    }
}

//print.it(a);
if (a.Count > 0) {
    var b = new StringBuilder();
    int end = 0, i = 0;
    foreach (var (v, s) in a) {
        b.Append(text, end, v.Start - end);
        b.AppendFormat("\"\x1{0}\"", i++);
        end = v.End;
    }

    b.Append(text, end, text.Length - end);
    text = b.ToString();
}


var aStyle = new AStyleInterface();
text = aStyle.FormatSource(text, "style=allman");

if (a.Count > 0) {
    text = text.RxReplace(@"""\x1\d+""", m => a[text.ToInt(m.Start + 2)].Item2);
    //print.it(text);
}

Panels.Editor.ActiveDoc.EReplaceTextGently(text);



#region code to format

class C {
    public void F() {
        var a = @"verbatim
string F() {
}"
;
        
        a = """
raw
string F() {
}
"""
;
        
        a = $"""
raw
string F()
{1
            + 2}
"""
;
        
        var b = @"UTF-8
string F() {
}"u8
;
    }
}


//TODO: in the same way escape #if-disabled code
#if DEBUG
class D {
    
}
#else
class D {
    
}

#endif

#endregion


Forum Jump:


Users browsing this thread: 1 Guest(s)