Пример #1
0
        /// <summary>
        /// Parser to turn lg content into an <see cref="LGFile"/>.
        /// </summary>
        /// <param name="content">Text content contains lg templates.</param>
        /// <param name="id">id is the content identifier. If importResolver is null, id must be a full path string. </param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <returns>new <see cref="LGFile"/> entity.</returns>
        public static LGFile ParseText(string content, string id = "", ImportResolverDelegate importResolver = null)
        {
            importResolver = importResolver ?? DefaultFileResolver;
            var lgFile      = new LGFile(content: content, id: id, importResolver: importResolver);
            var diagnostics = new List <Diagnostic>();

            try
            {
                var(templates, imports, invalidTemplateErrors) = AntlrParse(content, id);
                lgFile.Templates = templates;
                lgFile.Imports   = imports;
                diagnostics.AddRange(invalidTemplateErrors);

                lgFile.References = GetReferences(lgFile, importResolver);
                var semanticErrors = new StaticChecker(lgFile).Check();
                diagnostics.AddRange(semanticErrors);
            }
            catch (LGException ex)
            {
                diagnostics.AddRange(ex.Diagnostics);
            }
            catch (Exception err)
            {
                diagnostics.Add(BuildDiagnostic(err.Message, source: id));
            }

            lgFile.Diagnostics = diagnostics;

            return(lgFile);
        }
Пример #2
0
 /// <summary>
 /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>.
 /// </summary>
 /// <param name="filePath">Absolute path of a LG file.</param>
 /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">expressionEngine Expression engine for evaluating expressions.</param>
 /// <returns>new <see cref="LanguageGeneration.Templates"/> entity.</returns>
 public static Templates ParseFile(
     string filePath,
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null)
 {
     return(TemplatesParser.ParseFile(filePath, importResolver, expressionParser).InjectToExpressionFunction());
 }
Пример #3
0
        /// <summary>
        /// Parser to turn lg content into an <see cref="LGFile"/>.
        /// </summary>
        /// <param name="filePath">LG absolute file path.</param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <returns>new <see cref="LGFile"/> entity.</returns>
        public static LGFile ParseFile(string filePath, ImportResolverDelegate importResolver = null)
        {
            var fullPath = Path.GetFullPath(filePath.NormalizePath());
            var content  = File.ReadAllText(fullPath);

            return(ParseText(content, fullPath, importResolver));
        }
Пример #4
0
        /// <summary>
        /// Parser to turn lg content into a <see cref="Templates"/>.
        /// </summary>
        /// <param name="resource">LG resource.</param>
        /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
        /// <param name="expressionParser">Expression parser for parsing expressions.</param>
        /// <param name="cachedTemplates">Give the file path and templates to avoid parsing and to improve performance.</param>
        /// <param name="parentTemplates">Parent visited Templates.</param>
        /// <returns>new <see cref="Templates"/> entity.</returns>
        private static Templates InnerParseResource(
            LGResource resource,
            ImportResolverDelegate importResolver          = null,
            ExpressionParser expressionParser              = null,
            Dictionary <string, Templates> cachedTemplates = null,
            Stack <Templates> parentTemplates              = null)
        {
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>();
            parentTemplates = parentTemplates ?? new Stack <Templates>();
            if (cachedTemplates.ContainsKey(resource.Id))
            {
                return(cachedTemplates[resource.Id]);
            }

            importResolver = importResolver ?? DefaultFileResolver;
            var lg = new Templates(content: resource.Content, id: resource.Id, source: resource.FullName, importResolver: importResolver, expressionParser: expressionParser);

            try
            {
                lg            = new TemplatesTransformer(lg).Transform(AntlrParseTemplates(resource));
                lg.References = GetReferences(lg, cachedTemplates, parentTemplates);
                new StaticChecker(lg).Check().ForEach(u => lg.Diagnostics.Add(u));
            }
            catch (TemplateException ex)
            {
                ex.Diagnostics.ToList().ForEach(u => lg.Diagnostics.Add(u));
            }

            return(lg);
        }
