public JsExpression MemberReference(JsExpression @this, ISymbol symbol, bool isSetter = false, bool isBaseReference = false) { switch (symbol.Kind) { case SymbolKind.Field: { var field = (IFieldSymbol)symbol; var result = (JsExpression)@this.Member(field.GetMemberName()); if (field.Type is IArrayTypeSymbol && !field.IsExported()) { result = MakeArray(result, (IArrayTypeSymbol)field.Type); } return result; } case SymbolKind.Event: { var field = (IEventSymbol)symbol; return @this.Member(field.GetBackingFieldName()); } case SymbolKind.Property: { var property = (IPropertySymbol)symbol; if (property.ContainingType.IsGenericType && Equals(property.ContainingType.ConstructedFrom, Context.Instance.NullableType)) { property = property.OriginalDefinition; if (Equals(property, Context.Instance.NullableHasValue)) { return @this.NotEqualTo(Js.Null()).Parenthetical(); } else if (Equals(property, Context.Instance.NullableValue)) { return Js.Reference(SpecialNames.NullableGetValue).Invoke(@this); } } return GetPropertyValue(@this, property, isSetter, isBaseReference); } case SymbolKind.Parameter: return transformer.ReferenceDeclarationInScope(symbol).GetReference(); case SymbolKind.NamedType: var namedTypeSymbol = (INamedTypeSymbol)symbol; var type = Type(namedTypeSymbol); if (!(type is JsInvocationExpression) && namedTypeSymbol.IsExported()) type = type.Invoke(); return type; case SymbolKind.Local: var declaration = transformer.ReferenceDeclarationInScope(symbol); return !isSetter ? declaration.GetReference() : declaration.SetReference(); case SymbolKind.Method: { var method = (IMethodSymbol)symbol; var containingSymbol = symbol.ContainingType; var name = method.GetMemberName(); var target = method.IsStatic ? Type(containingSymbol) : @this; if (Equals(method.ContainingType, containingSymbol)) { return target.Member(name); } else if (containingSymbol.IsSubclassOf(method.ContainingType)) { return target.Member(name); } else { throw new Exception(); } } case SymbolKind.Namespace: return Js.Reference(symbol.Name); case SymbolKind.Label: return Js.Reference(symbol.Name); case SymbolKind.TypeParameter: return Js.Reference(symbol.Name); default: throw new InvalidOperationException("Unexpected node: " + symbol); } }