public void ValidateReturnsNoErrosWhenCalledWithAValidString()
        {
            Compile("class C<T1> { public void F<T2>(string s, int a, params string[] p) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{$System.Object}({T1}, {T2}, {@s}, {this}, {a}, {*p})", n => JsExpression.Null, t => JsExpression.Null), Is.Empty);
        }
        private JsExpression CreateDefaultConstructorInvocation(IMethod defaultConstructor, JsExpression typeRef)
        {
            var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor);

            switch (sem.Type)
            {
            case ConstructorScriptSemantics.ImplType.UnnamedConstructor:                      // default behavior is good enough.
            case ConstructorScriptSemantics.ImplType.NotUsableFromScript:                     // Can't be invoked so we don't need to create it.
                return(null);

            case ConstructorScriptSemantics.ImplType.NamedConstructor:
                return(JsExpression.New(JsExpression.Member(typeRef, sem.Name)));

            case ConstructorScriptSemantics.ImplType.StaticMethod:
                return(JsExpression.Invocation(JsExpression.Member(typeRef, sem.Name)));

            case ConstructorScriptSemantics.ImplType.InlineCode:
                var prevRegion = _errorReporter.Region;
                try {
                    _errorReporter.Region = defaultConstructor.Region;
                    return(InlineCodeMethodCompiler.CompileInlineCodeMethodInvocation(defaultConstructor, sem.LiteralCode, null, EmptyList <JsExpression> .Instance, r => r.Resolve(_compilation), _runtimeLibrary.GetScriptType, false, s => _errorReporter.Message(7525, s)));
                }
                finally {
                    _errorReporter.Region = prevRegion;
                }

            case ConstructorScriptSemantics.ImplType.Json:
                return(JsExpression.ObjectLiteral());

            default:
                throw new Exception("Invalid constructor implementation type: " + sem.Type);
            }
        }
        public void InvalidTypeNameIsReportedAsAnError()
        {
            string msg = null;

            InlineCodeMethodCompiler.Tokenize("{$Some[]-bad|type}", new string[0], new string[0], s => msg = s);
            Assert.That(msg, Is.StringContaining("Some[]-bad|type"));
        }
        private JsExpression CompileImportedTypeCheckCode(IType type, ref JsExpression @this, IRuntimeContext context, bool isTypeIs)
        {
            var def = type.GetDefinition();

            if (def == null)
            {
                return(null);
            }
            var ia = AttributeReader.ReadAttribute <ImportedAttribute>(def);

            if (ia == null || string.IsNullOrEmpty(ia.TypeCheckCode))
            {
                return(null);
            }

            // Can ignore errors here because they are caught by the metadata importer
            var method    = MetadataUtils.CreateTypeCheckMethod(type, _compilation);
            var tokens    = InlineCodeMethodCompiler.Tokenize(method, ia.TypeCheckCode, _ => {});
            int thisCount = tokens.Count(t => t.Type == InlineCodeToken.TokenType.This);

            if (!isTypeIs || thisCount > 0)
            {
                @this = context.EnsureCanBeEvaluatedMultipleTimes(@this, new JsExpression[0]);
            }
            return(JsExpression.LogicalAnd(
                       ReferenceNotEquals(@this, JsExpression.Null, context),
                       InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, @this, EmptyList <JsExpression> .Instance, n => { var t = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); return t.Kind == TypeKind.Unknown ? JsExpression.Null : InstantiateType(t, context); }, t => InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), _ => {})));
        }
        public void TokenizerCanDetectTypeParameterNamePreceededByAtSign()
        {
            Compile("class C<@T1> { public static void F<@T2>(params string[] p1) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{T1}{T2}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.TypeParameter, index: 0, ownerType: SymbolKind.TypeDefinition), new InlineCodeToken(InlineCodeToken.TokenType.TypeParameter, index: 0, ownerType: SymbolKind.Method) }));
        }
Exemple #6
0
        public void TokenizerCanDetectMethodTypeParameters()
        {
            Compile("class C { public static void F<T1, T2>(params string[] p1) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{T1}{T2}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.TypeParameter, index: 0, ownerType: EntityType.Method), new InlineCodeToken(InlineCodeToken.TokenType.TypeParameter, index: 1, ownerType: EntityType.Method) }));
        }
        public void TokenizerCanDetectThis()
        {
            Compile("class C { public static void F() {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{this}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.This) }));
        }
        public void TokenizerCanDetectParameterNamePreceededByAtSign()
        {
            Compile("class C { public static void F(int @p1) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{p1}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.Parameter, index: 0) }));
        }
        public void TokenizerCanDetectLiteralStringParameterToUseAsIdentifier()
        {
            Compile("class C { public static void F(string p1, string p2) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{@p1}{@p2}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.LiteralStringParameterToUseAsIdentifier, index: 0), new InlineCodeToken(InlineCodeToken.TokenType.LiteralStringParameterToUseAsIdentifier, index: 1) }));
        }
        public void TokenizerCanDetectExpandedParamArrayParameter()
        {
            Compile("class C { public static void F(params string[] p1) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "{*p1}", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.Parameter, index: 0, isExpandedParamArray: true) }));
        }
        public void ValidateReturnsAnErrorWhenTheStarModifierIsUsedWithAnArgumentThatIsNotAParamArray()
        {
            Compile("class C { public static void F(string[] myArg) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{*myArg}", n => JsExpression.Null, t => JsExpression.Null);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("*") && e.Contains("myArg") && e.Contains("param array")));
        }
        public void ValidateReturnsAnErrorWhenAnExpandedParamArrayIsUsedInAnInvalidContext()
        {
            Compile("class C { public static void F(string p1, int p2, params string[] p3) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{p1}*{p2} + {*p3}", n => JsExpression.Null, t => JsExpression.Null);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("can only be used")));
        }
        public void ValidateReturnsAnErrorWhenTheAtModifierIsUsedWithAnArgumentThatIsNotAString()
        {
            Compile("class C { public static void F(int myArg) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateLiteralCode(method, "{@myArg}", t => new DummyType());

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("'@'") && e.Contains("myArg")));
        }
        public void ValidateReturnsAnErrorWhenAReferencedTypeCannotBeFound()
        {
            Compile("class C { public static void F() {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateLiteralCode(method, "{$NonExisting.Type}()", t => SpecialType.UnknownType);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("NonExisting.Type")));
        }
        public void ValidateReturnsAnErrorWhenThereIsASyntaxError()
        {
            Compile("class C { public static void F(string x, int y) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{x} + ", n => JsExpression.Null, t => JsExpression.Null);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("syntax error")));
        }
        public void InvalidTypeNameIsReportedAsAnError()
        {
            Compile("class C { public static void F() {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            string msg = null;

            InlineCodeMethodCompiler.Tokenize(method, "{$Some[]-bad|type}", s => msg = s);
            Assert.That(msg, Is.StringContaining("Some[]-bad|type"));
        }
        public void ValidateReturnsAnErrorWhenThereIsAFormatStringError()
        {
            Compile("class C { public void F() {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{abc", n => JsExpression.Null, t => JsExpression.Null);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("expected '}'")));
        }
        public void ValidateReturnsAnErrorWhenThisIsUsedForAStaticMethod()
        {
            Compile("class C { public static void F() {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            var result = InlineCodeMethodCompiler.ValidateExpressionLiteralCode(method, "{this}", n => JsExpression.Null, t => JsExpression.Null);

            Assert.That(result.Count, Is.EqualTo(1));
            Assert.That(result.Any(e => e.Contains("{this}") && e.Contains("static")));
        }
        public void TheTokenizerWorks()
        {
            Assert.That(InlineCodeMethodCompiler.Tokenize("X{ab}{{y}z}}Y{{{c}}}T", new[] { "ab", "c" }, new string[0], s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] {
                new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Text, "X"),
                new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Parameter, index: 0),
                new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Text, "{y}z}Y{"),
                new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Parameter, index: 1),
                new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Text, "}T"),
            }));

            string msg = null;

            InlineCodeMethodCompiler.Tokenize("Something {abcd", new string[0], new string[0], s => msg = s);
            Assert.That(msg, Is.StringContaining("'}'"));

            Assert.That(InlineCodeMethodCompiler.Tokenize("X{}Y", new string[0], new string[0], s => Assert.Fail("Unexpected error " + s)), Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Text, "X{}Y") }));
        }