Пример #5
0
        public Templates(
            IList <Template> templates     = null,
            IList <TemplateImport> imports = null,
            IList <Diagnostic> diagnostics = null,
            IList <Templates> references   = null,
            string content = null,
            string id      = null,
            ExpressionParser expressionParser     = null,
            ImportResolverDelegate importResolver = null,
            IList <string> options = null)
        {
            if (templates != null)
            {
                this.AddRange(templates);
            }

            Imports          = imports ?? new List <TemplateImport>();
            Diagnostics      = diagnostics ?? new List <Diagnostic>();
            References       = references ?? new List <Templates>();
            Content          = content ?? string.Empty;
            ImportResolver   = importResolver;
            Id               = id ?? string.Empty;
            ExpressionParser = expressionParser ?? new ExpressionParser();
            Options          = options ?? new List <string>();
            this.InjectToExpressionFunction();
        }
        /// <summary>
        /// Parser to turn lg content into a <see cref="Templates"/>.
        /// </summary>
        /// <param name="content">Text content contains lg templates.</param>
        /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param>
        /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
        /// <param name="expressionParser">Expression parser for parsing expressions.</param>
        /// <param name="cachedTemplates">Give the file path and templates to avoid parsing and to improve performance.</param>
        /// <returns>new <see cref="Templates"/> entity.</returns>
        private static Templates InnerParseText(
            string content,
            string id = "",
            ImportResolverDelegate importResolver          = null,
            ExpressionParser expressionParser              = null,
            Dictionary <string, Templates> cachedTemplates = null)
        {
            cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>();
            if (cachedTemplates.ContainsKey(id))
            {
                return(cachedTemplates[id]);
            }

            importResolver = importResolver ?? DefaultFileResolver;
            var lg = new Templates(content: content, id: id, importResolver: importResolver, expressionParser: expressionParser);

            try
            {
                lg            = new TemplatesTransformer(lg).Transform(AntlrParseTemplates(content, id));
                lg.References = GetReferences(lg, cachedTemplates);
                new StaticChecker(lg).Check().ForEach(u => lg.Diagnostics.Add(u));
            }
            catch (TemplateException ex)
            {
                ex.Diagnostics.ToList().ForEach(u => lg.Diagnostics.Add(u));
            }

            return(lg);
        }
Пример #7
0
 /// <summary>
 /// Parser to turn lg content into a <see cref="Templates"/>.
 /// </summary>
 /// <param name="resource">LG resource.</param>
 /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">Expression parser for parsing expressions.</param>
 /// <returns>new <see cref="Templates"/> entity.</returns>
 public static Templates ParseResource(
     LGResource resource,
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null)
 {
     return(InnerParseResource(resource, importResolver, expressionParser));
 }
 /// <summary>
 /// Parser to turn lg content into a <see cref="Templates"/>.
 /// </summary>
 /// <param name="content">Text content contains lg templates.</param>
 /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param>
 /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">Expression parser for parsing expressions.</param>
 /// <returns>New <see cref="Templates"/> entity.</returns>
 public static Templates ParseText(
     string content,
     string id = "",
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null)
 {
     return(InnerParseText(content, id, importResolver, expressionParser));
 }
Пример #9
0
        /// <summary>
        /// Discover all imported lg resources from a start resouce.
        /// </summary>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <returns>LGResource list of parsed lg content.</returns>
        public List <LGResource> DiscoverDependencies(ImportResolverDelegate importResolver)
        {
            var resourcesFound = new HashSet <LGResource>();

            ResolveImportResources(this, importResolver ?? ImportResolver.FileResolver, resourcesFound);

            return(resourcesFound.ToList());
        }
Пример #10
0
        private static IList <LGFile> GetReferences(LGFile file, ImportResolverDelegate importResolver)
        {
            var resourcesFound = new HashSet <LGFile>();

            ResolveImportResources(file, resourcesFound, importResolver);

            resourcesFound.Remove(file);
            return(resourcesFound.ToList());
        }
        /// <summary>
        /// Parser to turn lg content into a <see cref="Templates"/>.
        /// </summary>
        /// <param name="filePath">Absolut path of a LG file.</param>
        /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
        /// <param name="expressionParser">Expression parser for parsing expressions.</param>
        /// <returns>new <see cref="Templates"/> entity.</returns>
        public static Templates ParseFile(
            string filePath,
            ImportResolverDelegate importResolver = null,
            ExpressionParser expressionParser     = null)
        {
            var fullPath = Path.GetFullPath(filePath.NormalizePath());
            var content  = File.ReadAllText(fullPath);

            return(InnerParseText(content, fullPath, importResolver, expressionParser));
        }
