/// <summary> /// Extracts meta comments from all C# files of this compilation, including project files and files added through meta option 'c'. /// Returns false if there are errors, except with flag ForCodeInfo. Then use <see cref="Errors"/>. /// </summary> /// <param name="f">Main C# file. If projFolder not null, must be the main file of the project.</param> /// <param name="projFolder">Project folder of the main file, or null if it is not in a project.</param> /// <param name="flags"></param> public bool Parse(FileNode f, FileNode projFolder, EMPFlags flags) { Debug.Assert(Errors == null); //cannot be called multiple times Errors = new ErrBuilder(); _flags = flags; _ParseFile(f, true); if (projFolder != null) { foreach (var ff in projFolder.EnumProjectClassFiles(f)) { _ParseFile(ff, false); } } if (_filesC != null) { foreach (var ff in _filesC) { if (CodeFiles.Exists(o => o.f == ff)) { continue; } _ParseFile(ff, false); } } if (!Optimize) { if (!Defines.Contains("DEBUG")) { Defines.Add("DEBUG"); } if (!Defines.Contains("TRACE")) { Defines.Add("TRACE"); } } //if(Role == ERole.exeProgram && !Defines.Contains("EXE")) Defines.Add("EXE"); //rejected _FinalCheckOptions(); if (Errors.ErrorCount > 0) { if (flags.Has(EMPFlags.PrintErrors)) { Errors.PrintAll(); } return(false); } return(true); }
/// <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];