X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=documentor%2Fsrc%2FDocumentor.ec;h=7dfc77e367c0be86ad8b08a76354a1800c0be4b4;hb=12cb9288a539df89d4b4e7bdb21cd78da2cd10e3;hp=21959e3c866a86a77310c4d3485753a4ab8dd3e3;hpb=331c2ad06c24a2a037e9495122ea5a2410c83ece;p=sdk
diff --git a/documentor/src/Documentor.ec b/documentor/src/Documentor.ec
index 21959e3..7dfc77e 100644
--- a/documentor/src/Documentor.ec
+++ b/documentor/src/Documentor.ec
@@ -1,9 +1,18 @@
import "ecere"
+#if !defined(EAR_TO_ECON_ECDOC)
import "ec"
import "HTMLView"
import "IDESettings"
import "SettingsDialog"
+IDESettings ideSettings;
+
+IDESettingsContainer settingsContainer
+{
+ dataOwner = &ideSettings;
+ dataClass = class(IDESettings);
+};
+
static Context globalContext { };
static OldList defines { };
static OldList imports { };
@@ -45,15 +54,6 @@ static const char * iconNames[CodeObjectType] =
"<:ecere>constructs/propertyPrivate.png"
};
-IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
-
-IDESettingsContainer settingsContainer
-{
- driver = "JSON";
- data = settings;
- dataOwner = &settings;
-};
-
void GetTemplateString(Class c, char * templateString)
{
Module m = c.module.application;
@@ -77,9 +77,11 @@ void GetTemplateString(Class c, char * templateString)
Class pc;
char * d = templateString + strlen(templateString);
curName[len] = 0;
+ TrimLSpaces(curName, curName);
+ TrimRSpaces(curName, curName);
pc = eSystem_FindClass(m, curName);
if(pc)
- sprintf(d, "%s", pc, pc.name);
+ sprintf(d, "%s%s", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
else
strcat(d, curName);
}
@@ -100,7 +102,7 @@ void GetTemplateString(Class c, char * templateString)
strcat(templateString, curName);
len = 0;
}
- else if(ch != ' ')
+ else
curName[len++] = ch;
}
}
@@ -407,14 +409,16 @@ void DocPrintType(Type type, char * string, bool printName, bool fullName)
_PrintType(type, string, printName, true, fullName);
}
+Map modulesAdded { };
void AddComponents(Module module, bool isDll)
{
DataRow row = null;
SubModule m;
- if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
+ if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
{
row = mainForm.browser.AddRow();
+ modulesAdded["ecereCOM"] = true;
row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
row.tag = (int64)null;
AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
@@ -427,9 +431,10 @@ void AddComponents(Module module, bool isDll)
}
// PUT MODULE DESCRIPTION HERE
- if(module.name && strcmp(module.name, "ecereCOM"))
+ if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
{
row = mainForm.browser.AddRow();
+ modulesAdded[module.name] = true;
row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
row.tag = (int64)module;
AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
@@ -469,6 +474,7 @@ public:
enum DocumentationType
{
+ unset,
nameSpaceDoc,
classDoc,
functionDoc,
@@ -477,6 +483,7 @@ enum DocumentationType
enum DocumentationItem
{
+ unset,
description,
usage,
remarks,
@@ -493,14 +500,60 @@ enum DocumentationItem
static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
{
+ char hex[20];
+ fileName[0] = 0;
+ sprintf(hex, "%p", module);
+ strcat(fileName, hex);
+ strcat(fileName, "/");
+ sprintf(hex, "%p", object);
+ strcat(fileName, hex);
+ strcat(fileName, "/");
+ sprintf(hex, "%p", data);
+ strcat(fileName, hex);
+ strcat(fileName, "/");
+ if(type == nameSpaceDoc)
+ strcat(fileName, "namespace");
+ else if(type == functionDoc)
+ strcat(fileName, "function");
+ else if(type == classDoc)
+ strcat(fileName, "class");
+ else if(type == methodDoc)
+ strcat(fileName, "method");
+ strcat(fileName, "/");
+ if(item == description)
+ strcat(fileName, "description");
+ else if(item == usage)
+ strcat(fileName, "usage");
+ else if(item == remarks)
+ strcat(fileName, "remarks");
+ else if(item == example)
+ strcat(fileName, "example");
+ else if(item == seeAlso)
+ strcat(fileName, "seeAlso");
+ else if(item == enumerationValue)
+ strcat(fileName, "enumerationValue");
+ else if(item == definition)
+ strcat(fileName, "definition");
+ else if(item == conversion)
+ strcat(fileName, "conversion");
+ else if(item == memberDescription)
+ strcat(fileName, "memberDescription");
+ else if(item == propertyDescription)
+ strcat(fileName, "propertyDescription");
+ else if(item == parameter)
+ strcat(fileName, "parameter");
+ else if(item == returnValue)
+ strcat(fileName, "returnValue");
+}
+
+static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
+{
+ char docPath[MAX_LOCATION];
NameSpace * nameSpace, * ns;
Class cl = null;
Method method = null;
GlobalFunction function = null;
char nsName[1024], temp[1024];
- char docFile[1024];
-
-
switch(type)
{
case nameSpaceDoc: nameSpace = object; break;
@@ -510,125 +563,221 @@ static void FigureFileName(char * fileName, Module module, DocumentationType typ
}
nsName[0] = 0;
+ temp[0] = 0;
ns = nameSpace;
while(ns && ns->name)
{
- strcpy(temp, "namespaces/");
- strcat(temp, ns->name);
+ strcpy(temp, ns->name);
strcat(temp, "/");
strcat(temp, nsName);
strcpy(nsName, temp);
ns = ns->parent;
}
- sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
- if(strchr(docFile, DIR_SEP))
- {
- GetLastDirectory(docFile, temp);
- strcpy(docFile, temp);
- }
-
- sprintf(fileName, "<%s/%s>", settings.docDir, docFile); // Note that in the ecereIDE.ini file, there can be no quotes around the path, and there needs to be the final backslash. Otherwise this does not work.
- strcat(fileName, nsName);
+ docPath[0] = 0;
+ PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
+ //ChangeExtension(docPath, "eCdoc", docPath);
+ PathCatSlash(docPath, nsName);
if(cl)
{
- strcat(fileName, "classes/");
- strcat(fileName, cl.name);
- strcat(fileName, "/");
- }
-
- if(method)
- {
- strcat(fileName, "methods/");
- strcat(fileName, method.name);
- strcat(fileName, "/");
- }
- else if(function)
- {
- const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
- if(name) name += 2; else name = function.name;
- strcat(fileName, "functions/");
- strcat(fileName, name);
- strcat(fileName, "/");
- }
-
- switch(item)
- {
- case description: strcat(fileName, "description"); break;
- case usage: strcat(fileName, "usage"); break;
- case remarks: strcat(fileName, "remarks"); break;
- case example: strcat(fileName, "example"); break;
- case seeAlso: strcat(fileName, "seeAlso"); break;
- case returnValue: strcat(fileName, "returnValue"); break;
- case enumerationValue:
- strcat(fileName, "enumeration values/");
- strcat(fileName, ((NamedLink)data).name);
- break;
- case definition:
- strcat(fileName, "definitions/");
- strcat(fileName, ((Definition)data).name);
- break;
- case conversion:
- {
- const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
- if(name) name += 2; else name = ((Property)data).name;
- strcat(fileName, "conversions/");
- strcat(fileName, name);
- break;
- }
- case memberDescription:
- strcat(fileName, "data members/");
- strcat(fileName, ((DataMember)data).name);
- break;
- case propertyDescription:
- strcat(fileName, "properties/");
- strcat(fileName, ((Property)data).name);
- break;
- case parameter:
- {
- int count;
- char name[1024];
- Type prev;
- strcat(fileName, "parameters/");
- for(prev = data, count = 0; prev; prev = prev.prev, count++);
- sprintf(name, "%s.%d", ((Type)data).name, count);
- strcat(fileName, name);
- break;
- }
+ char * name = getDocFileNameFromTypeName(cl.name);
+ PathCatSlash(docPath, name);
+ delete name;
}
+ else
+ PathCatSlash(docPath, "_global-defs");
+ ChangeExtension(docPath, "econ", docPath);
+
+ path[0] = 0;
+ strcpy(path, ideSettings.docDir);
+ PathCatSlash(path, docPath);
}
static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
{
- char fileName[MAX_LOCATION];
String contents = null;
- File file;
+ NamespaceDoc nsDoc = null;
+ ClassDoc clDoc = null;
+ FunctionDoc fnDoc = null;
+ MethodDoc mdDoc = null;
+ String s = null;
+ char filePath[MAX_LOCATION];
+ Method method = null;
+ GlobalFunction function = null;
+
+ ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
- FigureFileName(fileName, module, type, object, item, data);
- file = FileOpen(fileName, read);
- if(file)
+ switch(type)
{
- uint len;
- if((len = file.GetSize()))
+ case functionDoc: function = object; break;
+ case methodDoc: method = object; break;
+ }
+
+ if(doc)
+ {
+ if(eClass_IsDerived(doc._class, class(ClassDoc)))
{
- contents = new char[len+1];
- file.Read(contents, 1, len);
- contents[len] = '\0';
+ clDoc = (ClassDoc)doc;
+ }
+ else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
+ {
+ nsDoc = (NamespaceDoc)doc;
}
- delete file;
}
- if(contents)
+
+ if(clDoc || nsDoc)
{
- int c;
- for(c = 0; contents[c]; c++)
- if(!isspace(contents[c])) break;
- if(!contents[c])
- delete contents;
+ ItemDoc itDoc = null;
+ if(type == functionDoc)
+ {
+ MapIterator it { map = nsDoc.functions };
+ const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
+ if(name) name += 2; else name = function.name;
+ if(it.Index(name, false))
+ fnDoc = it.data;
+ }
+ else if(type == methodDoc)
+ {
+ MapIterator it { map = clDoc.methods };
+ if(it.Index(method.name, false))
+ mdDoc = it.data;
+ }
+
+ switch(item)
+ {
+ case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
+ case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
+ case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
+ case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
+ case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
+ case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
+ case enumerationValue:
+ if(clDoc && clDoc.values)
+ {
+ itDoc = clDoc.values[((NamedLink)data).name];
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ case definition:
+ if(nsDoc && nsDoc.defines)
+ {
+ itDoc = nsDoc.defines[((Definition)data).name];
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ case conversion:
+ if(clDoc && clDoc.conversions)
+ {
+ const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
+ if(name) name += 2; else name = ((Property)data).name;
+ itDoc = clDoc.conversions[name];
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ case memberDescription:
+ if(clDoc && clDoc.fields)
+ {
+ itDoc = clDoc.fields[((DataMember)data).name];
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ case propertyDescription:
+ if(clDoc && clDoc.properties)
+ {
+ itDoc = clDoc.properties[((Property)data).name];
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ case parameter:
+ if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
+ {
+ char * name = ((Type)data).name;
+ itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
+ if(itDoc) s = itDoc.description;
+ }
+ break;
+ }
+ if(s)
+ contents = CopyString(s);
}
if(editing && !contents && !readOnly)
contents = CopyString($"[Add Text]");
+ delete doc;
return contents;
}
+ // The filePath is returned!
+ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
+{
+ ItemDoc doc = null;
+ Class cl = null;
+ Method method = null;
+ DocCacheEntry entry;
+ Time now;
+
+ switch(type)
+ {
+ case classDoc: cl = (Class)object; break;
+ case methodDoc: method = object; cl = method._class; break;
+ }
+
+ FigureFilePath(filePath, module, type, object, item, data);
+
+ entry = docCache[filePath];
+ if(entry)
+ doc = entry.doc;
+
+ if(!doc)
+ {
+ File f = FileOpen(filePath, read);
+ if(f)
+ {
+ ECONParser parser { f = f };
+ JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
+ delete parser;
+ delete f;
+
+ if(jsonResult != success)
+ {
+ PrintLn("error: problem parsing file: ", filePath);
+ delete doc;
+ }
+ }
+ if(!doc)
+ doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
+ }
+
+ incref doc; // Reference to return
+
+ now = GetTime();
+ // Add to the cache
+ if(entry)
+ entry.timeStamp = now;
+ else
+ {
+ docCache[filePath] = { now, doc };
+ incref doc; // Reference for the cache
+ }
+
+ //void pruneDocCache()
+ // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
+ {
+ MapIterator it { map = docCache };
+ Array toRemove { };
+ for(entry : docCache; now - entry.timeStamp > 30)
+ toRemove.Add(&entry);
+ while(toRemove.count)
+ {
+ if(it.Index(toRemove.lastIterator.data, false))
+ {
+ delete it.data;
+ it.Remove();
+ }
+ toRemove.Remove(toRemove.lastIterator.pointer);
+ }
+ delete toRemove;
+ }
+ return doc;
+}
class APIPageNameSpace : APIPage
{
@@ -689,17 +838,18 @@ class APIPageNameSpace : APIPage
char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
if(desc)
{
- f.Printf($"Description
\n");
+ f.Printf($"Description
\n");
if(editing)
{
char fileName[MAX_LOCATION];
FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
f.Printf("", fileName);
f.Puts(desc);
- f.Printf("
");
+ f.Printf("");
}
else
- f.Printf("%s
", desc);
+ f.Printf("%s", desc);
+ f.Printf("
");
delete desc;
}
}
@@ -712,7 +862,7 @@ class APIPageNameSpace : APIPage
char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
if(first)
{
- f.Printf($"Sub Namespaces
\n");
+ f.Printf($"Sub Namespaces
\n");
f.Printf("\n");
first = false;
}
@@ -735,7 +885,7 @@ class APIPageNameSpace : APIPage
f.Printf("
\n");
}
if(!first)
- f.Printf("
\n");
+ f.Printf("
\n");
}
if(nameSpace->classes.first)
@@ -744,13 +894,14 @@ class APIPageNameSpace : APIPage
for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
{
Class cl = link.data;
- if(!cl.templateClass)
+ Module module = cl.module ? cl.module : this.module;
+ if(!cl.templateClass) // && !cl.internalDecl)
{
char * desc = ReadDoc(module, classDoc, cl, description, null);
if(first)
{
- f.Printf($"Classes
\n");
+ f.Printf($"Classes
\n");
f.Printf("\n");
first = false;
}
@@ -776,7 +927,7 @@ class APIPageNameSpace : APIPage
}
}
if(!first)
- f.Printf("
\n");
+ f.Printf("
\n");
}
if(nameSpace->functions.first)
@@ -785,12 +936,13 @@ class APIPageNameSpace : APIPage
for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
{
GlobalFunction function = link.data;
+ Module module = function.module ? function.module : this.module;
char * desc = ReadDoc(module, functionDoc, function, description, null);
const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
if(name) name += 2; else name = function.name;
if(first)
{
- f.Printf($"Functions
\n");
+ f.Printf($"Functions
\n");
f.Printf("\n");
first = false;
}
@@ -813,7 +965,7 @@ class APIPageNameSpace : APIPage
f.Printf("
\n");
}
if(!first)
- f.Printf("
\n");
+ f.Printf("
\n");
}
if(nameSpace->defines.first)
@@ -825,7 +977,7 @@ class APIPageNameSpace : APIPage
char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
if(first)
{
- f.Printf($"Definitions
\n");
+ f.Printf($"Definitions
\n");
f.Printf("\n");
first = false;
}
@@ -849,7 +1001,7 @@ class APIPageNameSpace : APIPage
f.Printf("
\n");
}
if(!first)
- f.Printf("
\n");
+ f.Printf("
\n");
}
f.Printf("