Skip to content
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

Optionally show source context next to reference paths & line numbers #268

Merged
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
64 changes: 64 additions & 0 deletions src/i18n.Domain.Tests/PathNormalizerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.IO;
using i18n.Domain.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace i18n.Domain.Tests
{
[TestClass]
public class PathNormalizerTests
{
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MakeRelativePath_InvalidPath_Throws()
{
var anchorPath = string.Empty;
PathNormalizer.MakeRelativePath(anchorPath, null);
}

[TestMethod]
public void MakeRelativePath_NullOrEmptyAnchorPath_ReturnsPath()
{
var path = @"C:\some\path\file.ext";

AssertNormalizedPath(null, path, path, "Null anchor path");
AssertNormalizedPath(string.Empty, path, path, "Empty anchor path");
}

private static void AssertNormalizedPath(string anchorPath, string path, string expected, string reason)
{
var actual = PathNormalizer.MakeRelativePath(anchorPath, path);

Assert.AreEqual(expected, actual, reason);
}

[TestMethod]
public void MakeRelativePath_SimpleRelativePath_ReturnsRelativePath()
{
var anchorPath = @"C:\Some\Path";
var relativePath = @"Another\Nested\File.ext";
var path = Path.Combine(anchorPath, relativePath);

AssertNormalizedPath(anchorPath, path, relativePath, "Simple relative path");
}

[TestMethod]
public void MakeRelativePath_NoCommonPortion_ReturnsPath()
{
var anchorPath = @"C:\Some\Path";
var path = @"D:\Some\Other\Path";
AssertNormalizedPath(anchorPath, path, path, "No common path portion");
}

[TestMethod]
public void MakeRelativePath_SomeCommonPorths_ReturnsRelativePath()
{
var commonPath = @"C:\Some\Common\Path";
var anchorPath = Path.Combine(commonPath, @"Anchor\Path");
var distinctPath = @"Distinct\Path\File.ext";
var path = Path.Combine(commonPath, distinctPath);
var relativePath = Path.Combine(@"..\..", distinctPath);
AssertNormalizedPath(anchorPath, path, relativePath, "Some common path components");
}
}
}
65 changes: 65 additions & 0 deletions src/i18n.Domain.Tests/ReferenceContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using i18n.Domain.Entities;
using i18n.Domain.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace i18n.Domain.Tests
{
[TestClass]
public class ReferenceContextTests
{
private const string Path = @"C:\Some\Path\File.ext";
private const string Content =
// 0 1 2 3 4 5
// 0123456789 0 12345678901 2 345678901234567890 1 234567890123456789
"The quick\r\n brown fox\r\n jumps over the lazy \r\ndog";

[TestMethod]
public void Create_PositionTooSmall_ReturnsFirstLine()
{
AssertExpectedContext(-10, CreateExpected("The quick", 1), "Position too small");
}

[TestMethod]
public void Create_WithOutOfRangePosition_ReturnsLastLineWithNoContext()
{
AssertExpectedContext(Content.Length + 10, CreateExpected(string.Empty, 4), "Position too big");
}

[TestMethod]
public void Create_PositionInFirstLine_ReturnsFirstLine()
{
AssertExpectedContext(2, CreateExpected("The quick", 1), "Position in first line");
}

[TestMethod]
public void Create_PositionInThirdLine_ReturnsThirdLine()
{
AssertExpectedContext(23, CreateExpected("jumps over the lazy", 3), "Position in 3rd line");
}

[TestMethod]
public void Create_PositionInLastLine_ReturnsLastLine()
{
AssertExpectedContext(46, CreateExpected("dog", 4), "Position in last line");
}

private static ReferenceContext CreateExpected(string context, int lineNumber)
{
return new ReferenceContext
{
Path = Path,
LineNumber = lineNumber,
Context = context
};
}

private static void AssertExpectedContext(int position, ReferenceContext expected, string reason)
{
var actual = ReferenceContext.Create(Path, Content, position);

Assert.AreEqual(expected.Path, actual.Path, "Path: " + reason);
Assert.AreEqual(expected.LineNumber, actual.LineNumber, "LineNumber: " + reason);
Assert.AreEqual(expected.Context, actual.Context, "Context:" + reason);
}
}
}
2 changes: 2 additions & 0 deletions src/i18n.Domain.Tests/i18n.Domain.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
</Choose>
<ItemGroup>
<Compile Include="NuggetTests.cs" />
<Compile Include="PathNormalizerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="NuggetParserTests.cs" />
<Compile Include="ReferenceContextTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\i18n.Domain\i18n.Domain.csproj">
Expand Down
31 changes: 13 additions & 18 deletions src/i18n.Domain/Concrete/FileNuggetFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,18 @@ public IDictionary<string, TemplateItem> ParseAll()

