Пример #1
0
 private Editor()
 {
     shadowClass = new ShadowClass();
     contexts = new Contexts(shadowClass);
     codeLexer = new CodeLexer(contexts);
     templateLexer = new TemplateLexer(contexts);
 }
Пример #2
0
        public static Type Compile(ShadowClass shadowClass)
        {
            if (Directory.Exists(Constants.TempDirectory) == false)
            {
                Directory.CreateDirectory(Constants.TempDirectory);
            }

            var filname = Path.GetRandomFileName();
            var path = Path.Combine(Constants.TempDirectory, filname);

            var result = shadowClass.Compile(path);

            if (result.Success)
                return Assembly.LoadFrom(path).GetTypes().FirstOrDefault();

            var errors = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error);

            foreach (var error in errors)
            {
                var message = error.GetMessage();

                message = message.Replace("__Typewriter.", string.Empty);
                message = message.Replace("__Code.", string.Empty);
                message = message.Replace("publicstatic", string.Empty);

                Log.Error("Template error: {0} {1}", error.Id, message);
            }

            throw new Exception("Failed to compile template.");
        }
Пример #3
0
        public static string Parse(string template, List<Type> extensions)
        {
            if (string.IsNullOrWhiteSpace(template)) return null;

            var output = string.Empty;
            var stream = new Stream(template);
            var shadowClass = new ShadowClass();
            var contexts = new Contexts(shadowClass);

            shadowClass.Clear();

            while (stream.Advance())
            {
                if (ParseCodeBlock(stream, shadowClass)) continue;
                if (ParseLambda(stream, shadowClass, contexts, ref output)) continue;
                output += stream.Current;
            }

            shadowClass.Parse();

            extensions.Clear();
            extensions.Add(Compiler.Compile(shadowClass));
            extensions.AddRange(FindExtensionClasses(shadowClass));

            return output;
        }
Пример #4
0
        public Contexts(ShadowClass shadowClass)
        {
            var assembly = typeof(ContextAttribute).Assembly;

            ParseCodeModel(assembly);
            ParseExtensions(shadowClass);
        }
Пример #5
0
        private static void ParseCode(Stream stream, ShadowClass shadowClass)
        {
            var code = new StringBuilder();

            do
            {
                code.Append(stream.Current);
            }
            while (stream.Advance());

            shadowClass.AddBlock(code.ToString(), 0);
        }
Пример #6
0
        private static bool ParseLambda(Stream stream, ShadowClass shadowClass, ref string template)
        {
            if (stream.Current == '$')
            {
                var identifier = stream.PeekWord(1);
                if (identifier != null)
                {
                    var filter = stream.PeekBlock(identifier.Length + 2, '(', ')');
                    if (filter != null && stream.Peek(filter.Length + 2 + identifier.Length + 1) == '[')
                    {
                        try
                        {
                            var index = filter.IndexOf("=>", StringComparison.Ordinal);

                            if (index > 0)
                            {
                                var name = filter.Substring(0, index);

                                var contextName = identifier;
                                // Todo: Make the TemplateCodeParser context aware
                                if (contextName == "GenericTypeArguments") contextName = "Types";
                                else if (contextName.StartsWith("Nested")) contextName = contextName.Remove(0, 6);

                                var type = Contexts.Find(contextName)?.Type.FullName;

                                if (type == null) return false;

                                var methodIndex = counter++;

                                shadowClass.AddLambda(filter, type, name, methodIndex);

                                stream.Advance(filter.Length + 2 + identifier.Length);
                                template += $"${identifier}($__{methodIndex})";

                                return true;
                            }
                        }
                        catch
                        {
                        }
                    }
                }
            }

            return false;
        }
Пример #7
0
        private static bool ParseCodeBlock(Stream stream, ShadowClass shadowClass)
        {
            if (stream.Current == '$' && stream.Peek() == '{')
            {
                stream.Advance();

                var block = stream.PeekBlock(1, '{', '}');
                var codeStream = new Stream(block, stream.Position + 1);

                ParseUsings(codeStream, shadowClass);
                ParseCode(codeStream, shadowClass);

                stream.Advance(block.Length + 1);

                return true;
            }

            return false;
        }
Пример #8
0
        private static IEnumerable<Type> FindExtensionClasses(ShadowClass shadowClass)
        {
            var types = new List<Type>();

            var usings = shadowClass.Snippets.Where(s => s.Type == SnippetType.Using && s.Code.StartsWith("using"));
            foreach (var usingStatement in usings.Select(u => u.Code))
            {
                var ns = usingStatement.Remove(0, 5).Trim().Trim(';');

                foreach (var assembly in shadowClass.ReferencedAssemblies)
                {
                    types.AddRange(assembly.GetExportedTypes().Where(t => t.Namespace == ns &&
                        t.GetMethods(BindingFlags.Static | BindingFlags.Public).Any(m =>
                            m.IsDefined(typeof (ExtensionAttribute), false) &&
                            m.GetParameters().First().ParameterType.Namespace == "Typewriter.CodeModel")));
                }
            }

            return types;
        }
Пример #9
0
        private static void ParseUsings(Stream stream, ShadowClass shadowClass)
        {
            stream.Advance();

            while (true)
            {
                stream.SkipWhitespace();

                if ((stream.Current == 'u' && stream.PeekWord() == "using") || (stream.Current == '/' && stream.Peek() == '/'))
                {
                    var line = stream.PeekLine();
                    shadowClass.AddUsing(line, stream.Position);
                    stream.Advance(line.Length);

                    continue;
                }

                break;
            }
        }
Пример #10
0
        private void ParseExtensions(ShadowClass shadowClass)
        {
            foreach (var assembly in shadowClass.ReferencedAssemblies)
            {
                var methods = assembly.GetExportedTypes().SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public)
                    .Where(m => m.IsDefined(typeof (ExtensionAttribute), false) &&
                        m.GetParameters().First().ParameterType.Namespace == "Typewriter.CodeModel"));

                foreach (var method in methods)
                {
                    var parameters = method.GetParameters();
                    if (parameters.Count() != 1) continue;

                    var context = items.Values.FirstOrDefault(c => c.Type == parameters.First().ParameterType);

                    if (context != null)
                    {
                        var identifier = CreateIdentifier(method);
                        context.AddExtensionIdentifier(method.ReflectedType.Namespace, identifier);
                    }
                }
            }
        }
Пример #11
0
 public SemanticModel(ShadowClass shadowClass)
 {
     this.shadowClass = shadowClass;
 }