protected override void WriteOutput(InputOutput io) { Results = io.Output; Output = new StringBuilder(); foreach (LNode node in Results) { LNode.Printer(node, Output, Sink, null, IndentString, NewlineString); Output.Append(NewlineString); } }
protected virtual void WriteOutput(InputOutput io) { Debug.Assert(io.FileName != io.OutFileName); Sink.Write(Severity.Verbose, io, "Writing output file: {0}", io.OutFileName); using (var stream = File.Open(io.OutFileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, Encoding.UTF8)) { var options = new LNodePrinterOptions { IndentString = IndentString, NewlineString = NewlineString }; var str = io.OutPrinter.Print(io.Output, Sink, null, options); writer.Write(str); } }
/// <summary>Opens a set of source files by file name, and creates an <see cref="InputOutput"/> object for each.</summary> /// <param name="sink">Any I/O errors that occur will be logged to this object.</param> /// <param name="fileNames">List of file names</param> /// <returns>a list of files that were opened, together with their settings. /// This method does not run the macro processor on these files.</returns> public static List <InputOutput> OpenSourceFiles(IMessageSink sink, IEnumerable <string> fileNames) { var openFiles = new List <InputOutput>(); foreach (var filename in fileNames) { try { var stream = File.OpenRead(filename); var io = new InputOutput(new StreamCharSource(stream), Path.GetFullPath(filename)); openFiles.Add(io); } catch (Exception ex) { sink.Error(filename, ex.GetType().Name + ": " + ex.Message); } } return(openFiles); }
/// <summary>Opens a set of source files by file name, and creates a text file for each.</summary> /// <param name="sink"></param> /// <param name="fileNames"></param> /// <returns></returns> public static List <InputOutput> OpenSourceFiles(IMessageSink sink, IEnumerable <string> fileNames) { var openFiles = new List <InputOutput>(); foreach (var filename in fileNames) { try { var stream = File.OpenRead(filename); var text = File.ReadAllText(filename, Encoding.UTF8); var io = new InputOutput(new StreamCharSource(stream), filename); openFiles.Add(io); } catch (Exception ex) { sink.Write(Severity.Error, filename, ex.GetType().Name + ": " + ex.Message); } } return(openFiles); }
private void WriteOutput2(InputOutput io) { Debug.Assert(io.FileName != io.OutFileName); Sink.Write(Severity.Verbose, io, "Writing output file: {0}", io.OutFileName); using (var stream = File.Open(io.OutFileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, Encoding.UTF8)) { var sb = new StringBuilder(); foreach (LNode node in io.Output) { io.OutPrinter(node, sb, Sink, null, IndentString, NewlineString); writer.Write(sb.ToString()); writer.Write(NewlineString); sb.Length = 0; // Clear() is new in .NET 4 } } }
public void CompleteInputOutputOptions(InputOutput file) { if (file.InputLang == null) { var inLang = InLang ?? ParsingService.Current; if (!ForceInLang || InLang == null) { inLang = ParsingService.GetServiceForFileName(file.FileName) ?? inLang; } file.InputLang = inLang; } if (file.OutFileName == null) { string inputFN = file.FileName; if (OutExt == null) { file.OutFileName = inputFN; } else { int dot = IndexOfExtension(inputFN); file.OutFileName = inputFN.Left(dot) + OutExt; } if (file.OutFileName == inputFN) { // e.g. input.cs => input.out.cs int dot = IndexOfExtension(inputFN); file.OutFileName = file.OutFileName.Insert(dot, ".out"); } } if (file.OutPrinter == null) { var outLang = OutLang; if (outLang == null && OutExt != null) { var lang = ParsingService.GetServiceForFileName(OutExt); if (lang != null) { outLang = lang.Printer; } } file.OutPrinter = outLang ?? LNode.Printer; } }
/// <summary>Writes results from <see cref="InputOutput.Output"/> to /// <see cref="InputOutput.OutFileName"/> using <see cref="InputOutput.OutPrinter"/> /// according to <see cref="InputOutput.OutOptions"/>.</summary> /// <remarks>In case of --eval inputs, output is sent to the Console. /// Status, warning and error messages are sent to <see cref="Sink"/>.</remarks> protected virtual void WriteOutput(InputOutput io) { Debug.Assert(io.FileName != io.OutFileName); if (io.OutFileName == "" && io.FileName.StartsWith("--eval")) { // Print result of --eval to console var str = io.OutPrinter.Print(io.Output, Sink, null, io.OutOptions); Console.WriteLine(str); } else { Sink.Write(Severity.Verbose, io, "Writing output file: {0}", io.OutFileName); using (var stream = File.Open(io.OutFileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, Encoding.UTF8)) { var str = io.OutPrinter.Print(io.Output, Sink, null, io.OutOptions); writer.Write(str); } } }
public VList <LNode> ProcessFile(InputOutput io, Action <InputOutput> onProcessed) { using (ParsingService.PushCurrent(io.InputLang ?? ParsingService.Current)) { try { string dir = Path.GetDirectoryName(io.FileName); if (!string.IsNullOrEmpty(dir)) { _rootScopedProperties[(Symbol)"#inputFolder"] = dir; } _rootScopedProperties[(Symbol)"#inputFileName"] = Path.GetFileName(io.FileName); } catch (ArgumentException) { } // Path.* may throw catch (PathTooLongException) { } // Path.* may throw var input = ParsingService.Current.Parse(io.Text, io.FileName, _sink); var inputRV = new VList <LNode>(input); io.Output = ProcessRoot(inputRV); if (onProcessed != null) { onProcessed(io); } return(io.Output); } }
public void CompleteInputOutputOptions(InputOutput file) { if (file.InputLang == null) { var inLang = InLang ?? ParsingService.Default; if (!ForceInLang || InLang == null) inLang = ParsingService.GetServiceForFileName(file.FileName) ?? inLang; file.InputLang = inLang; } if (file.OutFileName == null) { string inputFN = file.FileName; if (OutExt == null) file.OutFileName = inputFN; else { int dot = IndexOfExtension(inputFN); file.OutFileName = inputFN.Left(dot) + OutExt; } if (file.OutFileName == inputFN) { // e.g. input.cs => input.out.cs int dot = IndexOfExtension(inputFN); file.OutFileName = file.OutFileName.Insert(dot, ".out"); } } if (file.OutPrinter == null) { var outLang = OutLang; if (outLang == null && OutExt != null) { var lang = ParsingService.GetServiceForFileName(OutExt); if (lang != null) outLang = lang as ILNodePrinter; } file.OutPrinter = outLang ?? LNode.Printer; } if (file.OutOptions == null) file.OutOptions = OutOptions; if (file.PreserveComments == null) file.PreserveComments = PreserveComments; if (file.ParsingMode == null) file.ParsingMode = ParsingMode; }
protected override void WriteOutput(InputOutput io) { RVList<LNode> results = io.Output; var printer = LNode.Printer; if (!NoOutHeader) Output.AppendFormat( "// Generated from {1} by LeMP custom tool. LLLPG version: {2}{0}" + "// Note: you can give command-line arguments to the tool via 'Custom Tool Namespace':{0}" + "// --no-out-header Suppress this message{0}" + "// --verbose Allow verbose messages (shown by VS as 'warnings'){0}" + "// --macros=FileName.dll Load macros from FileName.dll, path relative to this file {0}" + "// Use #importMacros to use macros in a given namespace, e.g. #importMacros(Loyc.LLPG);{0}", NewlineString, Path.GetFileName(io.FileName), typeof(Rule).Assembly.GetName().Version.ToString()); foreach (LNode node in results) { printer(node, Output, Sink, null, IndentString, NewlineString); Output.Append(NewlineString); } }
protected override byte[] Generate(string inputFilePath, string inputFileContents, string defaultNamespace, IVsGeneratorProgress progressCallback) { string oldCurDir = Environment.CurrentDirectory; try { string inputFolder = Path.GetDirectoryName(inputFilePath); Environment.CurrentDirectory = inputFolder; // --macros should be relative to file being processed var options = new BMultiMap<string, string>(); var argList = G.SplitCommandLineArguments(defaultNamespace); UG.ProcessCommandLineArguments(argList, options, "", LeMP.Compiler.ShortOptions, LeMP.Compiler.TwoArgOptions); string _; var KnownOptions = LeMP.Compiler.KnownOptions; if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _)) LeMP.Compiler.ShowHelp(KnownOptions); // Originally I wrote a conversion from IVsGeneratorProgress to // IMessageSink so that errors could be reported immediately and // directly to Visual Studio. This broke in a bizarre way when I // added processing on a separate thread (in order to be able to // abort the thread if it runs too long); I got the following // InvalidCastException: "Unable to cast COM object of type 'System.__ComObject' // to interface type 'Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress'. // This operation failed because the QueryInterface call on the COM component for // the interface with IID '{BED89B98-6EC9-43CB-B0A8-41D6E2D6669D}' failed due to // the following error: No such interface supported (Exception from HRESULT: // 0x80004002 (E_NOINTERFACE))." // // A simple solution is to store the messages rather than reporting // them immediately. I'll report the errors at the very end. MessageHolder sink = new MessageHolder(); var sourceFile = new InputOutput((UString)inputFileContents, Path.GetFileName(inputFilePath)); var c = new Compiler(sink, sourceFile) { AbortTimeout = TimeSpan.FromSeconds(10), Parallel = false // only one file, parallel doesn't help }; if (LeMP.Compiler.ProcessArguments(c, options)) { if (options.ContainsKey("no-out-header")) { options.Remove("no-out-header", 1); c.NoOutHeader = true; } LeMP.Compiler.WarnAboutUnknownOptions(options, sink, KnownOptions); if (c != null) { if (inputFilePath.EndsWith(".les", StringComparison.OrdinalIgnoreCase)) c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les")); Configure(c); c.Run(); // Report errors foreach (var msg in sink.List) ReportErrorToVS(progressCallback, msg.Severity, msg.Context, msg.Format, msg.Args); return Encoding.UTF8.GetBytes(c.Output.ToString()); } } return null; } finally { Environment.CurrentDirectory = oldCurDir; } }
protected override void WriteOutput(InputOutput io) { Results = io.Output; Output = new StringBuilder(); var opts = new LNodePrinterOptions { IndentString = IndentString, NewlineString = NewlineString }; LNode.Printer.Print(Results, Output, Sink, null, opts); }
protected virtual void WriteOutput(InputOutput io) { #if !DotNet2 && !DotNet3 if (Parallel) { // attach to parent so that ProcessParallel does not exit before the file is written Task.Factory.StartNew(() => WriteOutput2(io), TaskCreationOptions.AttachedToParent); return; } #endif WriteOutput2(io); }
public void CompleteInputOutputOptions(InputOutput file) { if (file.InputLang == null) { var inLang = InLang ?? ParsingService.Current; if (!ForceInLang || InLang == null) inLang = FileNameToLanguage(file.FileName) ?? inLang; file.InputLang = inLang; } if (file.OutFileName == null) { string inputFN = file.FileName; if (OutExt == null) file.OutFileName = inputFN; else { int dot = IndexOfExtension(inputFN); file.OutFileName = inputFN.Left(dot) + OutExt; } if (file.OutFileName == inputFN) { // e.g. input.cs => input.out.cs int dot = IndexOfExtension(inputFN); file.OutFileName = file.OutFileName.Insert(dot, ".out"); } } if (file.OutPrinter == null) { var outLang = OutLang; if (outLang == null && OutExt != null) { var lang = FileNameToLanguage(OutExt); if (lang != null) outLang = lang.Printer; } file.OutPrinter = outLang ?? LNode.Printer; } }
/// <summary>Opens a set of source files by file name, and creates a text file for each.</summary> /// <param name="sink"></param> /// <param name="fileNames"></param> /// <returns></returns> public static List<InputOutput> OpenSourceFiles(IMessageSink sink, IEnumerable<string> fileNames) { var openFiles = new List<InputOutput>(); foreach (var filename in fileNames) { try { var stream = File.OpenRead(filename); var text = File.ReadAllText(filename, Encoding.UTF8); var io = new InputOutput(new StreamCharSource(stream), filename); openFiles.Add(io); } catch (Exception ex) { sink.Write(Severity.Error, filename, ex.GetType().Name + ": " + ex.Message); } } return openFiles; }
protected override void WriteOutput(InputOutput io) { Results = io.Output; Output = new StringBuilder(); io.OutPrinter.Print(Results, Output, Sink, null, io.OutOptions); }
public Compiler(IMessageSink sink, InputOutput file) : base(sink, typeof(global::LeMP.Prelude.BuiltinMacros), new [] { file }) { }
protected override byte[] Generate(string inputFilePath, string inputFileContents, string defaultNamespace, IVsGeneratorProgress progressCallback) { string oldCurDir = Environment.CurrentDirectory; try { string inputFolder = Path.GetDirectoryName(inputFilePath); Environment.CurrentDirectory = inputFolder; // --macros should be relative to file being processed // Originally I wrote a conversion from IVsGeneratorProgress to // IMessageSink so that errors could be reported immediately and // directly to Visual Studio. This broke in a bizarre way when I // added processing on a separate thread (in order to be able to // abort the thread if it runs too long); I got the following // InvalidCastException: "Unable to cast COM object of type 'System.__ComObject' // to interface type 'Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress'. // This operation failed because the QueryInterface call on the COM component for // the interface with IID '{BED89B98-6EC9-43CB-B0A8-41D6E2D6669D}' failed due to // the following error: No such interface supported (Exception from HRESULT: // 0x80004002 (E_NOINTERFACE))." // // A simple solution is to store the messages rather than reporting // them immediately. I'll report the errors at the very end. MessageHolder sink = new MessageHolder(); var sourceFile = new InputOutput((UString)inputFileContents, inputFilePath); Compiler.KnownOptions["no-out-header"] = Pair.Create("", "Remove explanatory comment from output file"); Compiler.KnownOptions.Remove("parallel"); // not applicable to single file Compiler.KnownOptions.Remove("noparallel"); // not applicable to single file var c = new Compiler(sink, sourceFile) { AbortTimeout = TimeSpan.FromSeconds(10), Parallel = false // only one file, parallel doesn't help }; var argList = G.SplitCommandLineArguments(defaultNamespace); var options = c.ProcessArguments(argList, true, false); // Note: if default namespace is left blank, VS uses the namespace // from project settings. Don't show an error in that case. if (argList.Count > 1 || (argList.Count == 1 && options.Count > 0)) sink.Write(Severity.Error, "Command line", "'{0}': expected options only (try --help).", argList[0]); string _; if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _)) { var ms = new MemoryStream(); LeMP.Compiler.ShowHelp(LeMP.Compiler.KnownOptions, new StreamWriter(ms), false); return ms.GetBuffer(); } LeMP.Compiler.WarnAboutUnknownOptions(options, sink, LeMP.Compiler.KnownOptions); if (options.ContainsKey("no-out-header")) c.NoOutHeader = true; if (c.InLang == LesLanguageService.Value || inputFilePath.EndsWith(".les", StringComparison.OrdinalIgnoreCase)) c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les")); Configure(c); _requestedExtension = c.OutExt; c.Run(); // Report errors foreach (var msg in sink.List) ReportErrorToVS(progressCallback, msg.Severity, msg.Context, msg.Format, msg.Args); return Encoding.UTF8.GetBytes(c.Output.ToString()); } finally { Environment.CurrentDirectory = oldCurDir; } }
protected override void WriteOutput(InputOutput io) { VList<LNode> results = io.Output; if (!NoOutHeader) Output.AppendFormat( "// Generated from {1} by LeMP custom tool. LeMP version: {2}{0}" + "// Note: you can give command-line arguments to the tool via 'Custom Tool Namespace':{0}" + "// --no-out-header Suppress this message{0}" + "// --verbose Allow verbose messages (shown by VS as 'warnings'){0}" + "// --timeout=X Abort processing thread after X seconds (default: 10){0}" + "// --macros=FileName.dll Load macros from FileName.dll, path relative to this file {0}" + "// Use #importMacros to use macros in a given namespace, e.g. #importMacros(Loyc.LLPG);{0}", NewlineString, Path.GetFileName(io.FileName), typeof(MacroProcessor).Assembly.GetName().Version.ToString()); var options = new LNodePrinterOptions { IndentString = IndentString, NewlineString = NewlineString }; LNode.Printer.Print(results, Output, Sink, ParsingMode.File, options); }