private void ParseFile(string projectDirectory, string filePath, ConcurrentDictionary<string, TemplateItem> templateItems)
{
var referencePath = (projectDirectory != null) && filePath.StartsWith(projectDirectory, StringComparison.OrdinalIgnoreCase)
? filePath.Substring(projectDirectory.Length + 1)
: filePath;
var referencePath = PathNormalizer.MakeRelativePath(projectDirectory, filePath);

DebugHelpers.WriteLine("FileNuggetFinder.ParseFile -- {0}", filePath);
// Lookup any/all nuggets in the file and for each add a new template item.
using (var fs = File.OpenText(filePath))
{
_nuggetParser.ParseString(fs.ReadToEnd(), delegate(string nuggetString, int pos, Nugget nugget, string i_entity)
{
var referenceContext = ReferenceContext.Create(referencePath, i_entity, pos);

AddNewTemplateItem(
referencePath,
i_entity.LineFromPos(pos),
referenceContext,
nugget,
templateItems);
// Done.
Expand All @@ -123,13 +122,11 @@ private void ParseFile(string projectDirectory, string filePath, ConcurrentDicti
}
}

private void AddNewTemplateItem(
string filePath,
int lineNumber,
private void AddNewTemplateItem(
ReferenceContext referenceContext,
Nugget nugget,
ConcurrentDictionary<string, TemplateItem> templateItems)
{
string reference = filePath + ":" + lineNumber.ToString();
{
string msgid = nugget.MsgId.Replace("\r\n", "\n").Replace("\r", "\\n");
// NB: In memory msgids are normalized so that LFs are converted to "\n" char sequence.
string key = TemplateItem.KeyFromMsgidAndComment(msgid, nugget.Comment, _settings.MessageContextEnabledFromComment);
Expand All @@ -143,9 +140,7 @@ private void AddNewTemplateItem(
item.MsgKey = key;
item.MsgId = msgid;

tmpList = new List<string>();
tmpList.Add(reference);
item.References = tmpList;
item.References = new List<ReferenceContext> {referenceContext};

if (nugget.Comment.IsSet()) {
tmpList = new List<string>();
Expand All @@ -156,11 +151,11 @@ private void AddNewTemplateItem(
return item;
},
// Update routine.
(k, v) => {

tmpList = v.References.ToList();
tmpList.Add(reference);
v.References = tmpList;
(k, v) =>
{
var newReferences = new List<ReferenceContext>(v.References.ToList());
newReferences.Add(referenceContext);
v.References = newReferences;

if (nugget.Comment.IsSet()) {
tmpList = v.Comments != null ? v.Comments.ToList() : new List<string>();
Expand Down
21 changes: 11 additions & 10 deletions src/i18n.Domain/Concrete/POTranslationRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public void SaveTranslation(Translation translation)
foreach (var reference in item.References)
{
hasReferences = true;
stream.WriteLine("#: " + reference);
stream.WriteLine("#: " + reference.ToComment());
}
}

Expand Down Expand Up @@ -320,7 +320,7 @@ public void SaveTemplate(IDictionary<string, TemplateItem> items)

foreach (var reference in item.References)
{
stream.WriteLine("#: " + reference);
stream.WriteLine("#: " + reference.ToComment());
}

if (_settings.MessageContextEnabledFromComment
Expand Down Expand Up @@ -383,10 +383,10 @@ private Translation ParseTranslationFile(string langtag)
bool itemStarted = false;
while ((line = fs.ReadLine()) != null)
{
List<string> extractedComments = new List<string>();
List<string> translatorComments = new List<string>();
List<string> flags = new List<string>();
List<string> references = new List<string>();
var extractedComments = new List<string>();
var translatorComments = new List<string>();
var flags = new List<string>();
var references = new List<ReferenceContext>();

//read all comments, flags and other descriptive items for this string
//if we have #~ its a historical/log entry but it is the messageID/message so we skip this do/while
Expand All @@ -401,7 +401,7 @@ private Translation ParseTranslationFile(string langtag)
extractedComments.Add(line.Substring(2).Trim());
break;
case ':': //references
references.Add(line.Substring(2).Trim());
references.Add(ReferenceContext.Parse(line.Substring(2).Trim()));
break;
case ',': //flags
flags.Add(line.Substring(2).Trim());
Expand Down Expand Up @@ -435,9 +435,10 @@ private Translation ParseTranslationFile(string langtag)
// Update routine.
(k, v) => {
v.References = v.References.Append(item.References);
v.ExtractedComments = v.ExtractedComments.Append(item.References);
v.TranslatorComments = v.TranslatorComments.Append(item.References);
v.Flags = v.Flags.Append(item.References);
var referencesAsComments = item.References.Select(r => r.ToComment()).ToList();
v.ExtractedComments = v.ExtractedComments.Append(referencesAsComments);
v.TranslatorComments = v.TranslatorComments.Append(referencesAsComments);
v.Flags = v.Flags.Append(referencesAsComments);
return v;
});
}
Expand Down
83 changes: 83 additions & 0 deletions src/i18n.Domain/Entities/ReferenceContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.Text.RegularExpressions;

namespace i18n.Domain.Entities
{
public class ReferenceContext
{
public static bool ShowSourceContext { get; set; }

public string Path { get; set; }
public int LineNumber { get; set; }
public string Context { get; set; }

public static ReferenceContext Create(string path, string content, int position)
{
var lineNumber = 1;
var lineStartPosition = 0;
var context = string.Empty;

for (var i = 0; i < content.Length; i++)
{
if (content[i] == '\n')
{
lineNumber++;
lineStartPosition = i;
}

if (i < position) continue;

var lineEndPosition = content.IndexOf("\n", i, StringComparison.Ordinal);

if (lineEndPosition < 0)
{
lineEndPosition = content.Length;
}

context = content.Substring(lineStartPosition, lineEndPosition - lineStartPosition);
break;
}

return new ReferenceContext
{
Path = path,
LineNumber = lineNumber,
Context = context.Trim()
};
}

private static readonly Regex ReferenceRegex = new Regex(@"\s*(?<path>.*):(?<lineNumber>\d+)(?<context>.*)$", RegexOptions.Compiled);

public static ReferenceContext Parse(string line)
{
var match = ReferenceRegex.Match(line);

if (match.Success)
{
return new ReferenceContext
{
Path = match.Groups["path"].Value.Trim(),
LineNumber = Convert.ToInt32(match.Groups["lineNumber"].Value),
Context = match.Groups["context"].Value.Trim()
};
}

return new ReferenceContext
{
Path = line
};
}

public string ToComment()
{
var comment = Path + ":" + LineNumber;

if (ShowSourceContext)
{
comment += " " + Context;
}

return comment;
}
}
}
2 changes: 1 addition & 1 deletion src/i18n.Domain/Entities/TemplateItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class TemplateItem
{
public string MsgKey;
public string MsgId;
public IEnumerable<string> References { get; set; }
public IEnumerable<ReferenceContext> References { get; set; }
public IEnumerable<string> Comments { get; set; }

public override string ToString()
Expand Down
2 changes: 1 addition & 1 deletion src/i18n.Domain/Entities/TranslationItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class TranslationItem
public string MsgKey { get; set; }
public string MsgId { get; set; }
public string Message { get; set; }
public IEnumerable<string> References { get; set; }
public IEnumerable<ReferenceContext> References { get; set; }
public IEnumerable<string> ExtractedComments { get; set; }
public IEnumerable<string> TranslatorComments { get; set; }
public IEnumerable<string> Flags { get; set; }
Expand Down
Loading