Exemplo n.º 1
0
        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, inputFilePath);

                var c = new Compiler(sink, sourceFile)
                {
                    AbortTimeout = TimeSpan.FromSeconds(10),
                    Parallel     = false                 // only one file, parallel doesn't help
                };

                if (c.ProcessArguments(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;
            }
        }
Exemplo n.º 2
0
		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;
			}
		}