xamarin-macios/tools/pmcs/Replacement.cs

170 строки
3.8 KiB
C#

//
// Replacement.cs
//
// Author:
// Aaron Bockover <abock@xamarin.com>
//
// Copyright 2013-2015 Xamarin Inc. All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Xamarin.Pmcs
{
public enum ReplacementContext
{
Global,
EnumBackingType
}
public enum ReplacementKind
{
Builtin,
Exact,
Regex,
Prefix
}
public abstract class ExplicitReplacement : Replacement
{
protected abstract string Evaluate (string input);
public sealed override bool Evaluate (string input, out string replacement)
{
replacement = Evaluate (input);
return replacement != null;
}
}
public class Replacement
{
Regex regex;
public ReplacementContext Context { get; set; }
public ReplacementKind Kind { get; set; }
public string Pattern { get; set; }
public string Replace { get; set; }
public bool IsValid {
get { return Pattern != null && Replace != null; }
}
public static Replacement Parse (string pattern, string replace)
{
if (String.IsNullOrEmpty (pattern))
throw new ArgumentNullException ("pattern");
var replacement = new Replacement ();
if (pattern [0] == '/') {
replacement.Kind = ReplacementKind.Regex;
replacement.Pattern = pattern.Substring (1);
} else if (pattern [0] == '^') {
replacement.Kind = ReplacementKind.Prefix;
replacement.Pattern = pattern.Substring (1);
} else {
replacement.Kind = ReplacementKind.Exact;
replacement.Pattern = pattern;
}
replacement.Replace = replace;
return replacement;
}
public virtual bool Evaluate (string input, out string replacement)
{
replacement = null;
switch (Kind) {
case ReplacementKind.Exact:
if (input == Pattern)
replacement = Replace;
break;
case ReplacementKind.Prefix:
if (input.StartsWith (Pattern, StringComparison.Ordinal))
replacement = Replace + input.Substring (Pattern.Length);
break;
case ReplacementKind.Regex:
if (regex == null)
regex = new Regex (Pattern, RegexOptions.Compiled | RegexOptions.Singleline);
replacement = regex.Replace (input, Replace);
break;
}
return input != replacement && replacement != null;
}
public override string ToString ()
{
switch (Kind) {
case ReplacementKind.Builtin:
return String.Format ("builtin: <{0}>", GetType ().FullName);
case ReplacementKind.Exact:
return String.Format ("exact: {0} => {1}", Pattern, Replace);
case ReplacementKind.Prefix:
return String.Format ("prefix: {0} => {1}", Pattern, Replace);
case ReplacementKind.Regex:
return String.Format ("regex: {0} => {1}", Pattern, Replace);
default:
return String.Format ("unknown: {0} => {1}", Pattern, Replace);
}
}
}
public class ReplacementCollection : IEnumerable<Replacement>
{
public ReplacementContext Context { get; private set; }
public ReplacementCollection (ReplacementContext context)
{
Context = context;
}
List<Replacement> list = new List<Replacement> ();
public void Add (string pattern, string replace)
{
Add (Replacement.Parse (pattern, replace));
}
public void Add (Replacement replacement)
{
replacement.Context = Context;
list.Add (replacement);
}
public void AddRange (IEnumerable<Replacement> replacements)
{
foreach (var replacement in replacements)
Add (replacement);
}
public bool Evaluate (string input, out string replacement)
{
foreach (var item in list) {
if (item.Evaluate (input, out replacement))
return true;
}
replacement = null;
return false;
}
public int Count {
get { return list.Count; }
}
public IEnumerator<Replacement> GetEnumerator ()
{
foreach (var item in list)
yield return item;
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
}
}