/CSEdit/F12Anywhere/F12AnywherePackage.cs
C# | 315 lines | 249 code | 48 blank | 18 comment | 52 complexity | db26e344bc137fb9495b0b6934b6a29f MD5 | raw file
- using System;
- using System.Linq;
- using System.Diagnostics;
- using System.Globalization;
- using System.Runtime.InteropServices;
- using System.ComponentModel.Design;
- using Microsoft.Win32;
- using Microsoft.VisualStudio;
- using Microsoft.VisualStudio.Shell.Interop;
- using Microsoft.VisualStudio.OLE.Interop;
- using Microsoft.VisualStudio.Shell;
- using CSUtilities;
- using CSParse;
- using System.IO;
- using CSStore;
- using EnvDTE;
- using Microsoft.VisualStudio.Text.Editor;
- using Microsoft.VisualStudio.TextManager.Interop;
- using Microsoft.VisualStudio.Editor;
- using System.Collections.Generic;
-
- namespace F12Anywhere
- {
- /// <summary>
- /// The main F12Anywhere package.
- /// </summary>
- // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is a package.
- [PackageRegistration(UseManagedResourcesOnly = true)]
- // This attribute is used to register the informations needed to show the this package in the Help/About dialog of Visual Studio.
- [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
- // This attribute is needed to let the shell know that this package exposes some menus.
- [ProvideMenuResource("Menus.ctmenu", 1)]
- [Guid(GuidList.guidF12AnywherePkgString)]
- public sealed class F12AnywherePackage : Package
- {
- /// <summary>
- /// Default constructor of the package. Place for non-VS dependent initialization.
- /// </summary>
- public F12AnywherePackage()
- {
- }
-
- #region Package Logic
-
- /// <summary>
- /// Initialization of the package; Place for all VS dependent initialization.
- /// </summary>
- protected override void Initialize()
- {
- base.Initialize();
-
- OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
- if (null != mcs)
- {
- CommandID menuCommandID = new CommandID(GuidList.guidF12AnywhereCmdSet, (int)PkgCmdIDList.cmdidF12Anywhere);
- MenuCommand gotoMenuItem = new MenuCommand(F12Execute, menuCommandID );
- mcs.AddCommand(gotoMenuItem);
-
- CommandID indexCommandID = new CommandID(GuidList.guidF12AnywhereCmdSet, (int)PkgCmdIDList.cmdidCSIndex);
- MenuCommand indexMenuItem = new MenuCommand(IndexExecute, indexCommandID);
- mcs.AddCommand(indexMenuItem);
- }
- }
-
-
- private DTE dte;
- public DTE Dte
- {
- get
- {
- if (dte == null)
- {
- dte = (DTE)this.GetService(typeof(SDTE));
- }
-
- return dte;
- }
- }
-
- private IWpfTextView GetCurrentTextView()
- {
- IVsTextManager textMgr = (IVsTextManager)GetService(typeof(SVsTextManager));
-
- IVsTextView textView;
- textMgr.GetActiveView(0, null, out textView);
-
- IVsUserData userData = textView as IVsUserData;
- if (userData == null)
- return null;
-
- object holder;
- Guid guidViewHost = DefGuidList.guidIWpfTextViewHost;
- userData.GetData(ref guidViewHost, out holder);
-
- IWpfTextViewHost viewHost = (IWpfTextViewHost)holder;
-
- return viewHost.TextView;
- }
-
- #endregion
-
- #region F12 Logic
-
- private CodeStore store; //= new CodeStore("C:\\Users\\Durham\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication1\\index.txt"); // TODO: point at a index
-
- /// <summary>
- /// Executes an F12 on the active window.
- /// </summary>
- private void F12Execute(object sender, EventArgs e)
- {
- if (store == null)
- {
- IndexExecute(null, null);
- }
-
- IWpfTextView textView = this.GetCurrentTextView();
-
- if (textView != null)
- {
- string data = textView.TextSnapshot.GetText();
- FileNode fileNode = RetrieveFileNode(data);
-
- int caretLocation = textView.Caret.Position.BufferPosition.Position;
- Token foundLocation;
- QualifiedIdentifier id = FindIdAtLocation(fileNode, caretLocation, out foundLocation);
-
- if (foundLocation != null)
- {
- GoTo(foundLocation);
- }
- else if (id != null)
- {
- // Clear out generics since we're wanting to go to a declaration
- if (id.Children.Count > 0)
- {
- id = QualifiedIdentifier.Parse(id.ToGenericString());
- }
-
- GoToId(id);
- }
- }
- }
-
- private FileNode RetrieveFileNode(string data)
- {
- FileNode fileNode = FileParser.Parse(data, true);
- Resolver.ResolveReferences(fileNode, store);
-
- return fileNode;
- }
-
- private QualifiedIdentifier FindIdAtLocation(FileNode file, int location, out Token foundLocation)
- {
- foundLocation = null;
-
- FinderVisitor finder = new FinderVisitor(location);
- finder.Visit(file);
- CSParse.Expression foundExpr = finder.FoundExpression;
- CSParse.Reference foundRef = finder.FoundReference;
-
- if (foundRef == null && foundExpr != null)
- {
- MemberExpression memberExpression = foundExpr as MemberExpression;
- LocalExpression localExpression = foundExpr as LocalExpression;
- if (memberExpression != null)
- {
- foundRef = memberExpression.Member.Name;
- }
- else if (localExpression != null)
- {
- IdentifierExpression variable;
- if (localExpression.Declaration != null)
- {
- variable = localExpression.Declaration.Variables.FirstOrDefault(v => v.Id.ToShortString() == localExpression.Variable);
- }
- else // parameter
- {
- variable = localExpression.Parameter.Variable;
- }
- foundLocation = variable.EndToken;
- }
- }
- else if (foundRef != null)
- {
- // Find sub reference
-
- }
-
- return foundRef != null ? foundRef.Id : null;
- }
-
- private void GoToId(QualifiedIdentifier id)
- {
- TypeNode type = GetType(id);
- if (type != null)
- {
- Window newWindow = Dte.ItemOperations.OpenFile(type.Path);
- TextSelection newSelection = newWindow.Selection as TextSelection;
- // TODO figure out how to get the newly opened window.
- if (newSelection != null)
- {
- FileNode targetFileNode = RetrieveFileNode(this.GetCurrentTextView().TextSnapshot.GetText());
- Reference targetReference = GetReference(targetFileNode, id);
- if (targetReference != null)
- {
- newSelection.MoveToAbsoluteOffset(targetReference.Start.StartPos - targetReference.Start.LineNumber + 2);
- }
- }
- }
- }
-
- private void GoTo(Token target)
- {
- Window window = Dte.ActiveWindow;
- TextSelection newSelection = window.Selection as TextSelection;
- if (newSelection != null)
- {
- newSelection.MoveToAbsoluteOffset(target.StartPos - target.LineNumber + 2);
- }
- }
-
- private TypeNode GetType(QualifiedIdentifier id)
- {
- TypeNode type = null;
- while (type == null && id != null)
- {
- type = store.GetType(id);
- id = id.Qualifier;
- }
-
- return type;
- }
-
- private Reference GetReference(FileNode file, QualifiedIdentifier id)
- {
- Reference targetReference = TypeVisitor.GetTypes(file).Where(t => t.Name.Id == id).Select(t => t.Name).FirstOrDefault();
- if (targetReference != null)
- {
- return targetReference;
- }
-
- targetReference = MemberVisitor.GetMembers(file).Where(m => m.Name.Id == id).Select(m => m.Name).FirstOrDefault();
-
- return targetReference;
- }
- #endregion
-
- #region Index
-
- private void IndexExecute(object sender, EventArgs args)
- {
- List<FileNode> files = ParseFiles(GetFiles().Where(f => f.EndsWith(".cs"))).ToList();
-
- CodeStore declarationStore = new CodeStore();
- declarationStore.AddTypes(TypeVisitor.GetTypes(files));
-
- foreach (FileNode file in files)
- {
- Resolver.ResolveDeclarations(file, declarationStore);
- }
-
- store = new CodeStore();
- store.AddTypes(TypeVisitor.GetTypes(files));
- }
-
- private IEnumerable<FileNode> ParseFiles(IEnumerable<string> files)
- {
- foreach (string file in files)
- {
- FileNode fileNode = null;
- try
- {
- Console.WriteLine("Parsing " + file);
- string data = File.ReadAllText(file);
- fileNode = FileParser.Parse(data, false);
- fileNode.Path = file;
-
- foreach (TypeNode type in TypeVisitor.GetTypes(fileNode))
- {
- type.Path = file;
- }
- }
- catch (InvalidParseSource ex)
- {
- Console.WriteLine(ex.Message);
- }
-
- if (fileNode != null)
- {
- yield return fileNode;
- }
- }
- }
-
- private IEnumerable<string> GetFiles()
- {
- foreach (Project project in this.Dte.Solution.Projects)
- {
- Queue<ProjectItem> projectItems = new Queue<ProjectItem>(project.ProjectItems.OfType<ProjectItem>());
- while (projectItems.Count > 0)
- {
- ProjectItem item = projectItems.Dequeue();
- yield return item.FileNames[0];
-
- foreach (ProjectItem subItem in item.ProjectItems)
- {
- projectItems.Enqueue(subItem);
- }
- }
- }
- }
-
- #endregion
- }
- }