From 3a4950f22300e034f97b992a0c2bf29f4b875465 Mon Sep 17 00:00:00 2001 From: Adeel Date: Sun, 22 Dec 2013 12:08:43 +0300 Subject: [PATCH 1/2] LESS: Fixes source map path issues & refactoring. --- EditorExtensions/CodeAnalysis.ruleset | 1 - EditorExtensions/Margin/LessCompiler.cs | 7 +-- EditorExtensions/Margin/LessMargin.cs | 57 +++++++++++++------ .../Margin/LessProjectCompiler.cs | 8 +-- EditorExtensions/Margin/MarginBase.cs | 15 ++--- .../Tests/LESS/LessCompilationTests.cs | 3 +- 6 files changed, 51 insertions(+), 40 deletions(-) diff --git a/EditorExtensions/CodeAnalysis.ruleset b/EditorExtensions/CodeAnalysis.ruleset index f8815f0d6..c35609018 100644 --- a/EditorExtensions/CodeAnalysis.ruleset +++ b/EditorExtensions/CodeAnalysis.ruleset @@ -2,7 +2,6 @@ - diff --git a/EditorExtensions/Margin/LessCompiler.cs b/EditorExtensions/Margin/LessCompiler.cs index 6a485f95c..f91656ec8 100644 --- a/EditorExtensions/Margin/LessCompiler.cs +++ b/EditorExtensions/Margin/LessCompiler.cs @@ -19,15 +19,14 @@ public static class LessCompiler private static readonly string node = Path.Combine(webEssentialsNodeDir, @"node.exe"); private static readonly Regex errorParser = new Regex(@"^(.+) in (.+) on line (\d+), column (\d+):$", RegexOptions.Multiline); - public static async Task Compile(string fileName, string targetFileName = null, string sourceMapRootPath = null) + public static async Task Compile(string fileName, string targetFileName = null) { string output = Path.GetTempFileName(); string arguments = String.Format("--no-color --relative-urls \"{0}\" \"{1}\"", fileName, output); - string fileNameWithoutPath = Path.GetFileName(fileName); - string sourceMapArguments = (string.IsNullOrEmpty(sourceMapRootPath)) ? "" : String.Format("--source-map-rootpath=\"{0}\" ", sourceMapRootPath.Replace("\\", "/")); if (WESettings.GetBoolean(WESettings.Keys.LessSourceMaps)) - arguments = String.Format("--no-color --relative-urls {0}--source-map=\"{1}.map\" \"{2}\" \"{3}\"", sourceMapArguments, fileNameWithoutPath, fileName, output); + arguments = String.Format("--no-color --relative-urls --source-map=\"{0}.map\" \"{1}\" \"{2}\"", + targetFileName, fileName, output); ProcessStartInfo start = new ProcessStartInfo(String.Format("\"{0}\" \"{1}\"", (File.Exists(node)) ? node : "node", lessCompiler)) { diff --git a/EditorExtensions/Margin/LessMargin.cs b/EditorExtensions/Margin/LessMargin.cs index 1b9bbc522..db3332d63 100644 --- a/EditorExtensions/Margin/LessMargin.cs +++ b/EditorExtensions/Margin/LessMargin.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -12,6 +13,7 @@ namespace MadsKristensen.EditorExtensions public class LessMargin : MarginBase { public const string MarginName = "LessMargin"; + private static readonly Regex _sourceMapinCSS = new Regex(@"\/\*#([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/", RegexOptions.Multiline); public LessMargin(string contentType, string source, bool showMargin, ITextDocument document) : base(source, MarginName, contentType, showMargin, document) @@ -34,7 +36,7 @@ protected override async void StartCompiler(string source) Logger.Log("LESS: Compiling " + Path.GetFileName(lessFilePath)); - var result = await LessCompiler.Compile(lessFilePath, cssFilename, Path.GetDirectoryName(lessFilePath)); + var result = await LessCompiler.Compile(lessFilePath, cssFilename); if (result.IsSuccess) { @@ -96,37 +98,56 @@ protected override bool CanWriteToDisk(string source) return true;// !string.IsNullOrWhiteSpace(stylesheet.Text); } - protected override string UpdateLessSourceMapUrls(string content, string oldFileName, string newFileName) + protected override string UpdateLessSourceMapUrls(string content, string sourceFileName, string compiledFileName) { if (!WESettings.GetBoolean(WESettings.Keys.LessSourceMaps)) return content; - dynamic jsonSourceMap = null; - string sourceMapFilename = oldFileName + ".map"; - // Read JSON map file and deserialize. - string sourceMapContents = File.ReadAllText(sourceMapFilename); - jsonSourceMap = Json.Decode(sourceMapContents); + string sourceMapFilename = compiledFileName + ".map"; - if (jsonSourceMap == null) + if (!File.Exists(sourceFileName)) + return content; + + var updatedFileContent = GetUpdatedSourceMapFileContent(sourceFileName, compiledFileName, sourceMapFilename); + + if (updatedFileContent == null) return content; - string projectRoot = ProjectHelpers.GetRootFolder(ProjectHelpers.GetActiveProject()); - string cssNetworkPath = FileHelpers.RelativePath(oldFileName, newFileName); - string sourceMapRelativePath = FileHelpers.RelativePath(oldFileName, sourceMapFilename); + WriteFile(updatedFileContent, sourceMapFilename, true, false); + + return UpdateSourceLinkInCssComment(content, FileHelpers.RelativePath(sourceMapFilename, sourceFileName)); + } + + private static string GetUpdatedSourceMapFileContent(string lessFileName, string cssFileName, string sourceMapFilename) + { + // Read JSON map file and deserialize. + dynamic jsonSourceMap = Json.Decode(File.ReadAllText(sourceMapFilename)); + + if (jsonSourceMap == null) + return null; - jsonSourceMap.sources = new List(jsonSourceMap.sources); + jsonSourceMap.sources = UpdateSourcePaths(new List(jsonSourceMap.sources), cssFileName, lessFileName); jsonSourceMap.names = new List(jsonSourceMap.names); - jsonSourceMap.file = cssNetworkPath; + jsonSourceMap.file = FileHelpers.RelativePath(lessFileName, cssFileName); - for (int i = 0; i < jsonSourceMap.sources.Count; ++i) + return Json.Encode(jsonSourceMap); + } + + private static List UpdateSourcePaths(List sources, string cssFileName, string lessFileName) + { + for (int i = 0; i < sources.Count; ++i) { - jsonSourceMap.sources[i] = FileHelpers.RelativePath(newFileName, projectRoot + jsonSourceMap.sources[i]); + sources[i] = FileHelpers.RelativePath(cssFileName, + File.Exists(sources[i]) ? sources[i] : lessFileName); } - WriteFile(Json.Encode(jsonSourceMap), sourceMapFilename, File.Exists(sourceMapFilename), false); + return sources; + } - // Fixed sourceMappingURL comment in CSS file with network accessible path. - return Regex.Replace(content, @"\/\*#([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/", "/*# sourceMappingURL=" + sourceMapRelativePath + "*/"); + private static string UpdateSourceLinkInCssComment(string content, string sourceMapRelativePath) + { // Fixed sourceMappingURL comment in CSS file with network accessible path. + return _sourceMapinCSS.Replace(content, + String.Format(CultureInfo.CurrentCulture, "/*# sourceMappingURL={0} */", sourceMapRelativePath)); } } } \ No newline at end of file diff --git a/EditorExtensions/Margin/LessProjectCompiler.cs b/EditorExtensions/Margin/LessProjectCompiler.cs index 9cbbb24ed..8bbd835a0 100644 --- a/EditorExtensions/Margin/LessProjectCompiler.cs +++ b/EditorExtensions/Margin/LessProjectCompiler.cs @@ -19,18 +19,14 @@ public static void CompileProject(Project project) private static async Task Compile(Project project) { - string projectRoot = ProjectHelpers.GetRootFolder(project); - var files = Directory.EnumerateFiles(projectRoot, "*.less", SearchOption.AllDirectories).Where(CanCompile); - string fileBasePath = string.Empty; + var files = Directory.EnumerateFiles(ProjectHelpers.GetRootFolder(project), "*.less", SearchOption.AllDirectories).Where(CanCompile); if (!files.Any()) return; - fileBasePath = "/" + Path.GetDirectoryName(FileHelpers.RelativePath(projectRoot, files.First())).Replace("\\", "/"); - foreach (string file in files) { string cssFileName = MarginBase.GetCompiledFileName(file, ".css", WESettings.GetString(WESettings.Keys.LessCompileToLocation)); - var result = await LessCompiler.Compile(file, cssFileName, projectRoot + fileBasePath); + var result = await LessCompiler.Compile(file, cssFileName); if (result.IsSuccess) WriteResult(result, cssFileName); diff --git a/EditorExtensions/Margin/MarginBase.cs b/EditorExtensions/Margin/MarginBase.cs index 53b295ec1..3e68e1084 100644 --- a/EditorExtensions/Margin/MarginBase.cs +++ b/EditorExtensions/Margin/MarginBase.cs @@ -254,11 +254,10 @@ protected string WriteCompiledFile(string content, string currentFileName) return string.Empty; } - bool fileExist = File.Exists(fileName); - bool fileWritten = false; - ProjectHelpers.CheckOutFileFromSourceControl(fileName); - fileWritten = WriteFile(content, fileName, fileExist, fileWritten); + + bool fileExist = File.Exists(fileName); + bool fileWritten = WriteFile(content, fileName, fileExist, false); if (!fileExist && fileWritten) { @@ -268,16 +267,14 @@ protected string WriteCompiledFile(string content, string currentFileName) return content; } - protected virtual string UpdateLessSourceMapUrls(string content, string oldFileName, string newFileName) - { - // If not overridden by derived, return content as is. + protected virtual string UpdateLessSourceMapUrls(string content, string sourceFileName, string compiledFileName) + { // If not overridden by derived, return content as is. return content; } public static string GetCompiledFileName(string sourceFileName, string compiledExtension, string customFolder) { - string sourceExtension = Path.GetExtension(sourceFileName); - string compiledFileName = Path.GetFileName(sourceFileName).Replace(sourceExtension, compiledExtension); + string compiledFileName = Path.GetFileName(Path.ChangeExtension(sourceFileName, compiledExtension)); string sourceDir = Path.GetDirectoryName(sourceFileName); string compiledDir; string rootDir = ProjectHelpers.GetRootFolder(); diff --git a/WebEssentialsTests/Tests/LESS/LessCompilationTests.cs b/WebEssentialsTests/Tests/LESS/LessCompilationTests.cs index 0c46c85b7..6e3fd7e50 100644 --- a/WebEssentialsTests/Tests/LESS/LessCompilationTests.cs +++ b/WebEssentialsTests/Tests/LESS/LessCompilationTests.cs @@ -18,8 +18,7 @@ public class LessCompilationTests #region Helper Methods private static async Task CompileLess(string fileName, string targetFilename = null) { - string siteMapPath = "/" + Path.GetDirectoryName(FileHelpers.RelativePath(BaseDirectory, fileName)).Replace("\\", "/"); - var result = await LessCompiler.Compile(fileName, targetFilename, siteMapPath); + var result = await LessCompiler.Compile(fileName, targetFilename); if (result.IsSuccess) { From de43b9780a993f544a2264f4cbdbf5a775121ac3 Mon Sep 17 00:00:00 2001 From: Adeel Date: Sun, 22 Dec 2013 16:19:56 +0300 Subject: [PATCH 2/2] Analysis: (CA1002) Do not expose generic lists. --- .../BrowserLink/PixelPushing/PixelPushingMode.cs | 2 +- EditorExtensions/BrowserLink/UnusedCss/RawRuleUsage.cs | 2 +- EditorExtensions/BrowserLink/UnusedCss/SessionResult.cs | 2 +- .../BrowserLink/UnusedCss/UnusedCssExtension.cs | 4 ++-- EditorExtensions/Commands/Code/IntellisenseWriter.cs | 7 ++++++- .../Commands/Code/ScriptIntellisenseListener.cs | 7 +++---- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/EditorExtensions/BrowserLink/PixelPushing/PixelPushingMode.cs b/EditorExtensions/BrowserLink/PixelPushing/PixelPushingMode.cs index ad12266bb..cc7b22d71 100644 --- a/EditorExtensions/BrowserLink/PixelPushing/PixelPushingMode.cs +++ b/EditorExtensions/BrowserLink/PixelPushing/PixelPushingMode.cs @@ -45,7 +45,7 @@ public static bool IsPixelPushingModeEnabled } } } - public static List IgnoreList + public static IEnumerable IgnoreList { get { diff --git a/EditorExtensions/BrowserLink/UnusedCss/RawRuleUsage.cs b/EditorExtensions/BrowserLink/UnusedCss/RawRuleUsage.cs index 8194f9258..a55c9eb65 100644 --- a/EditorExtensions/BrowserLink/UnusedCss/RawRuleUsage.cs +++ b/EditorExtensions/BrowserLink/UnusedCss/RawRuleUsage.cs @@ -9,7 +9,7 @@ public class RawRuleUsage : IEquatable [JsonProperty] public string Selector { get; set; } [JsonProperty] - public List SourceLocations { get; private set; } + public IEnumerable SourceLocations { get; private set; } public RawRuleUsage() { diff --git a/EditorExtensions/BrowserLink/UnusedCss/SessionResult.cs b/EditorExtensions/BrowserLink/UnusedCss/SessionResult.cs index ae157d601..80bf446a1 100644 --- a/EditorExtensions/BrowserLink/UnusedCss/SessionResult.cs +++ b/EditorExtensions/BrowserLink/UnusedCss/SessionResult.cs @@ -18,7 +18,7 @@ public class SessionResult : IUsageDataSource, IResolutionRequiredDataSource [JsonProperty] public bool Continue { get; set; } [JsonProperty] - public List Sheets { get; private set; } + public IEnumerable Sheets { get; private set; } public IEnumerable AllRules { diff --git a/EditorExtensions/BrowserLink/UnusedCss/UnusedCssExtension.cs b/EditorExtensions/BrowserLink/UnusedCss/UnusedCssExtension.cs index 3a7e1a082..0965cef55 100644 --- a/EditorExtensions/BrowserLink/UnusedCss/UnusedCssExtension.cs +++ b/EditorExtensions/BrowserLink/UnusedCss/UnusedCssExtension.cs @@ -21,13 +21,13 @@ public class UnusedCssExtension : BrowserLinkExtension public static bool IsAnyConnectionAlive { get { return ExtensionByConnection.Count > 0; } } public BrowserLinkConnection Connection { get { return _connection; } } public bool IsRecording { get; private set; } - public static List IgnoreList + public static IEnumerable IgnoreList { get { var ignorePatterns = WESettings.GetString(WESettings.Keys.UnusedCss_IgnorePatterns) ?? ""; - return ignorePatterns.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList(); + return ignorePatterns.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()); } } private static List IgnorePatternList diff --git a/EditorExtensions/Commands/Code/IntellisenseWriter.cs b/EditorExtensions/Commands/Code/IntellisenseWriter.cs index 3f797f7f4..0d08991c8 100644 --- a/EditorExtensions/Commands/Code/IntellisenseWriter.cs +++ b/EditorExtensions/Commands/Code/IntellisenseWriter.cs @@ -164,12 +164,17 @@ public class IntellisenseObject public string FullName { get; set; } public bool IsEnum { get; set; } public string Summary { get; set; } - public List Properties { get; private set; } + public IList Properties { get; private set; } public IntellisenseObject() { Properties = new List(); } + + public IntellisenseObject(IList properties) + { + Properties = properties; + } } public class IntellisenseProperty diff --git a/EditorExtensions/Commands/Code/ScriptIntellisenseListener.cs b/EditorExtensions/Commands/Code/ScriptIntellisenseListener.cs index 7584fb428..c1e9fd21e 100644 --- a/EditorExtensions/Commands/Code/ScriptIntellisenseListener.cs +++ b/EditorExtensions/Commands/Code/ScriptIntellisenseListener.cs @@ -163,11 +163,11 @@ private static void ProcessEnum(CodeEnum element, List list) private static void ProcessClass(CodeClass cc, List list) { - var props = GetProperties(cc.Members, new HashSet()).ToList(); + var properties = GetProperties(cc.Members, new HashSet()).ToList(); - if (props.Any()) + if (properties.Any()) { - var intellisenseObject = new IntellisenseObject + var intellisenseObject = new IntellisenseObject(properties) { Namespace = GetNamespace(cc), Name = cc.Name, @@ -175,7 +175,6 @@ private static void ProcessClass(CodeClass cc, List list) Summary = GetSummary(cc), }; - intellisenseObject.Properties.AddRange(props); list.Add(intellisenseObject); } }