Пример #12
0
        public static Templates ParseText(
            string content,
            string id = "",
            ImportResolverDelegate importResolver = null,
            ExpressionParser expressionParser     = null)
        {
            var resource = new LGResource(id, id, content);

            return(ParseResource(resource, importResolver, expressionParser));
        }
Пример #13
0
        /// <summary>
        /// Add text as lg file content to template engine. A fullpath id is needed when importResolver is empty, or simply pass in customized importResolver.
        /// </summary>
        /// <param name="content">Text content contains lg templates.</param>
        /// <param name="id">id is the content identifier. If importResolver is null, id must be a full path string. </param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <returns>Template engine with the parsed content.</returns>
        public TemplateEngine AddText(string content, string id = "", ImportResolverDelegate importResolver = null)
        {
            CheckImportResolver(id, importResolver);

            var rootResource = LGParser.Parse(content, id);
            var lgresources  = rootResource.DiscoverDependencies(importResolver);

            Templates.AddRange(lgresources.SelectMany(x => x.Templates));
            RunStaticCheck(Templates);

            return(this);
        }
Пример #14
0
        /// <summary>
        /// Parser to turn lg content into a <see cref="Templates"/>.
        /// </summary>
        /// <param name="filePath">Absolut path of a LG file.</param>
        /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
        /// <param name="expressionParser">Expression parser for parsing expressions.</param>
        /// <returns>new <see cref="Templates"/> entity.</returns>
        public static Templates ParseFile(
            string filePath,
            ImportResolverDelegate importResolver = null,
            ExpressionParser expressionParser     = null)
        {
            var fullPath = Path.GetFullPath(filePath.NormalizePath());
            var content  = File.ReadAllText(fullPath);

            var resource = new LGResource(fullPath, fullPath, content);

            return(ParseResource(resource, importResolver, expressionParser));
        }
Пример #15
0
 private void CheckImportResolver(string id, ImportResolverDelegate importResolver)
 {
     // Currently if no resolver is passed into AddText(),
     // the default fileResolver is used to resolve the imports.
     // default fileResolver require resource id should be fullPath,
     // so that it can resolve relative path based on this fullPath.
     // But we didn't check the id provided with AddText is fullPath or not.
     // So when id != fullPath, fileResolver won't work.
     if (importResolver == null)
     {
         var importPath = ImportResolver.NormalizePath(id);
         if (!Path.IsPathRooted(importPath))
         {
             throw new Exception("[Error] id must be full path when importResolver is null");
         }
     }
 }
Пример #16
0
 public LGFile(
     IList <LGTemplate> templates   = null,
     IList <LGImport> imports       = null,
     IList <Diagnostic> diagnostics = null,
     IList <LGFile> references      = null,
     string content = null,
     string id      = null,
     ExpressionEngine expressionEngine     = null,
     ImportResolverDelegate importResolver = null)
 {
     Templates        = templates ?? new List <LGTemplate>();
     Imports          = imports ?? new List <LGImport>();
     Diagnostics      = diagnostics ?? new List <Diagnostic>();
     References       = references ?? new List <LGFile>();
     Content          = content ?? string.Empty;
     ImportResolver   = importResolver;
     Id               = id ?? string.Empty;
     ExpressionEngine = expressionEngine ?? new ExpressionEngine();
 }
        /// <summary>
        /// Parser to turn lg content into a <see cref="Templates"/>.
        /// </summary>
        /// <param name="content">Text content contains lg templates.</param>
        /// <param name="id">id is the identifier of content. If importResolver is null, id must be a full path string. </param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <param name="expressionParser">expressionEngine parser engine for parsing expressions.</param>
        /// <param name="cachedTemplates">give the file path and templates to avoid parsing and to improve performance.</param>
        /// <returns>new <see cref="Templates"/> entity.</returns>
        private static Templates InnerParseText(
            string content,
            string id = "",
            ImportResolverDelegate importResolver          = null,
            ExpressionParser expressionParser              = null,
            Dictionary <string, Templates> cachedTemplates = null)
        {
            cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>();
            if (cachedTemplates.ContainsKey(id))
            {
                return(cachedTemplates[id]);
            }

            importResolver = importResolver ?? DefaultFileResolver;
            var lg = new Templates(content: content, id: id, importResolver: importResolver, expressionParser: expressionParser);

            var diagnostics = new List <Diagnostic>();

            try
            {
                var(templates, imports, invalidTemplateErrors, options) = AntlrParse(content, id);
                lg.AddRange(templates);
                lg.Imports = imports;
                lg.Options = options;
                diagnostics.AddRange(invalidTemplateErrors);

                lg.References = GetReferences(lg, cachedTemplates);
                var semanticErrors = new StaticChecker(lg).Check();
                diagnostics.AddRange(semanticErrors);
            }
            catch (TemplateException ex)
            {
                diagnostics.AddRange(ex.Diagnostics);
            }
            catch (Exception err)
            {
                diagnostics.Add(BuildDiagnostic(err.Message, source: id));
            }

            lg.Diagnostics = diagnostics;

            return(lg);
        }
