e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
490 lines
20 KiB
C#
490 lines
20 KiB
C#
//------------------------------------------------------------------------------
|
|
// <OWNER>[....]</OWNER>
|
|
//
|
|
// <copyright file="CodeDomCompilationConfiguration.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
* Code related to the <assemblies> config section
|
|
*
|
|
* Copyright (c) 1999 Microsoft Corporation
|
|
*/
|
|
|
|
namespace System.CodeDom.Compiler {
|
|
|
|
using System;
|
|
using System.CodeDom;
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.Serialization.Formatters;
|
|
using System.Xml;
|
|
using System.Globalization;
|
|
|
|
internal class CodeDomCompilationConfiguration {
|
|
|
|
internal const String sectionName = "system.codedom";
|
|
|
|
static readonly char[] s_fieldSeparators = new char[] {';'};
|
|
|
|
// _compilerLanguages : Hashtable <string, CompilerInfo>
|
|
internal Hashtable _compilerLanguages;
|
|
|
|
// _compilerExtensions : Hashtable <string, CompilerInfo>
|
|
internal Hashtable _compilerExtensions;
|
|
internal ArrayList _allCompilerInfo;
|
|
|
|
private static CodeDomCompilationConfiguration defaultInstance = new CodeDomCompilationConfiguration();
|
|
|
|
internal static CodeDomCompilationConfiguration Default {
|
|
get {
|
|
return defaultInstance;
|
|
}
|
|
}
|
|
|
|
internal CodeDomCompilationConfiguration() {
|
|
// First time initialization. This must be kept consistent with machine.config.comments in that it
|
|
// must initialize the config system as if that block was present.
|
|
|
|
_compilerLanguages = new Hashtable(StringComparer.OrdinalIgnoreCase);
|
|
_compilerExtensions = new Hashtable(StringComparer.OrdinalIgnoreCase);
|
|
_allCompilerInfo = new ArrayList();
|
|
|
|
CompilerInfo compilerInfo;
|
|
CompilerParameters compilerParameters;
|
|
String typeName;
|
|
|
|
// C#
|
|
compilerParameters = new CompilerParameters();
|
|
compilerParameters.WarningLevel = 4;
|
|
typeName = "Microsoft.CSharp.CSharpCodeProvider, " + AssemblyRef.System;
|
|
compilerInfo = new CompilerInfo(compilerParameters, typeName);
|
|
compilerInfo._compilerLanguages = new string[] {"c#", "cs", "csharp"};
|
|
compilerInfo._compilerExtensions = new string[] {".cs", "cs"};
|
|
compilerInfo._providerOptions = new Dictionary<string, string>();
|
|
compilerInfo._providerOptions[RedistVersionInfo.NameTag] = RedistVersionInfo.DefaultVersion;
|
|
AddCompilerInfo(compilerInfo);
|
|
|
|
// VB
|
|
compilerParameters = new CompilerParameters();
|
|
compilerParameters.WarningLevel = 4;
|
|
typeName = "Microsoft.VisualBasic.VBCodeProvider, " + AssemblyRef.System;
|
|
compilerInfo = new CompilerInfo(compilerParameters, typeName);
|
|
compilerInfo._compilerLanguages = new string[] {"vb", "vbs", "visualbasic", "vbscript"};
|
|
compilerInfo._compilerExtensions = new string[] {".vb", "vb"};
|
|
compilerInfo._providerOptions = new Dictionary<string, string>();
|
|
compilerInfo._providerOptions[RedistVersionInfo.NameTag] = RedistVersionInfo.DefaultVersion;
|
|
AddCompilerInfo(compilerInfo);
|
|
|
|
// JScript
|
|
compilerParameters = new CompilerParameters();
|
|
compilerParameters.WarningLevel = 4;
|
|
typeName = "Microsoft.JScript.JScriptCodeProvider, " + AssemblyRef.MicrosoftJScript;
|
|
compilerInfo = new CompilerInfo(compilerParameters, typeName);
|
|
compilerInfo._compilerLanguages = new string[] {"js", "jscript", "javascript"};
|
|
compilerInfo._compilerExtensions = new string[] {".js", "js"};
|
|
compilerInfo._providerOptions = new Dictionary<string, string>();
|
|
AddCompilerInfo(compilerInfo);
|
|
|
|
// C++
|
|
compilerParameters = new CompilerParameters();
|
|
compilerParameters.WarningLevel = 4;
|
|
typeName = "Microsoft.VisualC.CppCodeProvider, " + AssemblyRef.MicrosoftVisualCCppCodeProvider;
|
|
compilerInfo = new CompilerInfo(compilerParameters, typeName);
|
|
compilerInfo._compilerLanguages = new string[] {"c++", "mc", "cpp"};
|
|
compilerInfo._compilerExtensions = new string[] {".h", "h"};
|
|
compilerInfo._providerOptions = new Dictionary<string, string>();
|
|
AddCompilerInfo(compilerInfo);
|
|
|
|
}
|
|
|
|
private CodeDomCompilationConfiguration(CodeDomCompilationConfiguration original) {
|
|
if (original._compilerLanguages != null)
|
|
_compilerLanguages = (Hashtable)original._compilerLanguages.Clone();
|
|
|
|
if (original._compilerExtensions != null)
|
|
_compilerExtensions = (Hashtable)original._compilerExtensions.Clone();
|
|
|
|
if (original._allCompilerInfo != null)
|
|
_allCompilerInfo = (ArrayList)original._allCompilerInfo.Clone();
|
|
}
|
|
|
|
private void AddCompilerInfo(CompilerInfo compilerInfo) {
|
|
|
|
foreach (string language in compilerInfo._compilerLanguages) {
|
|
_compilerLanguages[language] = compilerInfo;
|
|
}
|
|
|
|
foreach (string extension in compilerInfo._compilerExtensions) {
|
|
_compilerExtensions[extension] = compilerInfo;
|
|
}
|
|
|
|
_allCompilerInfo.Add(compilerInfo);
|
|
}
|
|
|
|
private void RemoveUnmapped() {
|
|
// Allow config compilers to replace redundant compiler entries
|
|
|
|
// clear out the mapped marker
|
|
for (int i = 0; i < _allCompilerInfo.Count; i++) {
|
|
((CompilerInfo)_allCompilerInfo[i])._mapped = false;
|
|
}
|
|
|
|
// Re-mark only the ones that still have a mapping
|
|
foreach (CompilerInfo destinationCompilerInfo in _compilerLanguages.Values) {
|
|
destinationCompilerInfo._mapped = true;
|
|
}
|
|
foreach (CompilerInfo destinationCompilerInfo in _compilerExtensions.Values) {
|
|
destinationCompilerInfo._mapped = true;
|
|
}
|
|
|
|
// Remove the ones that were not marked
|
|
for (int i = _allCompilerInfo.Count - 1; i >= 0; i--) {
|
|
if (!((CompilerInfo)_allCompilerInfo[i])._mapped) {
|
|
_allCompilerInfo.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class SectionHandler {
|
|
private SectionHandler () {
|
|
}
|
|
|
|
internal static object CreateStatic(object inheritedObject, XmlNode node) {
|
|
CodeDomCompilationConfiguration inherited = (CodeDomCompilationConfiguration)inheritedObject;
|
|
CodeDomCompilationConfiguration result;
|
|
|
|
if (inherited == null)
|
|
result = new CodeDomCompilationConfiguration();
|
|
else
|
|
result = new CodeDomCompilationConfiguration(inherited);
|
|
|
|
HandlerBase.CheckForUnrecognizedAttributes(node);
|
|
|
|
//
|
|
// Handle child elements (if they exist)
|
|
// - compilers
|
|
//
|
|
foreach (XmlNode child in node.ChildNodes) {
|
|
|
|
// skip whitespace and comments
|
|
// reject nonelements
|
|
if (HandlerBase.IsIgnorableAlsoCheckForNonElement(child))
|
|
continue;
|
|
|
|
// handle <compilers>
|
|
if (child.Name == "compilers") {
|
|
ProcessCompilersElement(result, child);
|
|
}
|
|
else {
|
|
HandlerBase.ThrowUnrecognizedElement(child);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static IDictionary<string, string> GetProviderOptions(XmlNode compilerNode) {
|
|
Dictionary<string, string> res = new Dictionary<string, string>();
|
|
|
|
foreach (XmlNode child in compilerNode) {
|
|
if (child.Name != "providerOption") {
|
|
HandlerBase.ThrowUnrecognizedElement(child);
|
|
}
|
|
|
|
string name = null, value = null;
|
|
HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref name);
|
|
HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "value", ref value);
|
|
HandlerBase.CheckForUnrecognizedAttributes(child);
|
|
HandlerBase.CheckForChildNodes(child);
|
|
|
|
res[name] = value;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
private static void ProcessCompilersElement(CodeDomCompilationConfiguration result, XmlNode node) {
|
|
|
|
// reject attributes
|
|
HandlerBase.CheckForUnrecognizedAttributes(node);
|
|
|
|
String configFile = ConfigurationErrorsException.GetFilename(node);
|
|
|
|
foreach(XmlNode child in node.ChildNodes) {
|
|
int configLineNumber = ConfigurationErrorsException.GetLineNumber(child);
|
|
|
|
// skip whitespace and comments
|
|
// reject nonelements
|
|
if (HandlerBase.IsIgnorableAlsoCheckForNonElement(child))
|
|
continue;
|
|
|
|
if (child.Name != "compiler") {
|
|
HandlerBase.ThrowUnrecognizedElement(child);
|
|
}
|
|
|
|
String languages = String.Empty;
|
|
XmlNode languageNode = HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "language", ref languages);
|
|
String extensions = String.Empty;
|
|
HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "extension", ref extensions);
|
|
String compilerTypeName = null;
|
|
HandlerBase.GetAndRemoveStringAttribute(child, "type", ref compilerTypeName);
|
|
|
|
// Create a CompilerParameters for this compiler.
|
|
CompilerParameters compilerParams = new CompilerParameters();
|
|
|
|
int warningLevel = 0;
|
|
if (HandlerBase.GetAndRemoveNonNegativeIntegerAttribute(child, "warningLevel", ref warningLevel) != null) {
|
|
compilerParams.WarningLevel = warningLevel;
|
|
|
|
// Need to be false if the warning level is 0
|
|
compilerParams.TreatWarningsAsErrors = (warningLevel>0);
|
|
}
|
|
String compilerOptions = null;
|
|
if (HandlerBase.GetAndRemoveStringAttribute(child, "compilerOptions", ref compilerOptions) != null) {
|
|
compilerParams.CompilerOptions = compilerOptions;
|
|
}
|
|
|
|
IDictionary<string, string> provOptions = GetProviderOptions(child);
|
|
|
|
HandlerBase.CheckForUnrecognizedAttributes(child);
|
|
|
|
// Parse the semicolon separated lists
|
|
string[] languageList = languages.Split(s_fieldSeparators);
|
|
string[] extensionList = extensions.Split(s_fieldSeparators);
|
|
|
|
for( int i =0 ; i < languageList.Length; i++) {
|
|
languageList[i] = languageList[i].Trim();
|
|
}
|
|
|
|
for( int i =0 ; i < extensionList.Length; i++) {
|
|
extensionList[i] = extensionList[i].Trim();
|
|
}
|
|
|
|
|
|
// Validate language names, language names must have length and extensions must start with a period.
|
|
foreach (string language in languageList) {
|
|
if (language.Length == 0)
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Language_Names_Cannot_Be_Empty));
|
|
}
|
|
|
|
foreach (string extension in extensionList) {
|
|
if (extension.Length == 0 || extension[0] != '.')
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Extension_Names_Cannot_Be_Empty_Or_Non_Period_Based));
|
|
}
|
|
|
|
|
|
// Create a CompilerInfo structure for this compiler, or get
|
|
// an existing one if no type was provided
|
|
CompilerInfo compilerInfo = null;
|
|
if (compilerTypeName != null) {
|
|
compilerInfo = new CompilerInfo(compilerParams, compilerTypeName);
|
|
} else {
|
|
// reconfiguring an existing entry
|
|
compilerInfo = result.FindExistingCompilerInfo(languageList, extensionList);
|
|
|
|
if (compilerInfo == null)
|
|
throw new ConfigurationErrorsException();
|
|
}
|
|
|
|
compilerInfo.configFileName = configFile;
|
|
compilerInfo.configFileLineNumber = configLineNumber;
|
|
|
|
|
|
if (compilerTypeName != null) {
|
|
compilerInfo._compilerLanguages = languageList;
|
|
compilerInfo._compilerExtensions = extensionList;
|
|
compilerInfo._providerOptions = provOptions;
|
|
|
|
result.AddCompilerInfo(compilerInfo);
|
|
} else {
|
|
// merge in new options, replacing any previous values w/
|
|
// new ones.
|
|
foreach (KeyValuePair<string, string> kvp in provOptions) {
|
|
compilerInfo._providerOptions[kvp.Key] = kvp.Value;
|
|
}
|
|
}
|
|
}
|
|
// Allow config options to replace redundant compiler entries
|
|
result.RemoveUnmapped();
|
|
}
|
|
}
|
|
|
|
private CompilerInfo FindExistingCompilerInfo(string[] languageList, string[] extensionList) {
|
|
CompilerInfo compilerInfo = null;
|
|
|
|
foreach (CompilerInfo ci in _allCompilerInfo) {
|
|
if (ci._compilerExtensions.Length == extensionList.Length &&
|
|
ci._compilerLanguages.Length == languageList.Length) {
|
|
|
|
bool differ = false;
|
|
for (int i = 0; i < ci._compilerExtensions.Length; i++) {
|
|
if (ci._compilerExtensions[i] != extensionList[i]) {
|
|
differ = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < ci._compilerLanguages.Length; i++) {
|
|
if (ci._compilerLanguages[i] != languageList[i]) {
|
|
differ = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!differ) {
|
|
compilerInfo = ci;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return compilerInfo;
|
|
}
|
|
}
|
|
|
|
internal class CodeDomConfigurationHandler : IConfigurationSectionHandler {
|
|
internal CodeDomConfigurationHandler() {
|
|
}
|
|
|
|
public virtual object Create(object inheritedObject, object configContextObj, XmlNode node) {
|
|
return CodeDomCompilationConfiguration.SectionHandler.CreateStatic(inheritedObject, node);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static class HandlerBase {
|
|
|
|
//
|
|
// XML Attribute Helpers
|
|
//
|
|
|
|
private static XmlNode GetAndRemoveAttribute(XmlNode node, string attrib, bool fRequired) {
|
|
XmlNode a = node.Attributes.RemoveNamedItem(attrib);
|
|
|
|
// If the attribute is required and was not present, throw
|
|
if (fRequired && a == null) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_missing_required_attribute, attrib, node.Name), node);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
private static XmlNode GetAndRemoveStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val) {
|
|
XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
|
|
if (a != null)
|
|
val = a.Value;
|
|
|
|
return a;
|
|
}
|
|
|
|
internal static XmlNode GetAndRemoveStringAttribute(XmlNode node, string attrib, ref string val) {
|
|
return GetAndRemoveStringAttributeInternal(node, attrib, false /*fRequired*/, ref val);
|
|
}
|
|
|
|
internal static XmlNode GetAndRemoveRequiredNonEmptyStringAttribute(XmlNode node, string attrib, ref string val) {
|
|
return GetAndRemoveNonEmptyStringAttributeInternal(node, attrib, true /*fRequired*/, ref val);
|
|
}
|
|
|
|
private static XmlNode GetAndRemoveNonEmptyStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val) {
|
|
XmlNode a = GetAndRemoveStringAttributeInternal(node, attrib, fRequired, ref val);
|
|
if (a != null && val.Length == 0) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Empty_attribute, attrib), a);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
private static XmlNode GetAndRemoveIntegerAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val) {
|
|
XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
|
|
if (a != null) {
|
|
if (a.Value.Trim() != a.Value) {
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Config_invalid_integer_attribute, a.Name),a);
|
|
}
|
|
|
|
try {
|
|
val = int.Parse(a.Value, CultureInfo.InvariantCulture);
|
|
}
|
|
catch (Exception e) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_invalid_integer_attribute, a.Name), e, a);
|
|
}
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
private static XmlNode GetAndRemoveNonNegativeAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val) {
|
|
XmlNode a = GetAndRemoveIntegerAttributeInternal(node, attrib, fRequired, ref val);
|
|
|
|
if (a != null && val < 0) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Invalid_nonnegative_integer_attribute, attrib), a);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
internal static XmlNode GetAndRemoveNonNegativeIntegerAttribute(XmlNode node, string attrib, ref int val) {
|
|
return GetAndRemoveNonNegativeAttributeInternal(node, attrib, false /*fRequired*/, ref val);
|
|
}
|
|
|
|
internal static void CheckForUnrecognizedAttributes(XmlNode node) {
|
|
if (node.Attributes.Count != 0) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_base_unrecognized_attribute, node.Attributes[0].Name),
|
|
node.Attributes[0]);
|
|
}
|
|
}
|
|
|
|
//
|
|
// XML Element Helpers
|
|
//
|
|
|
|
internal static void CheckForNonElement(XmlNode node) {
|
|
if (node.NodeType != XmlNodeType.Element) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_base_elements_only),
|
|
node);
|
|
}
|
|
}
|
|
|
|
|
|
internal static bool IsIgnorableAlsoCheckForNonElement(XmlNode node) {
|
|
if (node.NodeType == XmlNodeType.Comment || node.NodeType == XmlNodeType.Whitespace) {
|
|
return true;
|
|
}
|
|
|
|
CheckForNonElement(node);
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static void CheckForChildNodes(XmlNode node) {
|
|
if (node.HasChildNodes) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_base_no_child_nodes),
|
|
node.FirstChild);
|
|
}
|
|
}
|
|
|
|
internal static void ThrowUnrecognizedElement(XmlNode node) {
|
|
throw new ConfigurationErrorsException(
|
|
SR.GetString(SR.Config_base_unrecognized_element),
|
|
node);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|