private static ReturnCode runOnce2(TypeCobolConfiguration config, AbstractErrorWriter errorWriter) { SymbolTable baseTable = null; #region Dependencies parsing var depParser = new Parser(); bool diagDetected = false; if (config.ExecToStep > ExecutionStep.Preprocessor) { #region Event Diags Handler EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DiagnosticsErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics diagDetected = true; var diagnostic = diagEvent.Diagnostic; Server.AddError(errorWriter, MessageCode.IntrinsicLoading, diagnostic.ColumnStart, diagnostic.ColumnEnd, diagnostic.Line, "Error while parsing " + diagEvent.Path + ": " + diagnostic, diagEvent.Path); }; EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DependencyErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics Server.AddError(errorWriter, diagEvent.Path, diagEvent.Diagnostic); }; #endregion depParser.CustomSymbols = Tools.APIHelpers.Helpers.LoadIntrinsic(config.Copies, config.Format, DiagnosticsErrorEvent); //Load intrinsic depParser.CustomSymbols = Tools.APIHelpers.Helpers.LoadDependencies(config.Dependencies, config.Format, depParser.CustomSymbols, config.InputFiles, config.CopyFolders, DependencyErrorEvent); //Load dependencies if (diagDetected) { throw new CopyLoadingException("Diagnostics detected while parsing Intrinsic file", null, null, logged: false, needMail: false); } } baseTable = depParser.CustomSymbols; #endregion var typeCobolOptions = new TypeCobolOptions(config); #if EUROINFO_RULES typeCobolOptions.AutoRemarksEnable = config.AutoRemarks; #endif ReturnCode returnCode = ReturnCode.Success; List <Parser> parsers = new List <Parser>(); List <Compiler.Report.AbstractReport> reports = new List <AbstractReport>(); bool copyAreMissing = false; List <Diagnostic> diagnostics = new List <Diagnostic>(); foreach (var inputFilePath in config.InputFiles) { var parser = new Parser(); parser.CustomSymbols = baseTable; parsers.Add(parser); if (config.ExecToStep > ExecutionStep.SemanticCheck) //If inferior to semantic, use the execstep given by the user. { typeCobolOptions.ExecToStep = ExecutionStep.SemanticCheck; } try { parser.Init(inputFilePath, typeCobolOptions, config.Format, config.CopyFolders); //Init parser create CompilationProject & Compiler before parsing the given file } catch (Exception ex) { throw new ParsingException(MessageCode.ParserInit, ex.Message, inputFilePath, ex); //Make ParsingException trace back to RunOnce() } #region Copy Report Init if (config.ExecToStep >= ExecutionStep.CrossCheck) { if (!string.IsNullOrEmpty(config.ReportCopyMoveInitializeFilePath)) { if (config.UseAntlrProgramParsing) { Compiler.Parser.NodeDispatcher <Antlr4.Runtime.ParserRuleContext> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Antlr4.Runtime.ParserRuleContext>(config.ReportCopyMoveInitializeFilePath); reports.Add(report); return(report); }); } else { Compiler.Parser.NodeDispatcher <Compiler.CodeElements.CodeElement> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Compiler.CodeElements.CodeElement>(config.ReportCopyMoveInitializeFilePath); reports.Add(report); return(report); }); } } if (!string.IsNullOrEmpty(config.ReportZCallFilePath)) { if (config.UseAntlrProgramParsing) { Compiler.Parser.NodeDispatcher <Antlr4.Runtime.ParserRuleContext> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.ZCallPgmReport <Antlr4.Runtime.ParserRuleContext>(config.ReportZCallFilePath); reports.Add(report); return(report); }); } else { Compiler.Parser.NodeDispatcher <Compiler.CodeElements.CodeElement> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.ZCallPgmReport <Compiler.CodeElements.CodeElement>(config.ReportZCallFilePath); reports.Add(report); return(report); }); } } } #endregion //Parse input file parser.Parse(inputFilePath); diagnostics.AddRange(parser.Results.AllDiagnostics()); //Get all diags errorWriter.AddErrors(inputFilePath, diagnostics.Take(config.MaximumDiagnostics == 0 ? diagnostics.Count : config.MaximumDiagnostics)); //Write diags into error file if (!string.IsNullOrEmpty(config.HaltOnMissingCopyFilePath)) { if (parser.MissingCopys.Count > 0) { //Collect the missing copies copyAreMissing = true; File.WriteAllLines(config.HaltOnMissingCopyFilePath, parser.MissingCopys); } else { //Delete the file File.Delete(config.HaltOnMissingCopyFilePath); } } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExtractedCopiesFilePath)) { if (parser.Results.CopyTextNamesVariations.Count > 0) { #if EUROINFO_RULES IEnumerable <string> copiesName; if (config.UseEuroInformationLegacyReplacingSyntax) { copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextName).Distinct(); //Get copies without suffix } else { copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextNameWithSuffix).Distinct(); //Get copies with suffix } #else var copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextNameWithSuffix).Distinct(); //Get copies with suffix #endif //Create an output document of all the copy encountered by the parser File.WriteAllLines(config.ExtractedCopiesFilePath, copiesName); } else { File.Delete(config.ExtractedCopiesFilePath); } } if (copyAreMissing) { throw new MissingCopyException("Some copy are missing", inputFilePath, null, logged: false, needMail: false); } if (parser.Results.CodeElementsDocumentSnapshot == null && config.ExecToStep > ExecutionStep.Preprocessor) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + inputFilePath + "\" has syntactic error(s) preventing codegen (CodeElements).", inputFilePath); //Make ParsingException trace back to RunOnce() } else if (parser.Results.TemporaryProgramClassDocumentSnapshot == null && config.ExecToStep > ExecutionStep.SyntaxCheck) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + inputFilePath + "\" has semantic error(s) preventing codegen (ProgramClass).", inputFilePath); //Make ParsingException trace back to RunOnce() } if (config.ExecToStep >= ExecutionStep.SemanticCheck) { foreach (var program in parser.Results.TemporaryProgramClassDocumentSnapshot.Root.Programs) { var previousPrograms = baseTable.GetPrograms(); foreach (var previousProgram in previousPrograms) { previousProgram.SymbolTable.GetTableFromScope(SymbolTable.Scope.Namespace).AddProgram(program); } baseTable.AddProgram(program); //Add program to Namespace symbol table } } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExpandingCopyFilePath)) { try { StringBuilder generatedCobolStringBuilder = new StringBuilder(); var generator = GeneratorFactoryManager.Instance.Create(TypeCobol.Tools.Options_Config.OutputFormat.ExpandingCopy.ToString(), parser.Results, generatedCobolStringBuilder, null, null); var streamWriter = new StreamWriter(config.ExpandingCopyFilePath); generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); streamWriter.Write(generatedCobolStringBuilder); streamWriter.Flush(); streamWriter.Close(); } catch (Exception e) { throw new GenerationException(e.Message, inputFilePath, e); } } } //Then do the CrossCheck when all the programs are loaded in SymbolTable if (config.ExecToStep > ExecutionStep.SemanticCheck) { int fileIndex = 0; foreach (var parser in parsers) { parser.Results.RefreshProgramClassDocumentSnapshot(); //Do Cross Check phase for each file diagnostics.Clear(); diagnostics.AddRange(parser.Results.AllDiagnostics()); //Get all diags errorWriter.Errors.Clear(); //Clear errorWriter because of the potential previous diags errorWriter.AddErrors(config.InputFiles[fileIndex], diagnostics.Take(config.MaximumDiagnostics == 0 ? diagnostics.Count : config.MaximumDiagnostics)); //Write diags into error file if (diagnostics.Count > 0) { foreach (var diag in diagnostics) { if (diag.CatchedException != null) { AnalyticsWrapper.Telemetry.TrackException(diag.CatchedException, config.InputFiles[fileIndex]); AnalyticsWrapper.Telemetry.SendMail(diag.CatchedException, config.InputFiles, config.CopyFolders, config.CommandLine); } } } if (diagnostics.Count == 0) { if (config.ExecToStep >= ExecutionStep.CrossCheck && reports != null && reports.Count > 0) { foreach (var report in reports) { try { report.Report(); string msg = string.Format( "Succeed to emit report '{0}'", report.Filepath); Console.WriteLine(msg); } catch (Exception e) { Console.Error.WriteLine(e.Message); throw new GenerationException(e.Message, report.Filepath, e); } } } } if (diagnostics.Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Error)) { throw new PresenceOfDiagnostics("Diagnostics Detected", config.InputFiles[fileIndex]); //Make ParsingException trace back to RunOnce() } if (diagnostics.Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Warning)) { returnCode = ReturnCode.Warning; } if (config.ExecToStep >= ExecutionStep.Generate) { try { //Load skeletons if necessary List <Skeleton> skeletons = null; if (!(string.IsNullOrEmpty(config.skeletonPath))) { skeletons = TypeCobol.Codegen.Config.Config.Parse(config.skeletonPath); } var sb = new StringBuilder(); //Get Generator from specified config.OutputFormat var generator = GeneratorFactoryManager.Instance.Create(config.OutputFormat.ToString(), parser.Results, sb, skeletons, AnalyticsWrapper.Telemetry.TypeCobolVersion); if (generator == null) { throw new GenerationException("Unknown OutputFormat=" + config.OutputFormat + "_", config.InputFiles[fileIndex]); } //Generate and check diagnostics generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); if (generator.Diagnostics != null) { errorWriter.AddErrors(config.InputFiles[fileIndex], generator.Diagnostics); //Write diags into error file throw new PresenceOfDiagnostics("Diagnostics Detected", config.InputFiles[fileIndex]); //Make ParsingException trace back to RunOnce() } var outputDirectory = new FileInfo(config.OutputFiles[fileIndex]).Directory; var lockFilePath = outputDirectory.FullName + Path.DirectorySeparatorChar + "~.lock"; if (File.Exists(lockFilePath)) { errorWriter.AddErrors(config.InputFiles[fileIndex], new Diagnostic(MessageCode.GenerationFailled, 0, 0, 0)); } else { var lockWriter = new StreamWriter(lockFilePath); lockWriter.Flush(); lockWriter.Close(); using (var streamWriter = new StreamWriter(config.OutputFiles[fileIndex])) { try { streamWriter.Write(sb); //Write generated Cobol inside file streamWriter.Flush(); } catch (Exception) { throw; } finally { File.Delete(lockFilePath); //Remove lock to allow watchers to read the file streamWriter.Close(); } } } } catch (PresenceOfDiagnostics) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (GenerationException) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (Exception e) { //Otherwise create a new GenerationException throw new GenerationException(e.Message, config.InputFiles[fileIndex], e); } fileIndex++; } } } return(returnCode); }
private static ReturnCode runOnce2(TypeCobolConfiguration config, AbstractErrorWriter errorWriter) { var parser = new Parser(); bool diagDetected = false; if (config.ExecToStep > ExecutionStep.Preprocessor) { #region Event Diags Handler EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DiagnosticsErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics diagDetected = true; var diagnostic = diagEvent.Diagnostic; Server.AddError(errorWriter, MessageCode.IntrinsicLoading, diagnostic.ColumnStart, diagnostic.ColumnEnd, diagnostic.Line, "Error while parsing " + diagEvent.Path + ": " + diagnostic, diagEvent.Path); }; EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DependencyErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics Server.AddError(errorWriter, diagEvent.Path, diagEvent.Diagnostic); }; #endregion parser.CustomSymbols = Tools.APIHelpers.Helpers.LoadIntrinsic(config.Copies, config.Format, DiagnosticsErrorEvent); //Load intrinsic parser.CustomSymbols = Tools.APIHelpers.Helpers.LoadDependencies(config.Dependencies, config.Format, parser.CustomSymbols, config.InputFiles, DependencyErrorEvent); //Load dependencies if (diagDetected) { throw new CopyLoadingException("Diagnostics detected while parsing Intrinsic file", null, null, logged: false, needMail: false); } } ReturnCode returnCode = ReturnCode.Success; for (int c = 0; c < config.InputFiles.Count; c++) { string path = config.InputFiles[c]; try { var typeCobolOptions = new TypeCobolOptions { HaltOnMissingCopy = config.HaltOnMissingCopyFilePath != null, ExecToStep = config.ExecToStep, UseAntlrProgramParsing = config.UseAntlrProgramParsing }; #if EUROINFO_RULES typeCobolOptions.AutoRemarksEnable = config.AutoRemarks; #endif parser.Init(path, typeCobolOptions, config.Format, config.CopyFolders); //Init parser create CompilationProject & Compiler before parsing the given file } catch (Exception ex) { throw new ParsingException(MessageCode.ParserInit, ex.Message, path, ex); //Make ParsingException trace back to RunOnce() } Compiler.Report.AbstractReport cmrReport = null; if (config.ExecToStep >= ExecutionStep.CrossCheck && !string.IsNullOrEmpty(config.ReportCopyMoveInitializeFilePath)) { //Register Copy Move Initialize Reporter if (config.UseAntlrProgramParsing) { Compiler.Parser.NodeDispatcher <Antlr4.Runtime.ParserRuleContext> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Antlr4.Runtime.ParserRuleContext>(); cmrReport = report; return(report); }); } else { Compiler.Parser.NodeDispatcher <Compiler.CodeElements.CodeElement> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Compiler.CodeElements.CodeElement>(); cmrReport = report; return(report); }); } } parser.Parse(path); bool copyAreMissing = false; if (!string.IsNullOrEmpty(config.HaltOnMissingCopyFilePath)) { if (parser.MissingCopys.Count > 0) { //Write in the specified file all the absent copys detected File.WriteAllLines(config.HaltOnMissingCopyFilePath, parser.MissingCopys); copyAreMissing = true; } else { //Delete the file File.Delete(config.HaltOnMissingCopyFilePath); } } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExtractedCopiesFilePath)) { if (parser.Results.CopyTextNamesVariations.Count > 0) { #if EUROINFO_RULES var copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextName).Distinct(); //Get copies without suffix #else var copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextNameWithSuffix).Distinct(); //Get copies with suffix #endif //Create an output document of all the copy encountered by the parser File.WriteAllLines(config.ExtractedCopiesFilePath, copiesName); } else { File.Delete(config.ExtractedCopiesFilePath); } } var allDiags = parser.Results.AllDiagnostics(); errorWriter.AddErrors(path, allDiags.Take(config.MaximumDiagnostics == 0 ? allDiags.Count : config.MaximumDiagnostics)); //Write diags into error file if (allDiags.Count > 0) { foreach (var diag in allDiags) { if (diag.CatchedException != null) { AnalyticsWrapper.Telemetry.TrackException(diag.CatchedException); AnalyticsWrapper.Telemetry.SendMail(diag.CatchedException, config.InputFiles, config.CopyFolders, config.CommandLine); } } AnalyticsWrapper.Telemetry.TrackEvent("[Diagnostics] Detected", EventType.Diagnostics); //Exception is thrown just below } if (allDiags.Count == 0) { if (config.ExecToStep >= ExecutionStep.CrossCheck && !string.IsNullOrEmpty(config.ReportCopyMoveInitializeFilePath) && cmrReport != null) {//Emit any COPY MOVE/INITIALIZE Report. try { cmrReport.Report(config.ReportCopyMoveInitializeFilePath); string msg = string.Format( "Succeed to emit report '{0}' on MOVE and INITIALIZE statements that target COPYs.", config.ReportCopyMoveInitializeFilePath); Console.WriteLine(msg); } catch (Exception e) { string msg = string.Format( "Failed to emit report '{0}' on MOVE and INITIALIZE statements that target COPYs! : {1}", config.ReportCopyMoveInitializeFilePath, e.Message); Console.Error.WriteLine(msg); throw new GenerationException(msg, config.ReportCopyMoveInitializeFilePath, e); } } } //Copy missing is more important than diagnostics if (copyAreMissing) { throw new MissingCopyException("Some copy are missing", path, null, logged: false, needMail: false); } else if (parser.Results.AllDiagnostics().Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Error)) { throw new PresenceOfDiagnostics("Diagnostics Detected"); //Make ParsingException trace back to RunOnce() } if (parser.Results.CodeElementsDocumentSnapshot == null && config.ExecToStep > ExecutionStep.Preprocessor) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has syntactic error(s) preventing codegen (CodeElements).", path); //Make ParsingException trace back to RunOnce() } else if (parser.Results.ProgramClassDocumentSnapshot == null && config.ExecToStep > ExecutionStep.SyntaxCheck) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has semantic error(s) preventing codegen (ProgramClass).", path); //Make ParsingException trace back to RunOnce() } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExpandingCopyFilePath)) { try { StringBuilder generatedCobolStringBuilder = new StringBuilder(); var generator = GeneratorFactoryManager.Instance.Create(TypeCobol.Tools.Options_Config.OutputFormat.ExpandingCopy.ToString(), parser.Results, generatedCobolStringBuilder, null, null); var streamWriter = new StreamWriter(config.ExpandingCopyFilePath); generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); streamWriter.Write(generatedCobolStringBuilder); streamWriter.Flush(); streamWriter.Close(); } catch (Exception e) { throw new GenerationException(e.Message, path, e); } } if (config.ExecToStep >= ExecutionStep.Generate) { var streamWriter = new StreamWriter(config.OutputFiles[c]); try { //Load skeletons if necessary List <Skeleton> skeletons = null; if (!(string.IsNullOrEmpty(config.skeletonPath))) { skeletons = TypeCobol.Codegen.Config.Config.Parse(config.skeletonPath); } var sb = new StringBuilder(); //Get Generator from specified config.OutputFormat var generator = GeneratorFactoryManager.Instance.Create(config.OutputFormat.ToString(), parser.Results, sb, skeletons, AnalyticsWrapper.Telemetry.TypeCobolVersion); if (generator == null) { throw new GenerationException("Unknown OutputFormat=" + config.OutputFormat + "_", path); } //Generate and check diagnostics generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); if (generator.Diagnostics != null) { errorWriter.AddErrors(path, generator.Diagnostics); //Write diags into error file throw new PresenceOfDiagnostics("Diagnostics Detected"); //Make ParsingException trace back to RunOnce() } streamWriter.Write(sb); //Write generated Cobol inside file streamWriter.Flush(); streamWriter.Close(); } catch (PresenceOfDiagnostics) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (GenerationException) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (Exception e) { //Otherwise create a new GenerationException throw new GenerationException(e.Message, path, e); } } if (parser.Results.AllDiagnostics().Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Warning)) { returnCode = ReturnCode.Warning; } } return(returnCode); }