Skip to content

Instantly share code, notes, and snippets.

@am11
Last active January 3, 2016 10:59
Show Gist options
  • Save am11/8452906 to your computer and use it in GitHub Desktop.
Save am11/8452906 to your computer and use it in GitHub Desktop.
Ancestry Manager for WE
// Note: We must have an option set to false for this kind of feature,
// unless there is better -- less expensive -- way to do detect cycles while walking.
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSS.Editor;
using Microsoft.Web.Editor;
//public class Importer//: HypotheticalVsShellClass
//{
// ...
// private AncestryManager _lessImportTree = new AncestryManager(LessCompiler, "LESS");
// public AncestryManager LessImportTree { get { return _lessImportTree; } }
// ProjectLoaded += LessImportTree.Initialize ();
// FileSaved += delegate { LessImportTree.UpdateDependents (FilePath) };
// ...
//}
internal class AncestryManager
{
private ICompiler _compiler;
private readonly object _compile = new object();
private List<ImportNode> _nodes;
private string _serviceName;
internal bool IsLoaded { get; private set; }
internal AncestryManager(ICompiler compiler, string serviceName)
{
_compiler = compiler;
_serviceName = serviceName;
IsLoaded = false;
}
//<summary>Collect items of type ServiceName</summary>
internal void Initialize()
{
// Where proj.DTE.Documents.Item(<counter>).Language == ServiceName
// [Recursively iterate all nested folders recursively? AND / OR HOW exactly?]
IEnumerable<IDocumentReference> documents = ProjectHelpers.GetAllSourceDocumentReferences(_serviceName);
foreach (var document in documents)
{
var node = new ImportNode(document);
node.Initialize();
_nodes.Add(node);
}
IsLoaded = true;
}
internal void UpdateDependents(string FilePath)
{
lock (_compile)
{
if (!IsLoaded)
return;
var importNode = _nodes.Where(n => n.DocumentFilePath == FilePath).First();
// last check is for reassurance; may be ommitted
if (importNode == null ||
!ImportNode.GetImports(importNode.SourceReference).SequenceEqual(importNode.Imports))
return;
// Walk once
foreach (IDocumentReference documentReference in importNode.Children)
{
_compiler.Compile(TextBufferExtensions.GetFileName(documentReference.TextBuffer));
}
}
}
private class ImportNode
{
private List<DocumentState> _children = new List<DocumentState>();
// for reassurance check in UpdateBranch.ImportsAncestoryManager; cascade omiision
private List<IDocumentReference> _imports = new List<IDocumentReference>();
// For retrieval
public string DocumentFilePath { get; set; }
public IDocumentReference SourceReference { get; set; }
public List<DocumentState> Children { get { return this._children; } }
// for reassurance check in UpdateBranch.ImportsAncestoryManager; cascade omiision
public List<IDocumentReference> Imports { get { return this._imports; } }
public ImportNode(IDocumentReference sourceReference)
{
this.DocumentFilePath = TextBufferExtensions.GetFileName(sourceReference.TextBuffer);
this.SourceReference = sourceReference;
this._imports = GetImports(sourceReference);
}
public void Initialize()
{
WalkDown(new DocumentState() { DocumentReference = SourceReference, IsWalked = true });
}
public void WalkDown(DocumentState document)
{
if (Children.Any(c => c.DocumentReference == document && c.IsWalked))
return;
this.Children.Add(document);
foreach (var relative in GetImports(document.DocumentReference))
{
WalkDown(new DocumentState() { DocumentReference = relative, IsWalked = true });
}
}
public static List<IDocumentReference> GetImports(IDocumentReference document)
{
return CssDocumentHelpers.DocumentImportManager.GetImports(
CssEditorDocument.FromTextBuffer(document.TextBuffer).Tree.StyleSheet
).ToList();
}
private class DocumentState
{
public IDocumentReference DocumentReference { get; set; }
public bool IsWalked { get; set; }
public DocumentState()
{
IsWalked = false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment