Skip to content

Commit 3de5406

Browse files
committed
fix(SCNvimDocEntry): JSON generation bug fixes
* the inheritance array in `toJSON` could be malformed if the class inheritance hierarchy is incomplete. For example the Object class has subclasses but no superclass, in that case the `superclasses` property would incorrectly represent `subclasses`. * The method didn't handle the implKlass case where the value would be a string, so we switch on the value type. * add `lastItem` argument to method `prJSONString` to get valid json * add `depth` argument to methods `prJSONString` `prJSONList` to get better formatting. * fix last item conditions for "methods" and "oldhelp" parsing. patch(SCNvimDoc): retab * there was a mix of tabs and spaces, only tabs now
1 parent ec347b2 commit 3de5406

1 file changed

Lines changed: 136 additions & 114 deletions

File tree

scide_scnvim/Classes/SCNvimDoc/SCNvimDoc.sc

Lines changed: 136 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
SCNvimDoc : SCDoc {
22
*exportDocMapJson {|path|
3-
var f, numItems;
4-
f = File.open(path,"w");
5-
numItems = this.documents.size - 1;
6-
f << "{\n";
7-
this.documents.do {|doc, i|
8-
doc.toJSON(f, i >= numItems);
9-
};
10-
f << "}\n";
11-
f.close;
12-
}
3+
var f, numItems;
4+
f = File.open(path,"w");
5+
numItems = this.documents.size - 1;
6+
f << "{\n";
7+
this.documents.do {|doc, i|
8+
doc.toJSON(f, i >= numItems);
9+
};
10+
f << "}\n";
11+
f.close;
12+
}
1313

