Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to specify the default member case preservation in an assembly #429

Open
wants to merge 1 commit into
base: cc
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 86 additions & 47 deletions src/Core/Compiler/Compiler/MetadataBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,47 +265,16 @@ private void BuildMemberDetails(MemberSymbol memberSymbol, TypeSymbol typeSymbol
memberSymbol.SetVisibility(GetVisibility(memberNode, typeSymbol));
}

AttributeNode nameAttribute = AttributeNode.FindAttribute(attributes, "ScriptName");
if ((nameAttribute != null) && (nameAttribute.Arguments != null) &&
(nameAttribute.Arguments.Count != 0)) {
string name = null;
bool preserveCase = false;
bool preserveName = false;

foreach (ParseNode argNode in nameAttribute.Arguments) {
Debug.Assert((argNode.NodeType == ParseNodeType.Literal) ||
(argNode.NodeType == ParseNodeType.BinaryExpression));

if (argNode.NodeType == ParseNodeType.Literal) {
Debug.Assert(((LiteralNode)argNode).Value is string);
name = (string)((LiteralNode)argNode).Value;
preserveName = preserveCase = true;
break;
}
else {
BinaryExpressionNode propSetNode = (BinaryExpressionNode)argNode;

if (String.CompareOrdinal(((NameNode)propSetNode.LeftChild).Name, "PreserveName") == 0) {
preserveName = (bool)((LiteralNode)propSetNode.RightChild).Value;
}
else {
preserveCase = (bool)((LiteralNode)propSetNode.RightChild).Value;
if (preserveCase) {
preserveName = true;
break;
}
}
}
}

if (String.IsNullOrEmpty(name) == false) {
memberSymbol.SetTransformedName(name);
}
else {
memberSymbol.SetNameCasing(preserveCase);
if (preserveName) {
memberSymbol.DisableNameTransformation();
}
bool preserveCase;
bool preserveName;
string name = GetScriptName(attributes, typeSymbol.MemberCasePreservation, out preserveName, out preserveCase);

if (String.IsNullOrEmpty(name) == false) {
memberSymbol.SetTransformedName(name);
} else {
memberSymbol.SetNameCasing(preserveCase);
if (preserveName) {
memberSymbol.DisableNameTransformation();
}
}
}
Expand Down Expand Up @@ -412,6 +381,8 @@ public ICollection<TypeSymbol> BuildMetadata(ParseNodeList compilationUnits, Sym
_options = options;
BuildAssembly(compilationUnits);

bool defaultMemberCasePreservation = GetDefaultMemberCasePreservation(compilationUnits);

List<TypeSymbol> types = new List<TypeSymbol>();

// Build all the types first.
Expand Down Expand Up @@ -495,11 +466,11 @@ public ICollection<TypeSymbol> BuildMetadata(ParseNodeList compilationUnits, Sym

// Merge interesting bits of information onto the primary type symbol as well
// representing this partial class
BuildType(partialTypeSymbol, userTypeNode);
BuildType(partialTypeSymbol, userTypeNode, defaultMemberCasePreservation);
}
}

TypeSymbol typeSymbol = BuildType(userTypeNode, namespaceSymbol);
TypeSymbol typeSymbol = BuildType(userTypeNode, namespaceSymbol, defaultMemberCasePreservation);
if (typeSymbol != null) {
typeSymbol.SetParseContext(userTypeNode);
typeSymbol.SetParentSymbolTable(symbols);
Expand Down Expand Up @@ -754,7 +725,7 @@ private void BuildResources(ResourcesSymbol resourcesSymbol) {
}
}

private TypeSymbol BuildType(UserTypeNode typeNode, NamespaceSymbol namespaceSymbol) {
private TypeSymbol BuildType(UserTypeNode typeNode, NamespaceSymbol namespaceSymbol, bool defaultMemberCasePreservation) {
Debug.Assert(typeNode != null);
Debug.Assert(namespaceSymbol != null);

Expand Down Expand Up @@ -810,7 +781,7 @@ private TypeSymbol BuildType(UserTypeNode typeNode, NamespaceSymbol namespaceSym
typeSymbol.SetPublic();
}

BuildType(typeSymbol, typeNode);
BuildType(typeSymbol, typeNode, defaultMemberCasePreservation);

if (namespaceSymbol.Name.EndsWith(".Tests", StringComparison.Ordinal) ||
(namespaceSymbol.Name.IndexOf(".Tests.", StringComparison.Ordinal) > 0)) {
Expand All @@ -821,7 +792,7 @@ private TypeSymbol BuildType(UserTypeNode typeNode, NamespaceSymbol namespaceSym
return typeSymbol;
}

private void BuildType(TypeSymbol typeSymbol, UserTypeNode typeNode) {
private void BuildType(TypeSymbol typeSymbol, UserTypeNode typeNode, bool defaultMemberCasePreservation) {
Debug.Assert(typeSymbol != null);
Debug.Assert(typeNode != null);

Expand Down Expand Up @@ -869,11 +840,16 @@ private void BuildType(TypeSymbol typeSymbol, UserTypeNode typeNode) {
typeSymbol.DisableNameTransformation();
}

string scriptName = GetAttributeValue(attributes, "ScriptName");
bool preserveCase;
bool dummy;
string scriptName = GetScriptName(attributes, defaultMemberCasePreservation, out dummy, out preserveCase);

if (scriptName != null) {
typeSymbol.SetTransformedName(scriptName);
}

typeSymbol.MemberCasePreservation = preserveCase;

if (typeNode.Type == TokenType.Class) {
AttributeNode extensionAttribute = AttributeNode.FindAttribute(attributes, "ScriptExtension");
if (extensionAttribute != null) {
Expand Down Expand Up @@ -992,6 +968,45 @@ private string GetAssemblyScriptName(ParseNodeList compilationUnits) {
return null;
}

private string GetScriptName(ParseNodeList attributes, bool defaultMemberCasePreservation, out bool preserveName, out bool preserveCase) {

string name = null;
preserveCase = defaultMemberCasePreservation;
preserveName = false;

AttributeNode nameAttribute = AttributeNode.FindAttribute(attributes, "ScriptName");

if ((nameAttribute != null) && (nameAttribute.Arguments != null) &&
(nameAttribute.Arguments.Count != 0)) {

foreach (ParseNode argNode in nameAttribute.Arguments) {
Debug.Assert((argNode.NodeType == ParseNodeType.Literal) ||
(argNode.NodeType == ParseNodeType.BinaryExpression));

if (argNode.NodeType == ParseNodeType.Literal) {
Debug.Assert(((LiteralNode)argNode).Value is string);
name = (string)((LiteralNode)argNode).Value;
preserveName = preserveCase = true;
break;
} else {
BinaryExpressionNode propSetNode = (BinaryExpressionNode)argNode;

if (String.CompareOrdinal(((NameNode)propSetNode.LeftChild).Name, "PreserveName") == 0) {
preserveName = (bool)((LiteralNode)propSetNode.RightChild).Value;
} else {
preserveCase = (bool)((LiteralNode)propSetNode.RightChild).Value;
if (preserveCase) {
preserveName = true;
break;
}
}
}
}
}

return name;
}

private List<AttributeNode> GetAttributes(ParseNodeList compilationUnits, string attributeName) {
List<AttributeNode> attributes = new List<AttributeNode>();

Expand Down Expand Up @@ -1020,6 +1035,18 @@ private string GetAttributeValue(ParseNodeList attributes, string attributeName)
return null;
}

private bool? GetBoolAttributeValue(ParseNodeList attributes, string attributeName) {
AttributeNode node = AttributeNode.FindAttribute(attributes, attributeName);

if ((node != null) &&
(node.Arguments.Count != 0) && (node.Arguments[0].NodeType == ParseNodeType.Literal)) {
Debug.Assert(((LiteralNode)node.Arguments[0]).Value is bool);

return (bool)((LiteralNode)node.Arguments[0]).Value;
}
return null;
}

private bool GetScriptTemplate(ParseNodeList compilationUnits, out string template) {
template = null;

Expand All @@ -1035,6 +1062,18 @@ private bool GetScriptTemplate(ParseNodeList compilationUnits, out string templa
return false;
}

private bool GetDefaultMemberCasePreservation(ParseNodeList compilationUnits) {
foreach (CompilationUnitNode compilationUnit in compilationUnits) {
foreach (AttributeBlockNode attribBlock in compilationUnit.Attributes) {
bool? preserveMemberCase = GetBoolAttributeValue(attribBlock.Attributes, "ScriptDefaultMemberCasePreservation");
if (preserveMemberCase != null) {
return (bool)preserveMemberCase;
}
}
}
return false;
}

private MemberVisibility GetVisibility(MemberNode node, TypeSymbol typeSymbol) {
if (typeSymbol.Type == SymbolType.Interface) {
return MemberVisibility.Public;
Expand Down
16 changes: 14 additions & 2 deletions src/Core/Compiler/Importer/MetadataHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ private static string GetAttributeArgument(CustomAttribute attribute) {
return attribute.ConstructorArguments[0].Value as string;
}

private static bool GetBoolAttributeArgument(CustomAttribute attribute) {
return (bool)attribute.ConstructorArguments[0].Value;
}

public static string GetScriptAlias(ICustomAttributeProvider attributeProvider) {
CustomAttribute scriptAliasAttribute = GetAttribute(attributeProvider, "System.Runtime.CompilerServices.ScriptAliasAttribute");
if (scriptAliasAttribute != null) {
Expand All @@ -54,6 +58,14 @@ public static string GetScriptAssemblyName(ICustomAttributeProvider attributePro
return null;
}

public static bool GetScriptDefaultMemberCasePreservation(ICustomAttributeProvider attributeProvider) {
CustomAttribute memberCasePreservationAttribute = GetAttribute(attributeProvider, "System.ScriptDefaultMemberCasePreservation");
if (memberCasePreservationAttribute != null) {
return GetBoolAttributeArgument(memberCasePreservationAttribute);
}
return false;
}

public static string GetScriptDependencyName(ICustomAttributeProvider attributeProvider, out string dependencyIdentifier) {
dependencyIdentifier = null;

Expand Down Expand Up @@ -94,9 +106,9 @@ public static string GetScriptMethodSelector(MethodDefinition method) {
return null;
}

public static string GetScriptName(ICustomAttributeProvider attributeProvider, out bool preserveName, out bool preserveCase) {
public static string GetScriptName(ICustomAttributeProvider attributeProvider, bool defaultPreserveCaseValue, out bool preserveName, out bool preserveCase) {
string name = null;
preserveName = false;
preserveName = defaultPreserveCaseValue;
preserveCase = false;

CustomAttribute nameAttribute = GetAttribute(attributeProvider, "System.ScriptNameAttribute");
Expand Down
29 changes: 17 additions & 12 deletions src/Core/Compiler/Importer/MetadataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private void ImportEnumFields(TypeSymbol enumTypeSymbol) {

EnumerationFieldSymbol fieldSymbol =
new EnumerationFieldSymbol(fieldName, enumTypeSymbol, field.Constant, fieldType);
ImportMemberDetails(fieldSymbol, null, field);
ImportMemberDetails(fieldSymbol, enumTypeSymbol, null, field);

enumTypeSymbol.AddMember(fieldSymbol);
}
Expand Down Expand Up @@ -207,7 +207,7 @@ private void ImportEvents(TypeSymbol typeSymbol) {
}

EventSymbol eventSymbol = new EventSymbol(eventName, typeSymbol, eventHandlerType);
ImportMemberDetails(eventSymbol, eventDef.AddMethod, eventDef);
ImportMemberDetails(eventSymbol, typeSymbol, eventDef.AddMethod, eventDef);

string addAccessor;
string removeAccessor;
Expand Down Expand Up @@ -251,13 +251,13 @@ private void ImportFields(TypeSymbol typeSymbol) {
FieldSymbol fieldSymbol = new FieldSymbol(fieldName, typeSymbol, fieldType);

fieldSymbol.SetVisibility(visibility);
ImportMemberDetails(fieldSymbol, null, field);
ImportMemberDetails(fieldSymbol, typeSymbol, null, field);

typeSymbol.AddMember(fieldSymbol);
}
}

private void ImportMemberDetails(MemberSymbol memberSymbol, MethodDefinition methodDefinition, ICustomAttributeProvider attributeProvider) {
private void ImportMemberDetails(MemberSymbol memberSymbol, TypeSymbol typeSymbol, MethodDefinition methodDefinition, ICustomAttributeProvider attributeProvider) {
if (methodDefinition != null) {
MemberVisibility visibility = MemberVisibility.PrivateInstance;
if (methodDefinition.IsStatic) {
Expand All @@ -275,7 +275,7 @@ private void ImportMemberDetails(MemberSymbol memberSymbol, MethodDefinition met

bool preserveName;
bool preserveCase;
string scriptName = MetadataHelpers.GetScriptName(attributeProvider, out preserveName, out preserveCase);
string scriptName = MetadataHelpers.GetScriptName(attributeProvider, typeSymbol.MemberCasePreservation, out preserveName, out preserveCase);

memberSymbol.SetNameCasing(preserveCase);
if (scriptName != null) {
Expand Down Expand Up @@ -360,7 +360,7 @@ private void ImportMethods(TypeSymbol typeSymbol) {
}

MethodSymbol methodSymbol = new MethodSymbol(methodName, typeSymbol, returnType);
ImportMemberDetails(methodSymbol, method, method);
ImportMemberDetails(methodSymbol, typeSymbol, method, method);

if (method.HasGenericParameters) {
List<GenericParameterSymbol> genericArguments = new List<GenericParameterSymbol>();
Expand Down Expand Up @@ -434,7 +434,7 @@ private void ImportProperties(TypeSymbol typeSymbol) {
PropertySymbol propertySymbol = null;
if (property.Parameters.Count != 0) {
IndexerSymbol indexerSymbol = new IndexerSymbol(typeSymbol, propertyType);
ImportMemberDetails(indexerSymbol, property.GetMethod, property);
ImportMemberDetails(indexerSymbol, typeSymbol, property.GetMethod, property);

if (scriptField) {
indexerSymbol.SetScriptIndexer();
Expand All @@ -451,7 +451,7 @@ private void ImportProperties(TypeSymbol typeSymbol) {
// instead of a property

FieldSymbol fieldSymbol = new FieldSymbol(propertyName, typeSymbol, propertyType);
ImportMemberDetails(fieldSymbol, property.GetMethod, property);
ImportMemberDetails(fieldSymbol, typeSymbol, property.GetMethod, property);

string alias = MetadataHelpers.GetScriptAlias(property);
if (String.IsNullOrEmpty(alias) == false) {
Expand All @@ -462,7 +462,7 @@ private void ImportProperties(TypeSymbol typeSymbol) {
}
else {
propertySymbol = new PropertySymbol(propertyName, typeSymbol, propertyType);
ImportMemberDetails(propertySymbol, property.GetMethod, property);
ImportMemberDetails(propertySymbol, typeSymbol, property.GetMethod, property);
}
}

Expand Down Expand Up @@ -577,21 +577,23 @@ private void ImportScriptAssembly(MetadataSource mdSource, string assemblyPath,
scriptNamespace = dependency.Identifier;
}

bool defaultMemberCasePreservation = MetadataHelpers.GetScriptDefaultMemberCasePreservation(assembly);

foreach (TypeDefinition type in assembly.MainModule.Types) {
try {
if (MetadataHelpers.IsCompilerGeneratedType(type)) {
continue;
}

ImportType(mdSource, type, coreAssembly, scriptNamespace);
ImportType(mdSource, type, coreAssembly, scriptNamespace, defaultMemberCasePreservation);
}
catch (Exception e) {
Debug.Fail(e.ToString());
}
}
}

private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScriptCoreAssembly, string scriptNamespace) {
private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScriptCoreAssembly, string scriptNamespace, bool defaultMemberCasePreservation) {
if (type.IsPublic == false) {
return;
}
Expand All @@ -603,7 +605,8 @@ private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScr
string namespaceName = type.Namespace;

bool dummy;
string scriptName = MetadataHelpers.GetScriptName(type, out dummy, out dummy);
bool memberCasePreservation;
string scriptName = MetadataHelpers.GetScriptName(type, defaultMemberCasePreservation, out dummy, out memberCasePreservation);

NamespaceSymbol namespaceSymbol = _symbols.GetNamespace(namespaceName);
TypeSymbol typeSymbol = null;
Expand Down Expand Up @@ -683,6 +686,8 @@ private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScr
typeSymbol.SetTransformedName(scriptName);
}

typeSymbol.MemberCasePreservation = memberCasePreservation;

namespaceSymbol.AddType(typeSymbol);
_importedTypes.Add(typeSymbol);
}
Expand Down
Loading