Skip to content

Added a default timeout for parsing #4

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

Open
wants to merge 2 commits into
base: main
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
6 changes: 4 additions & 2 deletions ColorCode.Core/CodeColorizerBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ColorCode.Compilation;
using ColorCode.Parsing;
using ColorCode.Styling;
using System;
using System.Collections.Generic;

namespace ColorCode
Expand All @@ -10,12 +11,13 @@ namespace ColorCode
/// </summary>
/// <param name="Style">The Custom styles to Apply to the formatted Code.</param>
/// <param name="languageParser">The language parser that the <see cref="CodeColorizerBase"/> instance will use for its lifetime.</param>
/// <param name="defaultParseTimeoutSec">The default amount of time spent parsing before throwing a <see cref="System.Text.RegularExpressions.RegexMatchTimeoutException"/></param>
public abstract class CodeColorizerBase
{
public CodeColorizerBase(StyleDictionary Styles, ILanguageParser languageParser)
public CodeColorizerBase(StyleDictionary Styles, ILanguageParser languageParser, double defaultParseTimeoutSec = 4)
{
this.languageParser = languageParser
?? new LanguageParser(new LanguageCompiler(Languages.CompiledLanguages), Languages.LanguageRepository);
?? new LanguageParser(new LanguageCompiler(Languages.CompiledLanguages), Languages.LanguageRepository, defaultParseTimeoutSec);

this.Styles = Styles ?? StyleDictionary.DefaultLight;
}
Expand Down
2 changes: 1 addition & 1 deletion ColorCode.Core/Compilation/ILanguageCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace ColorCode.Compilation
{
public interface ILanguageCompiler
{
CompiledLanguage Compile(ILanguage language);
CompiledLanguage Compile(ILanguage language, double defaultParseTimeoutSec);
}
}
12 changes: 6 additions & 6 deletions ColorCode.Core/Compilation/LanguageCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public LanguageCompiler(Dictionary<string, CompiledLanguage> compiledLanguages)
compileLock = new ReaderWriterLockSlim();
}

public CompiledLanguage Compile(ILanguage language)
public CompiledLanguage Compile(ILanguage language, double defaultParseTimeoutSec)
{
Guard.ArgNotNull(language, "language");

Expand Down Expand Up @@ -62,7 +62,7 @@ public CompiledLanguage Compile(ILanguage language)
if (language.Rules == null || language.Rules.Count == 0)
throw new ArgumentException("The language rules collection must not be empty.", "language");

compiledLanguage = CompileLanguage(language);
compiledLanguage = CompileLanguage(language, defaultParseTimeoutSec);

compiledLanguages.Add(compiledLanguage.Id, compiledLanguage);
}
Expand All @@ -80,17 +80,17 @@ public CompiledLanguage Compile(ILanguage language)
return compiledLanguage;
}

private static CompiledLanguage CompileLanguage(ILanguage language)
private static CompiledLanguage CompileLanguage(ILanguage language, double defaultParseTimeoutSec)
{
string id = language.Id;
string name = language.Name;

CompileRules(language.Rules, out Regex regex, out IList<string> captures);
CompileRules(language.Rules, defaultParseTimeoutSec, out Regex regex, out IList<string> captures);

return new CompiledLanguage(id, name, regex, captures);
}

private static void CompileRules(IList<LanguageRule> rules, out Regex regex, out IList<string> captures)
private static void CompileRules(IList<LanguageRule> rules, double defaultParseTimeoutSec, out Regex regex, out IList<string> captures)
{
StringBuilder regexBuilder = new StringBuilder();
captures = new List<string>();
Expand All @@ -103,7 +103,7 @@ private static void CompileRules(IList<LanguageRule> rules, out Regex regex, out
for (int i = 1; i < rules.Count; i++)
CompileRule(rules[i], regexBuilder, captures, false);

regex = new Regex(regexBuilder.ToString());
regex = new Regex(regexBuilder.ToString(), RegexOptions.None, TimeSpan.FromSeconds(defaultParseTimeoutSec));
}

private static void CompileRule(LanguageRule languageRule, StringBuilder regex, ICollection<string> captures, bool isFirstRule)
Expand Down
18 changes: 15 additions & 3 deletions ColorCode.Core/Parsing/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,34 @@ public class LanguageParser : ILanguageParser
{
private readonly ILanguageCompiler languageCompiler;
private readonly ILanguageRepository languageRepository;
private readonly double defaultParseTimeoutSec = 1;

public LanguageParser(ILanguageCompiler languageCompiler,
ILanguageRepository languageRepository)
ILanguageRepository languageRepository,
double defaultParseTimeoutSec)
{
this.languageCompiler = languageCompiler;
this.languageRepository = languageRepository;
this.defaultParseTimeoutSec = defaultParseTimeoutSec;
}

/// <summary>
/// Formats the specified text using the rules defined by the specified language.
/// </summary>
/// <param name="sourceCode">The text to parse</param>
/// <param name="language">The language used to define the syntax highlighting rules</param>
/// <param name="parseHandler">Called after parsing is complete</param>
/// <exception cref="System.Text.RegularExpressions.RegexMatchTimeoutException">
/// Thrown if parsing takes longer than the default specified duration
/// </exception>
public void Parse(string sourceCode,
ILanguage language,
Action<string, IList<Scope>> parseHandler)
{
if (string.IsNullOrEmpty(sourceCode))
return;

CompiledLanguage compiledLanguage = languageCompiler.Compile(language);
CompiledLanguage compiledLanguage = languageCompiler.Compile(language, defaultParseTimeoutSec);

Parse(sourceCode, compiledLanguage, parseHandler);
}
Expand Down Expand Up @@ -157,7 +169,7 @@ private void AppendCapturedStylesForNestedLanguage(Capture regexCapture,
throw new InvalidOperationException("The nested language was not found in the language repository.");
else
{
CompiledLanguage nestedCompiledLanguage = languageCompiler.Compile(nestedLanguage);
CompiledLanguage nestedCompiledLanguage = languageCompiler.Compile(nestedLanguage, defaultParseTimeoutSec);

Match regexMatch = nestedCompiledLanguage.Regex.Match(regexCapture.Value, 0, regexCapture.Value.Length);

Expand Down