Exemple #20
0
        public JsExpression InitializeField(JsExpression jsThis, string scriptName, IMember member, JsExpression initialValue, IRuntimeContext context)
        {
            var cia = _attributeStore.AttributesFor(member).GetAttribute <CustomInitializationAttribute>();

            if (cia != null)
            {
                if (string.IsNullOrEmpty(cia.Code))
                {
                    return(null);
                }
                var method = MetadataUtils.CreateDummyMethodForFieldInitialization(member, _compilation);
                // Can ignore errors because they are caught by the metadata importer
                var tokens = InlineCodeMethodCompiler.Tokenize(method, cia.Code, _ => {});
                initialValue = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, jsThis, new[] { initialValue }, n => { var t = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); return(t.Kind == TypeKind.Unknown ? JsExpression.Null : InstantiateType(t, context)); }, t => InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), _ => {});
            }

            return(JsExpression.Assign(JsExpression.Member(jsThis, scriptName), initialValue));
        }
        public void TheTokenizerWorks()
        {
            Compile("class C { public static void F(int ab, int c) {} }");
            var method = FindClass("C").CSharpTypeDefinition.Methods.Single(m => m.Name == "F");

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "X{ab}{{y}z}}Y{{{c}}}T", s => Assert.Fail("Unexpected error " + s)),
                        Is.EqualTo(new[] {
                new InlineCodeToken(InlineCodeToken.TokenType.Text, "X"),
                new InlineCodeToken(InlineCodeToken.TokenType.Parameter, index: 0),
                new InlineCodeToken(InlineCodeToken.TokenType.Text, "{y}z}Y{"),
                new InlineCodeToken(InlineCodeToken.TokenType.Parameter, index: 1),
                new InlineCodeToken(InlineCodeToken.TokenType.Text, "}T"),
            }));

            string msg = null;

            InlineCodeMethodCompiler.Tokenize(method, "Something {abcd", s => msg = s);
            Assert.That(msg, Is.StringContaining("'}'"));

            Assert.That(InlineCodeMethodCompiler.Tokenize(method, "X{}Y", s => Assert.Fail("Unexpected error " + s)), Is.EqualTo(new[] { new InlineCodeToken(InlineCodeToken.TokenType.Text, "X{}Y") }));
        }
 public void TokenizerCanDetectTypeReferences()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{$System.Type}", new string[0], new string[0], s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.TypeRef, "System.Type") }));
 }
        private static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType, MethodScriptSemantics semanticsIfAccessor)
        {
            if (m is IMethod && ((IMethod)m).IsConstructor)
            {
                return(ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType));
            }

            var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType);

            if (m.IsStatic)
            {
                properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True));
            }

            if (m is IMethod)
            {
                var method = (IMethod)m;
                var sem    = semanticsIfAccessor ?? metadataImporter.GetMethodSemantics(method);
                if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "method");
                    return(JsExpression.Null);
                }
                if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams)
                {
                    properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True));
                }

                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)));
                if (sem.Type == MethodScriptSemantics.ImplType.InlineCode)
                {
                    var usedNames  = new HashSet <string>();
                    var parameters = new List <IVariable>();
                    var variables  = new Dictionary <IVariable, VariableData>();
                    var arguments  = new List <ResolveResult>();
                    foreach (var p in method.Parameters)
                    {
                        string name = namer.GetVariableName(p.Name, usedNames);
                        usedNames.Add(name);
                        var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty);
                        parameters.Add(variable);
                        variables.Add(variable, new VariableData(name, null, false));
                        arguments.Add(new LocalResolveResult(variable));
                    }
                    var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {});

                    var compileResult = Compile(CreateMethodInvocationResolveResult(method, method.IsStatic ? (ResolveResult) new TypeResolveResult(method.DeclaringType) : new ThisResolveResult(method.DeclaringType), arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames);
                    var definition    = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) })));

                    if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == SymbolKind.Method))
                    {
                        definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), JsStatement.Return(definition));
                        properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count)));
                    }
                    properties.Add(new JsObjectLiteralProperty("def", definition));
                }
                else
                {
                    if (IsJsGeneric(method, metadataImporter))
                    {
                        properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count)));
                    }
                    if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument)
                    {
                        properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True));
                    }
                    properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name)));
                }
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType)));
                properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type)))));
            }
            else if (m is IField)
            {
                var field = (IField)m;
                var sem   = metadataImporter.GetFieldSemantics(field);
                if (sem.Type != FieldScriptSemantics.ImplType.Field)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "field");
                    return(JsExpression.Null);
                }
                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field)));
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType)));
                properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name)));
            }
            else if (m is IProperty)
            {
                var prop = (IProperty)m;
                var sem  = metadataImporter.GetPropertySemantics(prop);
                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property)));
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType)));
                if (prop.Parameters.Count > 0)
                {
                    properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type)))));
                }

                switch (sem.Type)
                {
                case PropertyScriptSemantics.ImplType.GetAndSetMethods:
                    if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                    {
                        errorReporter.Message(Messages._7202, m.FullName, "property", "getter");
                        return(JsExpression.Null);
                    }
                    if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                    {
                        errorReporter.Message(Messages._7202, m.FullName, "property", "setter");
                        return(JsExpression.Null);
                    }
                    if (sem.GetMethod != null)
                    {
                        properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.GetMethod)));
                    }
                    if (sem.SetMethod != null)
                    {
                        properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.SetMethod)));
                    }
                    break;

                case PropertyScriptSemantics.ImplType.Field:
                    if (prop.CanGet)
                    {
                        properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType)));
                    }
                    if (prop.CanSet)
                    {
                        properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType)));
                    }
                    properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName)));
                    break;

                default:
                    errorReporter.Message(Messages._7201, m.FullName, "property");
                    return(JsExpression.Null);
                }
            }
            else if (m is IEvent)
            {
                var evt = (IEvent)m;
                var sem = metadataImporter.GetEventSemantics(evt);
                if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "event");
                    return(JsExpression.Null);
                }
                if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor");
                    return(JsExpression.Null);
                }
                if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor");
                    return(JsExpression.Null);
                }

                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event)));
                properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.AddMethod)));
                properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.RemoveMethod)));
            }
            else
            {
                throw new ArgumentException("Invalid member " + m);
            }

            return(JsExpression.ObjectLiteral(properties));
        }
 public void TokenizerCanDetectThis()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{this}", new string[0], new string[0], s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.This) }));
 }
