public override void VisitClassDeclaration(ClassDeclarationSyntax node) { string className = node.Identifier.ToString(); _visitingClass = className; var docComment = node.GetLeadingTrivia().Select(i => i.GetStructure()).OfType <DocumentationCommentTriviaSyntax>().FirstOrDefault(); RhinoCommonClass.Get(className).AddClassComment(docComment); base.VisitClassDeclaration(node); }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { var classDeclaration = node.Parent as ClassDeclarationSyntax; if (classDeclaration != null) { _visitingClass = classDeclaration.Identifier.ToString(); } { bool isPublic = node.IsPublic(); bool isStatic = node.IsStatic(); if (isPublic) { // skip methods with ref parameters of multiple out parameters for now int refCount = 0; int outCount = 0; foreach (var parameter in node.ParameterList.Parameters) { foreach (var modifier in parameter.Modifiers) { if (modifier.Text == "ref") { refCount++; } if (modifier.Text == "out") { outCount++; } } } if (refCount == 0 && outCount < 2) { var docComment = node.GetLeadingTrivia().Select(i => i.GetStructure()).OfType <DocumentationCommentTriviaSyntax>().FirstOrDefault(); RhinoCommonClass.Get(_visitingClass).Methods.Add(new Tuple <MethodDeclarationSyntax, DocumentationCommentTriviaSyntax>(node, docComment)); } } } base.VisitMethodDeclaration(node); }
public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) { var classDeclaration = node.Parent as ClassDeclarationSyntax; if (classDeclaration != null) { _visitingClass = classDeclaration.Identifier.ToString(); } { bool isPublic = node.IsPublic(); if (isPublic) { var docComment = node.GetLeadingTrivia().Select(i => i.GetStructure()).OfType <DocumentationCommentTriviaSyntax>().FirstOrDefault(); RhinoCommonClass.Get(_visitingClass).Constructors.Add(new Tuple <ConstructorDeclarationSyntax, DocumentationCommentTriviaSyntax>(node, docComment)); } } base.VisitConstructorDeclaration(node); }
public static void Write() { StringBuilder py = new StringBuilder(); var keys = AllPythonClasses.Keys.ToList(); keys.Sort((a, b) => { var rhcmnA = GetPY(a); int aVal = ClassValue(rhcmnA); var rhcmnB = GetPY(b); int bVal = ClassValue(rhcmnB); if (aVal < bVal) { return(-1); } if (bVal < aVal) { return(1); } return(a.CompareTo(b)); }); var rstDirectory = new System.IO.DirectoryInfo("../"); foreach (var key in keys) { var pyclass = GetPY(key); var rhcommon = RhinoCommonClass.Get(key); RstFile.WriteRst(rstDirectory, rhcommon, pyclass); var doccomment = rhcommon.DocComment; if (string.IsNullOrWhiteSpace(pyclass.BaseClass)) { py.AppendLine($"class {pyclass.ClassName}:"); } else { py.AppendLine($"class {pyclass.ClassName}({pyclass.BaseClass}):"); } if (doccomment == null) { py.AppendLine(T1 + "\"\"\" ... \"\"\""); } else { string comment = DocCommentToPythonDoc(doccomment, 1); py.Append(comment); } foreach (var constructor in pyclass.Constructors) { var c = rhcommon.GetConstructor(constructor); if (c == null) { continue; } var constructorDecl = c.Item1; if (constructorDecl != null) { py.Append(T1 + "def __init__(self"); var paramnames = pyclass.GetParamNames(constructorDecl.ParameterList, true); foreach (var paramname in paramnames) { py.Append(", " + paramname); } py.AppendLine("):"); if (c.Item2 != null) { py.Append(DocCommentToPythonDoc(c.Item2, 2)); } py.AppendLine(T2 + "pass"); } } foreach (var(isStatic, method, args) in pyclass.Methods) { var m = rhcommon.GetMethod(method); if (m == null) { continue; } if (isStatic) { py.AppendLine(T1 + "@staticmethod"); } py.Append(T1 + $"def {method}("); bool addComma = false; if (!isStatic) { py.Append("self"); addComma = true; } var paramnames = pyclass.GetParamNames(m.Item1.ParameterList, true); foreach (var paramname in paramnames) { if (addComma) { py.Append(", "); } addComma = true; py.Append(paramname); } py.AppendLine("):"); if (m.Item2 != null) { py.Append(DocCommentToPythonDoc(m.Item2, 2)); } py.AppendLine(T2 + "pass"); py.AppendLine(); } foreach (var propName in pyclass.Properties) { var p = rhcommon.GetProperty(propName); if (null == p) { continue; } py.AppendLine(T1 + "@property"); py.AppendLine(T1 + $"def {propName}(self):"); if (p.Item2 != null) { py.Append(DocCommentToPythonDoc(p.Item2, 2)); } py.AppendLine(T2 + "return 0"); py.AppendLine(); } py.AppendLine(); } // Create an rst file for each class //foreach (var key in keys) //{ // var pyclass = GetPY(key); // StringBuilder rst = new StringBuilder(); // rst.AppendLine(pyclass.ClassName); // for (int i = 0; i < pyclass.ClassName.Length; i++) // rst.Append("*"); // rst.AppendLine(); // rst.AppendLine(); // rst.AppendLine($".. autoclass:: rhino3dm.{pyclass.ClassName}"); // rst.AppendLine(" :members:"); // rst.AppendLine(" :undoc-members:"); // rst.AppendLine(" :show-inheritance:"); // System.IO.File.WriteAllText($"../{pyclass.ClassName}.rst", rst.ToString()); //} // write the index StringBuilder indexRst = new StringBuilder(); indexRst.Append( @".. rhino3dm documentation master file, created by sphinx-quickstart on Fri Oct 19 16:07:18 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to rhino3dm's documentation! ==================================== .. toctree:: :maxdepth: 2 :caption: Contents: "); List <string> names = new List <string>(); foreach (var key in keys) { var pyclass = GetPY(key); names.Add(pyclass.ClassName); } names.Sort(); foreach (var name in names) { indexRst.AppendLine($" {name}"); } indexRst.Append( @" Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search`"); System.IO.File.WriteAllText("../index.rst", indexRst.ToString()); System.IO.File.WriteAllText("../rhino3dm.py", py.ToString()); }
public static void GenerateTypeStubs(string directory) { if (!System.IO.Directory.Exists(directory)) { System.IO.Directory.CreateDirectory(directory); } StringBuilder py = new StringBuilder(); py.AppendLine("from typing import Tuple, Set, Iterable, List"); var keys = AllPythonClasses.Keys.ToList(); keys.Sort((a, b) => { var rhcmnA = GetPY(a); int aVal = ClassValue(rhcmnA); var rhcmnB = GetPY(b); int bVal = ClassValue(rhcmnB); if (aVal < bVal) { return(-1); } if (bVal < aVal) { return(1); } return(a.CompareTo(b)); }); foreach (var key in keys) { var pyclass = GetPY(key); var rhcommon = RhinoCommonClass.Get(key); py.AppendLine(); py.AppendLine($"class {pyclass.ClassName}:"); foreach (var constructor in pyclass.Constructors) { var c = rhcommon.GetConstructor(constructor); if (c == null) { continue; } var constructorDecl = c.Item1; if (constructorDecl != null) { py.Append(T1 + "def __init__(self"); foreach (var parameter in constructorDecl.ParameterList.Parameters) { py.Append($", {ToSafePythonName(parameter.Identifier.ToString())}: {ToPythonType(parameter.Type.ToString())}"); } py.AppendLine("): ..."); } } foreach (var propName in pyclass.Properties) { var p = rhcommon.GetProperty(propName); if (null == p) { continue; } py.AppendLine(T1 + "@property"); py.AppendLine(T1 + $"def {propName}(self) -> {ToPythonType(p.Item1.Type.ToString())}: ..."); } foreach (var(isStatic, method, args) in pyclass.Methods) { var m = rhcommon.GetMethod(method); if (m == null) { continue; } if (isStatic) { py.AppendLine(T1 + "@staticmethod"); } py.Append(T1 + $"def {method}("); bool addComma = false; if (!isStatic) { py.Append("self"); addComma = true; } foreach (var parameter in m.Item1.ParameterList.Parameters) { if (addComma) { py.Append(", "); } addComma = true; py.Append($"{ToSafePythonName(parameter.Identifier.ToString())}: {ToPythonType(parameter.Type.ToString())}"); } py.AppendLine($") -> {ToPythonType(m.Item1.ReturnType.ToString())}: ..."); } } py.AppendLine(); System.IO.File.WriteAllText(System.IO.Path.Combine(directory, "__init__.pyi"), py.ToString()); }
public static void Write(string path) { StringBuilder js = new StringBuilder(); var keys = BindingClass.AllJavascriptClasses.Keys.ToList(); keys.Sort(); foreach (var key in keys) { var jsclass = GetJS(key); var rhcommon = RhinoCommonClass.Get(key); var doccomment = rhcommon.DocComment; js.AppendLine("/**"); if (doccomment == null) { js.AppendLine($" * {jsclass.ClassName}"); } else { string comment = doccomment.ToString(); comment = comment.Replace("///", ""); js.Append(comment); } if (!string.IsNullOrEmpty(jsclass.BaseClass)) { js.AppendLine($" * @extends {jsclass.BaseClass}"); } if (jsclass.Constructors.Count == 0) { js.AppendLine(" * @hideconstructor"); } js.AppendLine(" */"); js.AppendLine($"class {jsclass.ClassName} {{"); foreach (var constructor in jsclass.Constructors) { var c = rhcommon.GetConstructor(constructor); if (c == null) { continue; } ConstructorDeclarationSyntax constructorDecl = c.Item1; doccomment = c.Item2; if (constructorDecl != null) { List <string> paramNames = null; js.AppendLine(" /**"); if (doccomment != null) { string s = DocCommentToJsDoc(doccomment, null, constructorDecl.ParameterList, out paramNames); js.Append(s); } js.AppendLine(" */"); js.Append(" constructor("); if (paramNames != null) { string parameters = ""; foreach (var p in paramNames) { parameters += p + ","; } if (!string.IsNullOrWhiteSpace(parameters)) { parameters = parameters.Substring(0, parameters.Length - 1); js.Append(parameters); } } js.AppendLine("){}"); } } foreach (var(isStatic, method) in jsclass.Methods) { MethodDeclarationSyntax methodDecl = null; doccomment = null; for (int i = 0; i < rhcommon.Methods.Count; i++) { if (method.Equals(rhcommon.Methods[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { methodDecl = rhcommon.Methods[i].Item1; doccomment = rhcommon.Methods[i].Item2; break; } } List <string> paramNames = new List <string>(); if (doccomment == null) { js.AppendLine(" /** ... */"); } else { js.AppendLine(" /**"); string s = DocCommentToJsDoc(doccomment, methodDecl, methodDecl.ParameterList, out paramNames); js.Append(s); js.AppendLine(" */"); } string parameters = ""; foreach (var p in paramNames) { parameters += p + ","; } if (!string.IsNullOrEmpty(parameters)) { parameters = parameters.Substring(0, parameters.Length - 1); } if (isStatic) { js.Append($" static {method}({parameters}) {{"); } else { js.Append($" {method}({parameters}) {{"); } js.AppendLine(" }"); } foreach (var prop in jsclass.Properties) { PropertyDeclarationSyntax propDecl = null; doccomment = null; for (int i = 0; i < rhcommon.Properties.Count; i++) { if (prop.Equals(rhcommon.Properties[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { propDecl = rhcommon.Properties[i].Item1; doccomment = rhcommon.Properties[i].Item2; break; } } js.AppendLine(" /**"); if (doccomment != null) { string comment = DocCommentToJsDoc(doccomment, propDecl); js.Append(comment); } if (propDecl != null) { js.AppendLine($" * @type {{{ToJavascriptType(propDecl.Type.ToString())}}}"); } js.AppendLine(" */"); js.AppendLine($" get {prop}() {{ return null;}}"); } js.AppendLine("}"); } System.IO.File.WriteAllText(path, js.ToString()); }
public static void GenerateTypescriptDefinition(string directory) { if (!System.IO.Directory.Exists(directory)) { System.IO.Directory.CreateDirectory(directory); } var js = new StringBuilder(); js.AppendLine("declare module 'rhino3dm' {"); var keys = BindingClass.AllJavascriptEnums.Keys.ToList(); keys.Sort(); foreach (var key in keys) { js.AppendLine(); JavascriptEnum jsenum = BindingClass.AllJavascriptEnums[key]; js.AppendLine($"\tenum {jsenum.Name} {{"); for (int i = 0; i < jsenum.Elements.Count; i++) { if (i < (jsenum.Elements.Count - 1)) { js.AppendLine($"\t\t{jsenum.Elements[i]},"); } else { js.AppendLine($"\t\t{jsenum.Elements[i]}"); } } js.AppendLine("\t}"); } keys = BindingClass.AllJavascriptClasses.Keys.ToList(); keys.Sort(); foreach (var key in keys) { js.AppendLine(); var jsclass = GetJS(key); var rhcommon = RhinoCommonClass.Get(key); js.Append($"\tclass {jsclass.ClassName}"); if (!string.IsNullOrWhiteSpace(jsclass.BaseClass)) { js.Append($" extends {jsclass.BaseClass}"); } js.AppendLine(" {"); foreach (var prop in jsclass.Properties) { PropertyDeclarationSyntax propDecl = null; DocumentationCommentTriviaSyntax doccomment = null; for (int i = 0; i < rhcommon.Properties.Count; i++) { if (prop.Equals(rhcommon.Properties[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { propDecl = rhcommon.Properties[i].Item1; doccomment = rhcommon.Properties[i].Item2; break; } } js.AppendLine("\t\t/**"); if (doccomment != null) { string[] comments = DocCommentToTypeScript(doccomment, propDecl); foreach (var comment in comments) { if (!string.IsNullOrWhiteSpace(comment)) { js.AppendLine($"\t\t * {comment}"); } } } string proptype = "any"; if (propDecl != null) { proptype = ToTypeScriptType(propDecl.Type.ToString()); } js.AppendLine("\t\t */"); js.AppendLine($"\t\t{prop}: {proptype};"); } foreach (var(isStatic, method, args) in jsclass.Methods) { MethodDeclarationSyntax methodDecl = null; DocumentationCommentTriviaSyntax doccomment = null; for (int i = 0; i < rhcommon.Methods.Count; i++) { if (method.Equals(rhcommon.Methods[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { methodDecl = rhcommon.Methods[i].Item1; doccomment = rhcommon.Methods[i].Item2; break; } } List <string> paramNames = new List <string>(); List <string> paramTypes = new List <string>(); if (doccomment == null) { js.AppendLine("\t\t/** ... */"); } else { js.AppendLine("\t\t/**"); string s = DocCommentToTypeScript(doccomment, methodDecl, methodDecl.ParameterList, out paramNames, out paramTypes); string[] lines = s.Split(new char[] { '\n' }); for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); if (string.IsNullOrWhiteSpace(line)) { continue; } if (line.StartsWith("*")) { line = " " + line; } js.AppendLine($"\t\t{line}"); } js.AppendLine("\t\t */"); } string parameters = ""; for (int i = 0; i < paramNames.Count; i++) { parameters += $"{paramNames[i]}:{paramTypes[i]},"; } if (!string.IsNullOrEmpty(parameters)) { parameters = parameters.Substring(0, parameters.Length - 1); } string returnType = "void"; if (methodDecl != null) { returnType = ToTypeScriptType(methodDecl.ReturnType.ToString()); } if (isStatic) { js.AppendLine($"\t\tstatic {method}({parameters}): {returnType};"); } else { js.AppendLine($"\t\t{method}({parameters}): {returnType};"); } } js.AppendLine("\t}"); } js.AppendLine("}"); string path = System.IO.Path.Combine(directory, "rhino3dm.d.ts"); System.IO.File.WriteAllText(path, js.ToString()); }
/// <summary> /// Create API documentation file(s). Currently javascript help is created /// by first creating a fake javascript file that mocks rhino3dm wasm and /// then runing jsdoc on this file. /// TODO: My plan is to switch this over to the RST+sphinx technique that /// I would like to use for all languages /// </summary> /// <param name="directory">Where to write the API help</param> public static void GenerateApiHelp(string directory) { if (!System.IO.Directory.Exists(directory)) { System.IO.Directory.CreateDirectory(directory); } StringBuilder js = new StringBuilder(); var keys = BindingClass.AllJavascriptClasses.Keys.ToList(); keys.Sort(); foreach (var key in keys) { var jsclass = GetJS(key); var rhcommon = RhinoCommonClass.Get(key); var doccomment = rhcommon.DocComment; js.AppendLine("/**"); if (doccomment == null) { js.AppendLine($" * {jsclass.ClassName}"); } else { string comment = doccomment.ToString(); comment = comment.Replace("///", ""); js.Append(comment); } if (!string.IsNullOrEmpty(jsclass.BaseClass)) { js.AppendLine($" * @extends {jsclass.BaseClass}"); } if (jsclass.Constructors.Count == 0) { js.AppendLine(" * @hideconstructor"); } js.AppendLine(" */"); js.AppendLine($"class {jsclass.ClassName} {{"); foreach (var constructor in jsclass.Constructors) { var c = rhcommon.GetConstructor(constructor); if (c == null) { continue; } ConstructorDeclarationSyntax constructorDecl = c.Item1; doccomment = c.Item2; if (constructorDecl != null) { List <string> paramNames = null; js.AppendLine(" /**"); if (doccomment != null) { string s = DocCommentToJsDoc(doccomment, null, constructorDecl.ParameterList, out paramNames); js.Append(s); } js.AppendLine(" */"); js.Append(" constructor("); if (paramNames != null) { string parameters = ""; foreach (var p in paramNames) { parameters += p + ","; } if (!string.IsNullOrWhiteSpace(parameters)) { parameters = parameters.Substring(0, parameters.Length - 1); js.Append(parameters); } } js.AppendLine("){}"); // jsdoc doesn't allow multiple constructors. Skip constructor // overloads for now break; } } foreach (var jsMethod in jsclass.Methods) { bool isStatic = jsMethod.IsStatic; string method = jsMethod.Name; string[] args = jsMethod.ArgList; MethodDeclarationSyntax methodDecl = null; doccomment = null; for (int i = 0; i < rhcommon.Methods.Count; i++) { if (method.Equals(rhcommon.Methods[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { methodDecl = rhcommon.Methods[i].Item1; doccomment = rhcommon.Methods[i].Item2; // only break if the parameter count is a match, otherwise keep searching // and hope for a best match if (rhcommon.Methods[i].Item1.ParameterList.Parameters.Count == args.Length) { break; } } } List <string> paramNames = new List <string>(); if (doccomment == null) { js.AppendLine(" /** ... */"); } else { js.AppendLine(" /**"); string s = DocCommentToJsDoc(doccomment, methodDecl, methodDecl.ParameterList, out paramNames); js.Append(s); js.AppendLine(" */"); } string parameters = ""; foreach (var p in paramNames) { parameters += p + ","; } if (!string.IsNullOrEmpty(parameters)) { parameters = parameters.Substring(0, parameters.Length - 1); } if (isStatic) { js.Append($" static {method}({parameters}) {{"); } else { js.Append($" {method}({parameters}) {{"); } js.AppendLine(" }"); } foreach (var prop in jsclass.Properties) { PropertyDeclarationSyntax propDecl = null; doccomment = null; for (int i = 0; i < rhcommon.Properties.Count; i++) { if (prop.Equals(rhcommon.Properties[i].Item1.Identifier.ToString(), StringComparison.InvariantCultureIgnoreCase)) { propDecl = rhcommon.Properties[i].Item1; doccomment = rhcommon.Properties[i].Item2; break; } } js.AppendLine(" /**"); if (doccomment != null) { string comment = DocCommentToJsDoc(doccomment, propDecl); js.Append(comment); } if (propDecl != null) { js.AppendLine($" * @type {{{ToJavascriptType(propDecl.Type.ToString())}}}"); } js.AppendLine(" */"); js.AppendLine($" get {prop}() {{ return null;}}"); } js.AppendLine("}"); } string path = System.IO.Path.Combine(directory, "rh3dm_temp.js"); System.IO.File.WriteAllText(path, js.ToString()); }
public static void Write() { StringBuilder py = new StringBuilder(); var keys = AllPythonClasses.Keys.ToList(); keys.Sort(); keys.Sort((a, b) => { var rhcmnA = GetPY(a); int aVal = ClassValue(rhcmnA); var rhcmnB = GetPY(b); int bVal = ClassValue(rhcmnB); if (aVal < bVal) { return(-1); } if (bVal < aVal) { return(1); } return(a.CompareTo(b)); }); foreach (var key in keys) { var pyclass = GetPY(key); var rhcommon = RhinoCommonClass.Get(key); var doccomment = rhcommon.DocComment; if (string.IsNullOrWhiteSpace(pyclass.BaseClass)) { py.AppendLine($"class {pyclass.ClassName}:"); } else { py.AppendLine($"class {pyclass.ClassName}({pyclass.BaseClass}):"); } if (doccomment == null) { py.AppendLine(T1 + "\"\"\" ... \"\"\""); } else { string comment = DocCommentToPythonDoc(doccomment, 1); py.Append(comment); } foreach (var constructor in pyclass.Constructors) { var c = rhcommon.GetConstructor(constructor); if (c == null) { continue; } var constructorDecl = c.Item1; if (constructorDecl != null) { py.Append(T1 + "def __init__(self"); var paramnames = pyclass.GetParamNames(constructorDecl.ParameterList, true); foreach (var paramname in paramnames) { py.Append(", " + paramname); } py.AppendLine("):"); if (c.Item2 != null) { py.Append(DocCommentToPythonDoc(c.Item2, 2)); } py.AppendLine(T2 + "pass"); } } foreach (var(isStatic, method) in pyclass.Methods) { var m = rhcommon.GetMethod(method); if (m == null) { continue; } if (isStatic) { py.AppendLine(T1 + "@staticmethod"); } py.Append(T1 + $"def {method}("); bool addComma = false; if (!isStatic) { py.Append("self"); addComma = true; } var paramnames = pyclass.GetParamNames(m.Item1.ParameterList, true); foreach (var paramname in paramnames) { if (addComma) { py.Append(", "); } addComma = true; py.Append(paramname); } py.AppendLine("):"); if (m.Item2 != null) { py.Append(DocCommentToPythonDoc(m.Item2, 2)); } py.AppendLine(T2 + "pass"); py.AppendLine(); } foreach (var propName in pyclass.Properties) { var p = rhcommon.GetProperty(propName); if (null == p) { continue; } py.AppendLine(T1 + "@property"); py.AppendLine(T1 + $"def {propName}(self):"); if (p.Item2 != null) { py.Append(DocCommentToPythonDoc(p.Item2, 2)); } py.AppendLine(T2 + "return 0"); py.AppendLine(); } py.AppendLine(); } // Create an rst file for each class foreach (var key in keys) { var pyclass = GetPY(key); StringBuilder rst = new StringBuilder(); rst.AppendLine(pyclass.ClassName); for (int i = 0; i < pyclass.ClassName.Length; i++) { rst.Append("*"); } rst.AppendLine(); rst.AppendLine(); rst.AppendLine($".. autoclass:: rhino3dm.{pyclass.ClassName}"); rst.AppendLine(" :members:"); rst.AppendLine(" :undoc-members:"); rst.AppendLine(" :show-inheritance:"); System.IO.File.WriteAllText($"../{pyclass.ClassName}.rst", rst.ToString()); } System.IO.File.WriteAllText("../rhino3dm.py", py.ToString()); }