/// <summary> /// Called before executing script f. If returns true, don't need to compile. /// </summary> /// <param name="f"></param> /// <param name="r">Receives file path and execution options.</param> /// <param name="projFolder">Project folder or null. If not null, f must be its main file.</param> public bool IsCompiled(FileNode f, out CompResults r, FileNode projFolder) { r = new CompResults(); if (_data == null && !_Open()) { return(false); } if (!_data.TryGetValue(f.Id, out string value)) { return(false); } //ADebug.Print(value); int iPipe = 0; bool isScript = f.IsScript; r.role = MetaComments.DefaultRole(isScript); string asmFile; if (r.notInCache = (value != null && value.Starts("|="))) { iPipe = value.IndexOf('|', 2); if (iPipe < 0) { iPipe = value.Length; } asmFile = value.Substring(2, iPipe - 2); } else { asmFile = CacheDirectory + "\\" + f.IdString; } //AOutput.Write(asmFile); if (!AFile.GetProperties(asmFile, out var asmProp, FAFlags.UseRawPath)) { return(false); } DateTime asmDate = asmProp.LastWriteTimeUtc; if (_IsFileModified(f)) { return(false); } bool isMultiFileProject = false; if (value != null && iPipe < value.Length) { iPipe++; foreach (var v in value.Segments("|", SegFlags.NoEmpty, iPipe..)) { int offs = v.start + 1; char ch = value[v.start]; switch (ch) { case 't': r.role = (ERole)value.ToInt(offs); break; case 'a': r.runMode = (ERunMode)value.ToInt(offs); break; case 'n': r.ifRunning = (EIfRunning)value.ToInt(offs); break; case 'N': r.ifRunning2 = (EIfRunning2)value.ToInt(offs); break; case 'u': r.uac = (EUac)value.ToInt(offs); break; case 'b': r.prefer32bit = true; break; case 'q': r.console = true; break; case 'z': r.mtaThread = true; break; case 'd': r.pdbOffset = value.ToInt(offs); break; case 'p': isMultiFileProject = true; if (projFolder != null) { if (!Util.AHash.MD5Result.FromString(value.AsSpan(offs, v.end - offs), out var md5)) { return(false); } Util.AHash.MD5 md = default; foreach (var f1 in projFolder.EnumProjectClassFiles(f)) { if (_IsFileModified(f1)) { return(false); } md.Add(f1.Id); } if (md.IsEmpty || md.Hash != md5) { return(false); } } break; case '*': var dll = value[offs..v.end];
/// <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 int s_test; public static void AddSnippets(List <CiComplItem> items, TextSpan span, SyntaxNode node) { //don't add snippets if in arguments etc. // Add only where can be a statement or declaration or likely a directive. // The caller also does some simple filtering. //AOutput.Clear(); AOutput.Write(++s_test); int pos = span.Start; //find ancestor/self that contains pos inside while (node != null && !node.Span.ContainsInside(pos)) { node = node.Parent; } if (node is ArgumentListSyntax als) //return unless => is at left (lambda expression) { var left = node.FindToken(pos).GetPreviousToken().Parent; //CiUtil.PrintNode(left); if (!(left is SimpleLambdaExpressionSyntax)) { return; } } else { //for(var v = node; v != null; v = v.Parent) AOutput.Write(v.GetType().Name); switch (node) { case null: case CompilationUnitSyntax _: case BlockSyntax _: case SimpleLambdaExpressionSyntax _: case ArrowExpressionClauseSyntax _: //like void F() => case SwitchSectionSyntax _: //between case: and break; case ElseClauseSyntax _: case IfStatementSyntax s1 when pos > s1.CloseParenToken.SpanStart: case WhileStatementSyntax s2 when pos > s2.CloseParenToken.SpanStart: case DoStatementSyntax s3 when pos <s3.WhileKeyword.SpanStart: case ForStatementSyntax s4 when pos> s4.CloseParenToken.SpanStart: case CommonForEachStatementSyntax s5 when pos > s5.CloseParenToken.SpanStart: case LockStatementSyntax s6 when pos > s6.CloseParenToken.SpanStart: case FixedStatementSyntax s7 when pos > s7.CloseParenToken.SpanStart: case UsingStatementSyntax s8 when pos > s8.CloseParenToken.SpanStart: case TypeDeclarationSyntax td when pos > td.OpenBraceToken.Span.Start: //{ } of class, struct, interface case NamespaceDeclarationSyntax ns when pos > ns.OpenBraceToken.Span.Start: break; default: return; } } DateTime fileTime = default; if (Program.Settings.ci_complCustomSnippets == 1 && AFile.GetProperties(CustomFile, out var fp, FAFlags.DontThrow | FAFlags.UseRawPath)) { fileTime = fp.LastWriteTimeUtc; } if (fileTime != s_customFileTime) { s_customFileTime = fileTime; s_items = null; } if (s_items == null) { string file = fileTime == default ? DefaultFile : CustomFile; try { var xroot = AExtXml.LoadElem(file); var a = new List <_CiComplItemSnippet>(); foreach (var x in xroot.Elements("snippet")) { var ci = CompletionItem.Create(x.Attr("name"), tags: s_tags); a.Add(new _CiComplItemSnippet(ci, x)); } s_items = a; } catch (Exception ex) { AOutput.Write("Failed to load snippets from " + file + "\r\n\t" + ex.ToStringWithoutStack()); return; } } foreach (var v in s_items) { v.group = 0; v.hidden = 0; v.hilite = 0; v.moveDown = 0; v.ci.Span = span; items.Add(v); } items.Sort((i1, i2) => { var r = string.Compare(i1.DisplayText, i2.DisplayText, StringComparison.OrdinalIgnoreCase); if (r == 0) { r = i1.kind - i2.kind; } return(r); }); }