예제 #1
0
        /// <summary>
        /// Creates a compilation options
        /// </summary>
        /// <returns>Compilation options</returns>
        private LocalJsCompilationOptions CreateCompilationOptions()
        {
            var options = new LocalJsCompilationOptions
            {
                AcceptConstKeyword             = AcceptConstKeyword,
                AllowEs6Output                 = AllowEs6Output,
                AngularPass                    = AngularPass,
                DefinitionList                 = DefinitionList,
                ErrorList                      = ErrorList,
                ExportLocalPropertyDefinitions = ExportLocalPropertyDefinitions,
                ExtraAnnotationNameList        = ExtraAnnotationNameList,
                GenerateExports                = GenerateExports,
                LanguageInput                  = LanguageInput,
                LanguageOutput                 = LanguageOutput,
                ProcessClosurePrimitives       = ProcessClosurePrimitives,
                ProcessJqueryPrimitives        = ProcessJqueryPrimitives,
                SingleQuotes                   = SingleQuotes,
                ThirdParty                     = ThirdParty,
                TranspileOnly                  = TranspileOnly,
                TurnOffWarningClassList        = TurnOffWarningClassList,
                UseOnlyCustomExterns           = UseOnlyCustomExterns,
                WarningList                    = WarningList
            };

            FillJsCompilationOptions(options);

            return(options);
        }
		/// <summary>
		/// Creates a compilation options
		/// </summary>
		/// <returns>Compilation options</returns>
		private LocalJsCompilationOptions CreateCompilationOptions()
		{
			var options = new LocalJsCompilationOptions
			{
				AcceptConstKeyword = AcceptConstKeyword,
				AllowEs6Output = AllowEs6Output,
				AngularPass = AngularPass,
				DefinitionList = DefinitionList,
				ErrorList = ErrorList,
				ExportLocalPropertyDefinitions = ExportLocalPropertyDefinitions,
				ExtraAnnotationNameList = ExtraAnnotationNameList,
				GenerateExports = GenerateExports,
				LanguageInput = LanguageInput,
				LanguageOutput = LanguageOutput,
				ProcessClosurePrimitives = ProcessClosurePrimitives,
				ProcessJqueryPrimitives = ProcessJqueryPrimitives,
				SingleQuotes = SingleQuotes,
				ThirdParty = ThirdParty,
				TranspileOnly = TranspileOnly,
				TurnOffWarningClassList = TurnOffWarningClassList,
				UseOnlyCustomExterns = UseOnlyCustomExterns,
				WarningList = WarningList
			};
			FillJsCompilationOptions(options);

			return options;
		}
		/// <summary>
		/// Converts a compilation options to command line arguments
		/// </summary>
		/// <param name="options">Compilation options</param>
		/// <returns>Command line arguments</returns>
		private static string ConvertCompilationOptionsToArgs(LocalJsCompilationOptions options)
		{
			var args = new StringBuilder();

			if (options.AcceptConstKeyword)
			{
				args.Append("--accept_const_keyword ");
			}

			if (options.AllowEs6Output)
			{
				args.Append("--allow_es6_out ");
			}

			if (options.AngularPass)
			{
				args.Append("--angular_pass ");
			}

			if (!string.IsNullOrWhiteSpace(options.Charset))
			{
				args.AppendFormat("--charset {0} ", options.Charset);
			}

			args.AppendFormat("--compilation_level {0} ", ConvertCompilationLevelEnumValueToCode(options.CompilationLevel));

			IDictionary<string, string> defs = ParseDefinitions(options.DefinitionList);
			if (defs.Count > 0)
			{
				foreach (KeyValuePair<string, string> def in defs)
				{
					string variableName = def.Key;
					string variableValue = def.Value;

					args.Append("--define ");
					args.Append(variableName);
					if (variableValue != null)
					{
						args.AppendFormat("={0}", variableValue);
					}
					args.Append(" ");
				}
			}

			string[] errors = Utils.ConvertToStringCollection(options.ErrorList, ',',
				trimItemValues: true, removeEmptyItems: true);
			if (errors.Length > 0)
			{
				foreach (string warningClassName in errors)
				{
					args.AppendFormat("--jscomp_error {0} ", warningClassName);
				}
			}

			if (options.ExportLocalPropertyDefinitions)
			{
				args.Append("--export_local_property_definitions ");
			}

			string[] extraAnnotationNames = Utils.ConvertToStringCollection(options.ExtraAnnotationNameList, ',',
				trimItemValues: true, removeEmptyItems: true);
			if (extraAnnotationNames.Length > 0)
			{
				foreach (string extraAnnotationName in extraAnnotationNames)
				{
					args.AppendFormat("--extra_annotation_name {0} ", extraAnnotationName);
				}
			}

			if (options.GenerateExports)
			{
				args.Append("--generate_exports ");
			}

			ExperimentalLanguageSpec languageInput = options.LanguageInput;
			if (languageInput != ExperimentalLanguageSpec.None)
			{
				args.AppendFormat("--language_in {0} ", ConvertLanguageSpecEnumValueToCode(languageInput));
			}

			ExperimentalLanguageSpec languageOutput = (options.LanguageOutput != ExperimentalLanguageSpec.None) ?
				options.LanguageOutput : languageInput;
			if (languageOutput != ExperimentalLanguageSpec.None)
			{
				args.AppendFormat("--language_out {0} ", ConvertLanguageSpecEnumValueToCode(languageOutput));
			}

			if (options.PrettyPrint)
			{
				args.Append("--formatting PRETTY_PRINT ");
			}

			if (options.ProcessClosurePrimitives)
			{
				args.Append("--process_closure_primitives ");
			}

			if (options.ProcessJqueryPrimitives)
			{
				args.Append("--process_jquery_primitives ");
			}

			if (options.SingleQuotes)
			{
				args.Append("--formatting SINGLE_QUOTES ");
			}

			if (options.ThirdParty)
			{
				args.Append("--third_party ");
			}

			if (options.TranspileOnly)
			{
				args.Append("--transpile_only ");
			}

			string[] turnOffWarningClasses = Utils.ConvertToStringCollection(options.TurnOffWarningClassList, ',',
				trimItemValues: true, removeEmptyItems: true);
			if (turnOffWarningClasses.Length > 0)
			{
				foreach (string warningClassName in turnOffWarningClasses)
				{
					args.AppendFormat("--jscomp_off {0} ", warningClassName);
				}
			}

			if (options.UseOnlyCustomExterns)
			{
				args.Append("--use_only_custom_externs ");
			}

			if (options.UseTypesForOptimization)
			{
				args.Append("--use_types_for_optimization ");
			}

			string[] warnings = Utils.ConvertToStringCollection(options.WarningList, ',',
				trimItemValues: true, removeEmptyItems: true);
			if (warnings.Length > 0)
			{
				foreach (string warningClassName in warnings)
				{
					args.AppendFormat("--jscomp_warning {0} ", warningClassName);
				}
			}

			int severity = options.Severity;
			if (severity >= 0 && severity <= 3)
			{
				args.Append("--warning_level ");

				switch (severity)
				{
					case 0:
					case 1:
						args.Append("QUIET ");
						break;
					case 2:
						args.Append("DEFAULT ");
						break;
					case 3:
						args.Append("VERBOSE ");
						break;
				}
			}

			return args.ToString();
		}
		/// <summary>
		/// Constructs a instance of local Closure Compiler
		/// </summary>
		/// <param name="javaVmPath">Path to Java Virtual Machine</param>
		/// <param name="closureCompilerAppPath">Path to Google Closure Compiler Application</param>
		/// <param name="tempDirectoryPath">Absolute path to directory that contains temporary files</param>
		/// <param name="commonExternsDependencies">List of common JS-externs dependencies</param>
		/// <param name="defaultOptions">Default compilation options</param>
		public ClosureLocalJsCompiler(string javaVmPath, string closureCompilerAppPath,
			string tempDirectoryPath, DependencyCollection commonExternsDependencies,
			LocalJsCompilationOptions defaultOptions)
			: base(commonExternsDependencies)
		{
			_javaVmPath = javaVmPath;
			_closureCompilerAppPath = closureCompilerAppPath;
			_tempDirectoryPath = tempDirectoryPath;
			_commonExternsTempDirectoryPath = string.Empty;
			_commonExternsTempDirectoryCreated = false;
			_commonExternsTempFilePaths = new List<string>();
			_defaultOptions = defaultOptions;
			_defaultOptionsString = (defaultOptions != null) ?
				ConvertCompilationOptionsToArgs(defaultOptions) : "null";
		}
		/// <summary>
		/// "Compiles" a JS-code
		/// </summary>
		/// <param name="content">Text content written on JavaScript</param>
		/// <param name="path">Path to JS-file</param>
		/// <param name="externsDependencies">List of JS-externs dependencies</param>
		/// <param name="options">Compilation options</param>
		/// <returns>Compiled JS-code</returns>
		public string Compile(string content, string path, DependencyCollection externsDependencies,
			LocalJsCompilationOptions options = null)
		{
			string newContent;
			int commonExternsDependencyCount = _commonExternsDependencies.Count;
			string assetExternsTempDirectoryPath = Path.Combine(_tempDirectoryPath, Guid.NewGuid().ToString());
			bool assetExternsTempDirectoryCreated = false;
			LocalJsCompilationOptions currentOptions;
			string currentOptionsString;

			if (options != null)
			{
				currentOptions = options;
				currentOptionsString = ConvertCompilationOptionsToArgs(options);
			}
			else
			{
				currentOptions = _defaultOptions;
				currentOptionsString = _defaultOptionsString;
			}

			var args = new StringBuilder();
			args.AppendFormat(@"-jar ""{0}"" ", _closureCompilerAppPath);
			if (currentOptions.CompilationLevel == CompilationLevel.Advanced
				&& (commonExternsDependencyCount > 0 || externsDependencies.Count > 0))
			{
				if (!_commonExternsTempDirectoryCreated && commonExternsDependencyCount > 0)
				{
					WriteExternsToTempDirectory(_commonExternsDependencies, out _commonExternsTempDirectoryPath,
						out _commonExternsTempFilePaths);
					_commonExternsTempDirectoryCreated = true;
				}

				DependencyCollection assetExternsDependencies = new DependencyCollection();
				if (commonExternsDependencyCount > 0)
				{
					foreach (Dependency externsDependency in externsDependencies)
					{
						if (!_commonExternsDependencies.ContainsUrl(externsDependency.Url))
						{
							assetExternsDependencies.Add(externsDependency);
						}
					}
				}
				else
				{
					assetExternsDependencies.AddRange(externsDependencies);
				}

				IList<string> assetExternsTempFilePaths = new List<string>();

				if (assetExternsDependencies.Count > 0)
				{
					WriteExternsToTempDirectory(assetExternsDependencies, out assetExternsTempDirectoryPath,
						out assetExternsTempFilePaths);
					assetExternsTempDirectoryCreated = true;
				}

				var allExternsTempFilePaths = new List<string>();
				allExternsTempFilePaths.AddRange(_commonExternsTempFilePaths);
				allExternsTempFilePaths.AddRange(assetExternsTempFilePaths);

				foreach (string externsTempFilePath in allExternsTempFilePaths)
				{
					args.AppendFormat(@"--externs ""{0}"" ", externsTempFilePath);
				}
			}
			args.Append(currentOptionsString);

			var processInfo = new ProcessStartInfo
			{
				FileName = _javaVmPath,
				Arguments = args.ToString(),
				CreateNoWindow = true,
				WindowStyle = ProcessWindowStyle.Hidden,
				UseShellExecute = false,
				RedirectStandardInput = true,
				RedirectStandardOutput = true,
				RedirectStandardError = true,
			};

			var stdOutputBuilder = new StdContentBuilder();
			var stdErrorBuilder = new StdContentBuilder();
			Process process = null;

			try
			{
				process = new Process
				{
					StartInfo = processInfo
				};
				process.OutputDataReceived += stdOutputBuilder.OnDataReceived;
				process.ErrorDataReceived += stdErrorBuilder.OnDataReceived;

				process.Start();

				using (StreamWriter inputWriter = process.StandardInput)
				{
					inputWriter.Write(content);
					inputWriter.Flush();
				}

				process.BeginErrorReadLine();
				process.BeginOutputReadLine();

				process.WaitForExit();

				process.OutputDataReceived -= stdOutputBuilder.OnDataReceived;
				process.ErrorDataReceived -= stdErrorBuilder.OnDataReceived;

				string errorString = stdErrorBuilder.Content;
				if (!string.IsNullOrWhiteSpace(errorString))
				{
					IList<string> errors;
					IList<string> warnings;

					ParseErrorDetails(errorString, path, out errors, out warnings);

					if (errors.Count > 0 || warnings.Count > 0)
					{
						if (errors.Count > 0)
						{
							throw new ClosureCompilingException(errors[0]);
						}

						if (currentOptions.Severity > 0 && warnings.Count > 0)
						{
							throw new ClosureCompilingException(warnings[0]);
						}
					}
				}

				newContent = stdOutputBuilder.Content;
			}
			finally
			{
				if (process != null)
				{
					process.Dispose();
				}

				if (assetExternsTempDirectoryCreated && Directory.Exists(assetExternsTempDirectoryPath))
				{
					Directory.Delete(assetExternsTempDirectoryPath, true);
				}
			}

			return newContent;
		}