private void _eName_TextChanged(object sender, EventArgs e) { string name = _eName.Text; var a = new List <(string name, string code)>(); int nWild = 0; for (int i = 0; i < name.Length; i++) { switch (name[i]) { case '*': case '?': nWild++; break; } } if (name.Length > 0 && (nWild == 0 || name.Length - nWild >= 2)) { string sql; if (name.Contains(' ')) { sql = $"SELECT * FROM api WHERE name in ('{string.Join("', '", name.RegexFindAll(@"\b[A-Za-z_]\w\w+", 0))}')"; } else if (name.FindAny("*?") >= 0) { sql = $"SELECT * FROM api WHERE name GLOB '{name}'"; } else { sql = $"SELECT * FROM api WHERE name = '{name}'"; } try { using var stat = _db.Statement(sql); //APerf.First(); while (stat.Step()) { a.Add((stat.GetText(0), stat.GetText(1))); } //APerf.NW(); //30 ms cold, 10 ms warm. Without index. } catch (SLException ex) { ADebug.Print(ex.Message); } } string code = ""; if (a.Count != 0) { code = a[0].code; if (a.Count > 1) { code = string.Join(code.Starts("internal const") ? "\r\n" : "\r\n\r\n", a.Select(o => o.code)); } code += "\r\n"; } _code.ZSetText(code); }
/// <summary> /// Creates SQLite database containing Windows API declarations. /// </summary> public static void CreateWinapi(string csDir = @"Q:\app\Au\Other\Api", string dataDir = @"Q:\app\Au\Other\Data") { Cursor.Current = Cursors.WaitCursor; string dbFile = dataDir + @"\winapi.db"; AFile.Delete(dbFile); string s = File.ReadAllText(csDir + @"\Api.cs"); using var d = new ASqlite(dbFile); using var trans = d.Transaction(); d.Execute("CREATE TABLE api (name TEXT, def TEXT)"); //note: no PRIMARY KEY. Don't need index. using var statInsert = d.Statement("INSERT INTO api VALUES (?, ?)"); string rxType = @"(?ms)^(?:\[[^\r\n]+\r\n)*internal (?:struct|enum|interface|class) (\w+)[^\r\n\{]+\{(?:\}$|.+?^\})"; string rxFunc = @"(?m)^(?:\[[^\r\n]+\r\n)*internal (?:static extern|delegate) \w+\** (\w+)\(.+;$"; string rxVarConst = @"(?m)^internal (?:const|readonly|static) \w+ (\w+) =.+;$"; foreach (var m in s.RegexFindAll(rxType)) { _Add(m); } foreach (var m in s.RegexFindAll(rxFunc)) { _Add(m); } foreach (var m in s.RegexFindAll(rxVarConst)) { _Add(m); } void _Add(RXMatch m) { statInsert.Bind(1, m[1].Value); statInsert.Bind(2, m.Value); statInsert.Step(); statInsert.Reset(); } trans.Commit(); d.Execute("VACUUM"); Program.Settings.db_copy_winapi = dbFile; AOutput.Write("CreateWinapi done."); Cursor.Current = Cursors.Arrow; }
static void _CreateRef(string dbFile, string dir1, string dir2) { AFile.Delete(dbFile); using var d = new ASqlite(dbFile); using var trans = d.Transaction(); d.Execute("CREATE TABLE ref (name TEXT PRIMARY KEY, data BLOB)"); using var statInsert = d.Statement("INSERT OR REPLACE INTO ref VALUES (?, ?)"); _AddDir(dir1, "WindowsBase", "System.Drawing"); _AddDir(dir2); trans.Commit(); d.Execute("VACUUM"); AOutput.Write("Created " + dbFile); void _AddDir(string dir, params string[] skip) { foreach (var f in AFile.EnumDirectory(dir)) { if (f.IsDirectory) { continue; } if (!f.Name.Ends(".dll", true)) { continue; } var asmName = f.Name.RemoveSuffix(4); if (skip.Contains(asmName)) { continue; } _AddFile(asmName, f.FullPath); //break; } } void _AddFile(string asmName, string asmFile) { //AOutput.Write(asmName); statInsert.Bind(1, asmName); statInsert.Bind(2, File.ReadAllBytes(asmFile)); statInsert.Step(); statInsert.Reset(); } }
protected internal override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default) { if (_db != null) { lock (_db) { //sometimes not in main thread try { _stat ??= _db.Statement("SELECT xml FROM doc WHERE name=?"); if (_stat.Bind(1, documentationMemberID).Step()) { return(_stat.GetText(0)); } //ADebug.Print(documentationMemberID); } catch (SLException ex) { ADebug.Print(ex.Message); } finally { _stat?.Reset(); } } } return(null); }
/// <summary> /// Creates documentation provider for assembly <i>asmPath</i>. /// Returns null if its xml file does not exist. /// Returns _DocumentationProvider if xml file is big and found or successfully created and successfully loaded database for it. /// Else returns XmlDocumentationProvider. /// </summary> public static DocumentationProvider Create(string asmPath) { if (s_d.TryGetValue(asmPath, out var dp)) { return(dp); } var xmlPath = Path.ChangeExtension(asmPath, "xml"); if (!AFile.GetProperties(xmlPath, out var px)) { return(null); } if (px.Size >= 10_000) { var md5 = new Au.Util.AHash.MD5(); md5.Add(xmlPath.Lower()); var dbPath = AFolders.ThisAppTemp + md5.Hash.ToString() + ".db"; try { if (!AFile.GetProperties(dbPath, out var pd) || pd.LastWriteTimeUtc != px.LastWriteTimeUtc) { //ADebug.Print($"creating db: {asmPath} -> {dbPath}"); AFile.Delete(dbPath); using (var d = new ASqlite(dbPath)) { using var trans = d.Transaction(); d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)"); using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)"); var xr = AExtXml.LoadElem(xmlPath); foreach (var e in xr.Descendants("member")) { var name = e.Attr("name"); //remove <remarks> and <example>. foreach (var v in e.Descendants("remarks").ToArray()) { v.Remove(); } foreach (var v in e.Descendants("example").ToArray()) { v.Remove(); } using var reader = e.CreateReader(); reader.MoveToContent(); var xml = reader.ReadInnerXml(); //AOutput.Write(name, xml); statInsert.BindAll(name, xml).Step(); statInsert.Reset(); } trans.Commit(); d.Execute("VACUUM"); } File.SetLastWriteTimeUtc(dbPath, px.LastWriteTimeUtc); } var db = new ASqlite(dbPath, SLFlags.SQLITE_OPEN_READONLY); //never mind: we don't dispose it on process exit s_d[asmPath] = dp = new _DocumentationProvider { _db = db }; return(dp); } catch (Exception ex) { ADebug.Print(ex.ToStringWithoutStack()); } } return(XmlDocumentationProvider.CreateFromFile(xmlPath)); }
static void _CreateDoc(string dbFile, string dir1, string dir2) { AFile.Delete(dbFile); using var d = new ASqlite(dbFile, sql: "PRAGMA page_size = 8192;"); //8192 makes file smaller by 2-3 MB. using var trans = d.Transaction(); d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)"); using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)"); using var statDupl = d.Statement("SELECT xml FROM doc WHERE name=?"); var haveRefs = new List <string>(); var uniq = new Dictionary <string, string>(); //name -> asmName //using var textFile = File.CreateText(Path.ChangeExtension(dbFile, "txt")); //test. Compresses almost 2 times better than db. _AddDir(dir1, "WindowsBase"); _AddDir(dir2); statInsert.BindAll(".", string.Join("\n", haveRefs)).Step(); trans.Commit(); d.Execute("VACUUM"); AOutput.Write("Created " + dbFile); void _AddDir(string dir, params string[] skip) { foreach (var f in AFile.EnumDirectory(dir)) { if (f.IsDirectory) { continue; } if (!f.Name.Ends(".xml", true)) { continue; } var asmName = f.Name.RemoveSuffix(4); if (skip.Contains(asmName)) { continue; } if (!AFile.ExistsAsFile(dir + asmName + ".dll")) { AOutput.Write("<><c 0x808080>" + f.Name + "</c>"); continue; } _AddFile(asmName, f.FullPath); //break; } } void _AddFile(string asmName, string xmlFile) { //AOutput.Write(asmName); haveRefs.Add(asmName); var xr = AExtXml.LoadElem(xmlFile); foreach (var e in xr.Descendants("member")) { var name = e.Attr("name"); //remove <remarks> and <example>. Does not save much space, because .NET xmls don't have it. foreach (var v in e.Descendants("remarks").ToArray()) { v.Remove(); } foreach (var v in e.Descendants("example").ToArray()) { v.Remove(); } using var reader = e.CreateReader(); reader.MoveToContent(); var xml = reader.ReadInnerXml(); //AOutput.Write(name, xml); //textFile.WriteLine(name); textFile.WriteLine(xml); textFile.WriteLine("\f"); if (uniq.TryGetValue(name, out var prevRef)) { if (!statDupl.Bind(1, name).Step()) { throw new AuException(); } var prev = statDupl.GetText(0); if (xml != prev && asmName != "System.Linq") { AOutput.Write($"<>\t{name} already defined in {prevRef}\r\n<c 0xc000>{prev}</c>\r\n<c 0xff0000>{xml}</c>"); } statDupl.Reset(); } else { statInsert.BindAll(name, xml).Step(); uniq.Add(name, asmName); } statInsert.Reset(); } } }