Пример #18
0
        /// <summary>
        /// Load .lg files into template engine
        /// You can add one file, or mutlple file as once
        /// If you have multiple files referencing each other, make sure you add them all at once,
        /// otherwise static checking won't allow you to add it one by one.
        /// </summary>
        /// <param name="filePaths">Paths to .lg files.</param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <returns>Teamplate engine with parsed files.</returns>
        public TemplateEngine AddFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null)
        {
            var totalLGResources = new List <LGResource>();

            foreach (var filePath in filePaths)
            {
                var fullPath     = Path.GetFullPath(ImportResolver.NormalizePath(filePath));
                var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath);
                var lgresources  = rootResource.DiscoverDependencies(importResolver);
                totalLGResources.AddRange(lgresources);
            }

            // Remove duplicated lg files by id
            var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList();

            Templates.AddRange(deduplicatedLGResources.SelectMany(x => x.Templates));
            RunStaticCheck(Templates);

            return(this);
        }
Пример #19
0
        public List <Diagnostic> CheckFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null)
        {
            var result         = new List <Diagnostic>();
            var templates      = new List <LGTemplate>();
            var isParseSuccess = true;

            try
            {
                var totalLGResources = new List <LGResource>();
                foreach (var filePath in filePaths)
                {
                    // do not use ??=, it will cause issue in the C# < 8.0
                    importResolver = importResolver ?? ImportResolver.FileResolver;

                    var fullPath     = Path.GetFullPath(ImportResolver.NormalizePath(filePath));
                    var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath);
                    var resources    = rootResource.DiscoverDependencies(importResolver);
                    totalLGResources.AddRange(resources);
                }

                var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList();
                templates = deduplicatedLGResources.SelectMany(x => x.Templates).ToList();
            }
            catch (LGException ex)
            {
                result.AddRange(ex.Diagnostics);
                isParseSuccess = false;
            }
            catch (Exception err)
            {
                result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message));
                isParseSuccess = false;
            }

            if (isParseSuccess)
            {
                result.AddRange(CheckTemplates(templates));
            }

            return(result);
        }
Пример #20
0
        public List <Diagnostic> CheckText(string content, string id = "", ImportResolverDelegate importResolver = null)
        {
            if (importResolver == null)
            {
                var importPath = ImportResolver.NormalizePath(id);
                if (!Path.IsPathRooted(importPath))
                {
                    throw new Exception("[Error] id must be full path when importResolver is null");
                }
            }

            var result         = new List <Diagnostic>();
            var templates      = new List <LGTemplate>();
            var isParseSuccess = true;

            try
            {
                var rootResource = LGParser.Parse(content, id);
                var resources    = rootResource.DiscoverDependencies(importResolver);
                templates = resources.SelectMany(x => x.Templates).ToList();
            }
            catch (LGException ex)
            {
                result.AddRange(ex.Diagnostics);
                isParseSuccess = false;
            }
            catch (Exception err)
            {
                result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message));
                isParseSuccess = false;
            }

            if (isParseSuccess)
            {
                result.AddRange(CheckTemplates(templates));
            }

            return(result);
        }