Exemple #25
0
        private void AddClassMembers(JsClass c, JsExpression typeRef, List <JsStatement> stmts)
        {
            if (c.InstanceMethods.Count > 0)
            {
                stmts.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(c.InstanceMethods.Select(m => new JsObjectLiteralProperty(m.Name, m.Definition != null ? RewriteMethod(m) : JsExpression.Null))))));
            }

            if (c.NamedConstructors.Count > 0)
            {
                stmts.AddRange(c.NamedConstructors.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, m.Name), m.Definition))));
                stmts.Add(new JsExpressionStatement(c.NamedConstructors.Reverse().Aggregate((JsExpression)JsExpression.Member(typeRef, Prototype), (right, ctor) => JsExpression.Assign(JsExpression.Member(JsExpression.Member(typeRef, ctor.Name), Prototype), right))));                     // This generates a statement like {C}.ctor1.prototype = {C}.ctor2.prototype = {C}.prototoype
            }

            var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic);

            if (defaultConstructor != null)
            {
                var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor);
                if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript)
                {
                    var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null);
                    stmts.Add(new JsExpressionStatement(
                                  JsExpression.Assign(
                                      JsExpression.Member(typeRef, "createInstance"),
                                      JsExpression.FunctionDefinition(new string[0], new JsBlockStatement(createInstance.AdditionalStatements.Concat(new[] { new JsReturnStatement(createInstance.Expression) }))))));
                }
            }

            stmts.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, m.Name), RewriteMethod(m)))));

            if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition))
            {
                string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition);
                if (!string.IsNullOrEmpty(typeCheckCode))
                {
                    var oldReg = _errorReporter.Region;
                    _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region;
                    var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation);

                    var errors = new List <string>();
                    var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add);
                    if (errors.Count == 0)
                    {
                        var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer);
                        var result  = InlineCodeMethodCompiler.CompileInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0],
                                                                                                 n => {
                            var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation);
                            if (type.Kind == TypeKind.Unknown)
                            {
                                errors.Add("Unknown type '" + n + "' specified in inline implementation");
                                return(JsExpression.Null);
                            }
                            return(_runtimeLibrary.InstantiateType(type, context));
                        },
                                                                                                 t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context),
                                                                                                 errors.Add);

                        stmts.Add(new JsExpressionStatement(
                                      JsExpression.Assign(
                                          JsExpression.Member(typeRef, "isInstanceOfType"),
                                          JsExpression.FunctionDefinition(new[] { "obj" }, new JsReturnStatement(result)))));

                        foreach (var e in errors)
                        {
                            _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e);
                        }
                    }
                    _errorReporter.Region = oldReg;
                }
            }

            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
            {
                var args = new List <JsExpression> {
                    typeRef, new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp))))
                };
                if (c.CSharpTypeDefinition.Kind == TypeKind.Class)
                {
                    args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null)));
                }
                args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition)))));
                var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true);
                if (metadata != null)
                {
                    args.Add(metadata);
                }
                stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Class ? RegisterGenericClassInstance : RegisterGenericInterfaceInstance), args)));
            }
        }
 public void TokenizerCanDetectParameterNamePreceededByAtSign()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{p1}", new[] { "@p1" }, new string[0], s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.Parameter, index: 0) }));
 }
 public void TokenizerCanDetectLiteralStringParameterToUseAsIdentifier()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{@p1}{@p2}", new[] { "p1", "p2" }, new string[0], s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.LiteralStringParameterToUseAsIdentifier, index: 0), new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.LiteralStringParameterToUseAsIdentifier, index: 1) }));
 }
 public void TokenizerCanDetectExpandedParamArrayParameter()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{*p1}{*p2}", new[] { "p1", "p2" }, new string[0], s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.ExpandedParamArrayParameter, index: 0), new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.ExpandedParamArrayParameter, index: 1) }));
 }
 public void TokenizerCanDetectTypeParameterNames()
 {
     Assert.That(InlineCodeMethodCompiler.Tokenize("{T1}{T2}", new string[0], new[] { "T1", "T2" }, s => Assert.Fail("Unexpected error " + s)),
                 Is.EqualTo(new[] { new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.TypeParameter, index: 0), new InlineCodeMethodCompiler.InlineCodeToken(InlineCodeMethodCompiler.InlineCodeToken.TokenType.TypeParameter, index: 1) }));
 }
        private void AddClassMembers(JsClass c, string typevarName, List <JsStatement> stmts)
        {
            if (c.NamedConstructors.Count > 0)
            {
                stmts.AddRange(c.NamedConstructors.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), m.Definition)));
            }

            var  defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic);
            bool hasCreateInstance  = false;

            if (defaultConstructor != null)
            {
                var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor);
                if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript)
                {
                    var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null);
                    stmts.Add(JsExpression.Assign(
                                  JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance"),
                                  JsExpression.FunctionDefinition(new string[0], JsStatement.Block(createInstance.AdditionalStatements.Concat(new[] { JsStatement.Return(createInstance.Expression) })))));
                    hasCreateInstance = true;
                }
            }

            if (c.CSharpTypeDefinition.Kind == TypeKind.Struct)
            {
                stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "getDefaultValue"), hasCreateInstance ? JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance") : JsExpression.FunctionDefinition(EmptyList <string> .Instance, JsStatement.Return(JsExpression.New(JsExpression.Identifier(typevarName))))));

                if (_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Type == TypeScriptSemantics.ImplType.MutableValueType)
                {
                    stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "$clone"), GenerateStructCloneMethod(c.CSharpTypeDefinition, typevarName, hasCreateInstance)));
                }
            }

            stmts.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), RewriteMethod(m))));

            if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition, _attributeStore))
            {
                string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition, _attributeStore);
                if (!string.IsNullOrEmpty(typeCheckCode))
                {
                    var oldReg = _errorReporter.Region;
                    _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region;
                    var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation);

                    var errors = new List <string>();
                    var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add);
                    if (errors.Count == 0)
                    {
                        var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer);
                        var result  = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0],
                                                                                                           n => {
                            var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation);
                            if (type.Kind == TypeKind.Unknown)
                            {
                                errors.Add("Unknown type '" + n + "' specified in inline implementation");
                                return(JsExpression.Null);
                            }
                            return(_runtimeLibrary.InstantiateType(type, context));
                        },
                                                                                                           t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context),
                                                                                                           errors.Add);

                        stmts.Add(JsExpression.Assign(
                                      JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"),
                                      JsExpression.FunctionDefinition(new[] { "obj" }, JsStatement.Return(result))));

                        foreach (var e in errors)
                        {
                            _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e);
                        }
                    }
                    _errorReporter.Region = oldReg;
                }
                else
                {
                    stmts.Add(JsExpression.Assign(
                                  JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"),
                                  JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.True))));
                }
            }

            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
            {
                var args = new List <JsExpression> {
                    JsExpression.Identifier(typevarName),
                    new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp)))),
                    CreateInstanceMembers(c, typevarName),
                };
                if (c.CSharpTypeDefinition.Kind != TypeKind.Interface)
                {
                    args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null)));
                }
                args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition)))));
                stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterfaceInstance : RegisterGenericClassInstance), args));
                if (c.CSharpTypeDefinition.Kind == TypeKind.Class && c.NamedConstructors.Count > 0)
                {
                    stmts.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(typevarName)));
                }
                if (c.CSharpTypeDefinition.Kind == TypeKind.Struct)
                {
                    stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "__class"), JsExpression.False));
                }
                var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true);
                if (metadata != null)
                {
                    stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(typevarName), metadata));
                }
            }
        }