1414
*parseFileMetaData {|dir,path|
1515
var fullPath = dir +/+ path;
@@ -28,7 +28,7 @@ SCNvimDoc : SCDoc {
2828
^entry;
2929
}
3030

31-
*indexAllDocuments { |clearCache=false|
31+
*indexAllDocuments { |clearCache=false|
3232
var now = Main.elapsedTime;
3333
var key, doc;
3434
var nonHelpFiles;
@@ -115,94 +115,93 @@ SCNvimDoc : SCDoc {
115115
};
116116

117117
if(str.last == $_) { str = str.drop(-1) };
118-
^str;
118+
^str;
119119
}
120120

121-
*prepareHelpForURL {|url|
122-
var path, targetBasePath, pathIsCaseInsensitive;
123-
var subtarget, src, c, cmd, doc, destExist, destMtime;
124-
var verpath = this.helpTargetDir +/+ "version";
125-
path = url.asLocalPath;
126-
127-
// detect old helpfiles and wrap them in OldHelpWrapper
128-
if(url.scheme == "sc") { ^URI(SCNvimDoc.findHelpFile(path)); };
129-
130-
// just pass through remote url's
131-
if(url.scheme != "file") {^url};
132-
133-
targetBasePath = SCDoc.helpTargetDir;
134-
if (thisProcess.platform.name === \windows)
135-
{ targetBasePath = targetBasePath.replace("/","\\") };
136-
pathIsCaseInsensitive = thisProcess.platform.name === \windows;
137-
138-
// detect old helpfiles and wrap them in OldHelpWrapper
139-
if(
140-
/*
141-
// this didn't work for quarks due to difference between registered old help path and the quarks symlink in Extensions.
142-
// we could use File.realpath(path) below but that would double the execution time,
143-
// so let's just assume any local file outside helpTargetDir is an old helpfile.
144-
block{|break|
145-
Help.do {|key, path|
146-
if(url.endsWith(path)) {
147-
break.value(true)
148-
}
149-
}; false
150-
}*/
151-
compare(
152-
path [..(targetBasePath.size-1)],
153-
targetBasePath,
154-
pathIsCaseInsensitive
155-
) != 0
156-
) {
157-
^SCDoc.getOldWrapUrl(url)
158-
};
159-
160-
if(destExist = File.exists(path))
161-
{
162-
destMtime = File.mtime(path);
163-
};
164-
165-
if(path.endsWith(".html.scnvim")) {
166-
subtarget = path.drop(this.helpTargetDir.size+1).drop(-12).replace("\\","/");
167-
doc = this.documents[subtarget];
168-
doc !? {
169-
if(doc.isUndocumentedClass) {
170-
if(doc.mtime == 0) {
171-
this.renderUndocClass(doc);
172-
doc.mtime = 1;
173-
};
174-
^url;
175-
};
176-
if(File.mtime(doc.fullPath)>doc.mtime) { // src changed after indexing
177-
this.postMsg("% changed, re-indexing documents".format(doc.path),2);
178-
this.indexAllDocuments;
179-
^this.prepareHelpForURL(url);
180-
};
181-
if(destExist.not
182-
or: {doc.mtime>destMtime}
183-
or: {doc.additions.detect {|f| File.mtime(f)>destMtime}.notNil}
184-
or: {File.mtime(this.helpTargetDir +/+ "scdoc_version")>destMtime}
185-
or: {doc.klass.notNil and: {File.mtime(doc.klass.filenameSymbol.asString)>destMtime}}
186-
) {
187-
this.parseAndRender(doc);
188-
};
189-
^url;
190-
};
191-
};
192-
193-
if(destExist) {
194-
^url;
195-
};
196-
197-
warn("SCDoc: Broken link:" + url.asString);
198-
^nil;
199-
}
121+
*prepareHelpForURL {|url|
122+
var path, targetBasePath, pathIsCaseInsensitive;
123+
var subtarget, src, c, cmd, doc, destExist, destMtime;
124+
var verpath = this.helpTargetDir +/+ "version";
125+
path = url.asLocalPath;
126+
127+
// detect old helpfiles and wrap them in OldHelpWrapper
128+
if(url.scheme == "sc") { ^URI(SCNvimDoc.findHelpFile(path)); };
129+
130+
// just pass through remote url's
131+
if(url.scheme != "file") {^url};
132+
133+
targetBasePath = SCDoc.helpTargetDir;
134+
if (thisProcess.platform.name === \windows)
135+
{ targetBasePath = targetBasePath.replace("/","\\") };
136+
pathIsCaseInsensitive = thisProcess.platform.name === \windows;
137+
138+
// detect old helpfiles and wrap them in OldHelpWrapper
139+
if(
140+
/*
141+
// this didn't work for quarks due to difference between registered old help path and the quarks symlink in Extensions.
142+
// we could use File.realpath(path) below but that would double the execution time,
143+
// so let's just assume any local file outside helpTargetDir is an old helpfile.
144+
block{|break|
145+
Help.do {|key, path|
146+
if(url.endsWith(path)) {
147+
break.value(true)
148+
}
149+
}; false
150+
}*/
151+
compare(
152+
path [..(targetBasePath.size-1)],
153+
targetBasePath,
154+
pathIsCaseInsensitive
155+
) != 0
156+
) {
157+
^SCDoc.getOldWrapUrl(url)
158+
};
159+
160+
if(destExist = File.exists(path))
161+
{
162+
destMtime = File.mtime(path);
163+
};
164+
165+
if(path.endsWith(".html.scnvim")) {
166+
subtarget = path.drop(this.helpTargetDir.size+1).drop(-12).replace("\\","/");
167+
doc = this.documents[subtarget];
168+
doc !? {
169+
if(doc.isUndocumentedClass) {
170+
if(doc.mtime == 0) {
171+
this.renderUndocClass(doc);
172+
doc.mtime = 1;
173+
};
174+
^url;
175+
};
176+
if(File.mtime(doc.fullPath)>doc.mtime) { // src changed after indexing
177+
this.postMsg("% changed, re-indexing documents".format(doc.path),2);
178+
this.indexAllDocuments;
179+
^this.prepareHelpForURL(url);
180+
};
181+
if(destExist.not
182+
or: {doc.mtime>destMtime}
183+
or: {doc.additions.detect {|f| File.mtime(f)>destMtime}.notNil}
184+
or: {File.mtime(this.helpTargetDir +/+ "scdoc_version")>destMtime}
185+
or: {doc.klass.notNil and: {File.mtime(doc.klass.filenameSymbol.asString)>destMtime}}
186+
) {
187+
this.parseAndRender(doc);
188+
};
189+
^url;
190+
};
191+
};
192+
193+
if(destExist) {
194+
^url;
195+
};
200196

197+
warn("SCDoc: Broken link:" + url.asString);
198+
^nil;
199+
}
201200
}
202201

203202
SCNvimDocEntry : SCDocEntry {
204203
destPath {
205-
^SCDoc.helpTargetDir +/+ path ++ ".html.scnvim";
204+
^SCDoc.helpTargetDir +/+ path ++ ".html.scnvim";
206205
}
207206

208207
makeMethodList {
@@ -226,61 +225,84 @@ SCNvimDocEntry : SCDocEntry {
226225
}
227226

228227
// overriden to output valid json
229-
prJSONString {|stream, key, x|
228+
prJSONString {|depth=0, stream, key, x, lastItem|
229+
var delimiter = if (lastItem.notNil and: { lastItem }, "", ",");
230+
var indent = "";
230231
if (x.isNil) { x = "" };
231232
x = x.escapeChar(92.asAscii); // backslash
232233
x = x.escapeChar(34.asAscii); // double quote
233-
stream << "\"" << key << "\": \"" << x << "\",\n";
234+
235+
if (depth > 0) {
236+
depth.do {
237+
indent = indent ++ "\t";
238+
}
239+
};
240+
241+
stream << indent << "\"" << key << "\": \"" << x << "\"%\n".format(delimiter);
234242
}
235243

236244
// overriden to output valid json
237-
prJSONList {|stream, key, v, lastItem|
238-
var delimiter = if(lastItem.notNil and:{lastItem}, "", ",");
245+
prJSONList {|depth=0, stream, key, v, lastItem|
246+
var delimiter = if (lastItem.notNil and: { lastItem }, "", ",");
247+
var indent = "";
239248
if (v.isNil) { v = "" };
240-
stream << "\"" << key << "\": [ " << v.collect{|x|"\""++x.escapeChar(34.asAscii)++"\""}.join(",") << " ]%\n".format(delimiter);
249+
250+
if (depth > 0) {
251+
depth.do {
252+
indent = indent ++ "\t";
253+
}
254+
};
255+
256+
stream << indent << "\"" << key << "\": [" << v.collect{ |x| "\"" ++ x.escapeChar(34.asAscii) ++ "\"" }.join(", ") << "]%\n".format(delimiter);
241257
}
242258

243259
toJSON {|stream, lastItem|
244-
var delimiter = if(lastItem.notNil and:{lastItem}, "", ",");
245-
var inheritance = [];
246-
var numItems;
260+
var delimiter = if (lastItem.notNil and: { lastItem }, "", ",");
261+
var inheritance = Array.fill(3, nil);
247262
var keys;
263+
var lastKey = 0;
248264

249265
stream << "\"" << path.escapeChar(34.asAscii) << "\": {\n";
250266

251-
this.prJSONString(stream, "title", title);
252-
this.prJSONString(stream, "path", path);
253-
this.prJSONString(stream, "summary", summary);
254-
this.prJSONString(stream, "installed", if(isExtension,"extension","standard")); //FIXME: also 'missing'.. better to have separate extension and missing booleans..
255-
this.prJSONString(stream, "categories", if(categories.notNil) {categories.join(", ")} {""}); // FIXME: export list instead
256-
this.prJSONList(stream, "keywords", keywords);
257-
this.prJSONList(stream, "related", related);
267+
this.prJSONString(1, stream, "title", title);
268+
this.prJSONString(1, stream, "path", path);
269+
this.prJSONString(1, stream, "summary", summary);
270+
this.prJSONString(1, stream, "installed", if(isExtension,"extension","standard")); //FIXME: also 'missing'.. better to have separate extension and missing booleans..
271+
this.prJSONString(1, stream, "categories", if(categories.notNil) {categories.join(", ")} {""}); // FIXME: export list instead
258272

259-
this.prJSONList(stream, "methods", this.makeMethodList, klass.isNil);
273+
this.prJSONList(1, stream, "keywords", keywords);
274+
this.prJSONList(1, stream, "related", related);
275+
this.prJSONList(1, stream, "methods", this.makeMethodList, klass.isNil and: {oldHelp.isNil});
260276

261277
if (oldHelp.notNil) {
262-
this.prJSONString(stream, "oldhelp", oldHelp);
278+
this.prJSONString(1, stream, "oldhelp", oldHelp, klass.isNil);
263279
};
264280

265281
if (klass.notNil) {
266282
keys = #[ "superclasses", "subclasses", "implementor" ];
267283
klass.superclasses !? {
268-
inheritance = inheritance.add(klass.superclasses.collect {|c|
284+
inheritance.put(0, klass.superclasses.collect {|c|
269285
c.name.asString
270286
});
271287
};
272288
klass.subclasses !? {
273-
inheritance = inheritance.add(klass.subclasses.collect {|c|
289+
inheritance.put(1, klass.subclasses.collect {|c|
274290
c.name.asString
275291
});
292+
lastKey = 1;
276293
};
277294
implKlass !? {
278-
inheritance = inheritance.add(implKlass.name.asString);
295+
inheritance.put(2, implKlass.name.asString);
296+
lastKey = 2;
279297
};
280298

281-
numItems = inheritance.size - 1;
282299
inheritance.do {|item, i|
283-
this.prJSONList(stream, keys[i], item, i >= numItems);
300+
if (item.notNil && item.isKindOf(String)) {
301+
this.prJSONString(1, stream, keys[i], item, i == lastKey);
302+
};
303+
if (item.notNil && item.isKindOf(Array)) {
304+
this.prJSONList(1, stream, keys[i], item, i == lastKey);
305+
};
284306
};
285307
};
286308

0 commit comments

Comments
 (0)