Пример #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

                // 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;
            }
        }
Пример #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

				// 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;
			}
		}