Пример #21
0
        /// <summary>
        /// Resolve imported LG resources from a start resource.
        /// All the imports will be visited and resolved to LGResouce list.
        /// </summary>
        /// <param name="start">The lg resource from which to start resolving imported resources.</param>
        /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
        /// <param name="resourcesFound">Resources that have been found.</param>
        private void ResolveImportResources(LGResource start, ImportResolverDelegate importResolver, HashSet <LGResource> resourcesFound)
        {
            var resourceIds = start.Imports.Select(lg => lg.Id).ToList();

            resourcesFound.Add(start);

            foreach (var id in resourceIds)
            {
                try
                {
                    var(content, path) = importResolver(start.Id, id);
                    var childResource = LGParser.Parse(content, path);
                    if (!resourcesFound.Contains(childResource))
                    {
                        ResolveImportResources(childResource, importResolver, resourcesFound);
                    }
                }
                catch (Exception err)
                {
                    throw new Exception($"[Error]{id}:{err.Message}", err);
                }
            }
        }
Пример #22
0
 /// <summary>
 /// Load single .lg file into template engine.
 /// </summary>
 /// <param name="filePath">Path to .lg file.</param>
 /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
 /// <returns>Teamplate engine with single parsed file.</returns>
 public TemplateEngine AddFile(string filePath, ImportResolverDelegate importResolver = null) => AddFiles(new List <string> {
     filePath
 }, importResolver);
Пример #23
0
 /// <summary>
 /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>.
 /// </summary>
 /// <param name="resource">LG resource.</param>
 /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">Expression parser engine for parsing expressions.</param>
 /// <returns>new <see cref="Templates"/> entity.</returns>
 public static Templates ParseResource(
     LGResource resource,
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null) => TemplatesParser.ParseResource(resource, importResolver, expressionParser).InjectToExpressionFunction();
Пример #24
0
 /// <summary>
 /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>.
 /// </summary>
 /// <param name="content">Text content contains lg templates.</param>
 /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param>
 /// <param name="importResolver">Resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">Expression parser engine for parsing expressions.</param>
 /// <returns>new <see cref="Templates"/> entity.</returns>
 public static Templates ParseText(
     string content,
     string id = "",
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null) => TemplatesParser.ParseText(content, id, importResolver, expressionParser).InjectToExpressionFunction();
Пример #25
0
 /// <summary>
 /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>.
 /// </summary>
 /// <param name="filePath">Absolute path of a LG file.</param>
 /// <param name="importResolver">resolver to resolve LG import id to template text.</param>
 /// <param name="expressionParser">expressionEngine Expression engine for evaluating expressions.</param>
 /// <returns>new <see cref="LanguageGeneration.Templates"/> entity.</returns>
 public static Templates ParseFile(
     string filePath,
     ImportResolverDelegate importResolver = null,
     ExpressionParser expressionParser     = null) => TemplatesParser.ParseFile(filePath, importResolver, expressionParser);
Пример #26
0
        private static void ResolveImportResources(LGFile start, HashSet <LGFile> resourcesFound, ImportResolverDelegate importResolver)
        {
            var resourceIds = start.Imports.Select(lg => lg.Id);

            resourcesFound.Add(start);

            foreach (var id in resourceIds)
            {
                try
                {
                    var(content, path) = importResolver(start.Id, id);
                    if (resourcesFound.All(u => u.Id != path))
                    {
                        var childResource = ParseText(content, path, importResolver);
                        ResolveImportResources(childResource, resourcesFound, importResolver);
                    }
                }
                catch (LGException err)
                {
                    throw err;
                }
                catch (Exception err)
                {
                    throw new LGException(err.Message, new List <Diagnostic> {
                        BuildDiagnostic(err.Message, source: start.Id)
                    });
                }
            }
        }
Пример #27
0
 public List <Diagnostic> CheckFile(string filePath, ImportResolverDelegate importResolver = null) => CheckFiles(new List <string>()
 {
     filePath
 }, importResolver);
Пример #28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TemplateEngineLanguageGenerator"/> class.
 /// </summary>
 /// <param name="lgText">lg template text.</param>
 /// <param name="importResolver">template resource loader (id) => templateText.</param>
 /// <param name="id">optional label for the source of the templates (used for labeling source of template errors).</param>
 public TemplateEngineLanguageGenerator(string lgText, string id = null, ImportResolverDelegate importResolver = null)
 {
     this.Id     = id ?? DEFAULTLABEL;
     this.engine = new TemplateEngine().AddText(lgText ?? string.Empty, this.Id, importResolver: importResolver);
 }