[svn] r6901: vs-plugin/trunk:
Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/GotoInfo.n
Nemerle.Comp...
pbludov
svnadmin at nemerle.org
Wed Nov 15 12:51:59 CET 2006
Log:
Navigation is almost done!
Author: pbludov
Date: Wed Nov 15 12:51:54 2006
New Revision: 6901
Modified:
vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/GotoInfo.n
vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.Type.n
vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.n
vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.Designer.cs
vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.cs
vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleAuthoringScope.cs
vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs
Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/GotoInfo.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/GotoInfo.n (original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/GotoInfo.n Wed Nov 15 12:51:54 2006
@@ -27,20 +27,12 @@
SetLocation(member.Location);
unless (HasLocation)
- {
- if (member is IMethod)
- {
- // Methods are navigable through a .pdb
- //
- _member = member.GetHandle();
+ _member = member.GetHandle()
}
- else
+
+ public this(value : ClassMember)
{
- // TODO:
- // For fields: Lookup type, find ctor or any other method and go to it.
- // For properties & events: Go to getter/setter/adder/etc
- }
- }
+ SetLocation(value.Location);
}
public this(value : LocalValue)
@@ -61,12 +53,17 @@
_member = t.GetConstructor(Type.EmptyTypes);
}
+ public this(filePath : string, lineStart : int, colStart : int, lineEnd : int, colEnd : int)
+ {
+ SetLocation(filePath, lineStart, colStart, lineEnd, colEnd)
+ }
+
private SetLocation(location : Location) : void
{
SetLocation(location.File, location.Line, location.Column, location.EndLine, location.EndColumn)
}
- public SetLocation(filePath : string, lineStart : int, colStart : int, lineEnd : int, colEnd : int) : void
+ private SetLocation(filePath : string, lineStart : int, colStart : int, lineEnd : int, colEnd : int) : void
{
_filePath = filePath;
_lineStart = lineStart - 1;
@@ -89,11 +86,11 @@
public override ToString() : string
{
if (_lineEnd >= 0)
- string.Format("{0} {1}:{2} {3}:{4}", _filePath, _lineStart, _colStart, _lineEnd, _colEnd);
+ $"$_filePath $_lineStart:$_colStart $_lineEnd:$_colEnd"
else if (string.IsNullOrEmpty(_filePath))
- "<unknown>";
+ "<unknown>"
else
- _filePath;
+ _filePath
}
}
Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.Type.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.Type.n (original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.Type.n Wed Nov 15 12:51:54 2006
@@ -73,11 +73,6 @@
}
}
-
- // PB061114: Ìîæåò ÿâíî äîáàâèòü ïàòòåðíû TExpr.None è PExpr.None è
- // èñïîëüçîâàòü èõ âìåñòî null? Åù¸ âàðèàíò: èñïîëüçîâàòü option[TExpr] è option[PExpr]
- // VladD2: À ÷òî ìåøàåò âîçâðàùàòü ïðîñòî null-û äëÿ TExpr è PExpr? Òóò ÿâíî IT âîçâðàùåò íå òîëüêî TExpr è PExpr.
-
/// Finds an object by provided location.
/// Returns object location * associated Parsetree * associated Typedtree
private FindObject(
@@ -103,22 +98,23 @@
if (loc1.Intersect(loc2) == loc1) m1 else m2
});
- def checkType(ast, ty)
+ def checkType(pexpr, texpr)
{
- def ast_args =
- match (ast)
+ def pargs =
+ match (pexpr)
{
| PExpr.Array (_, p) => [p]
| PExpr.Call (_, p)
- | PExpr.Indexer(_, p) => p
+ | PExpr.Indexer(_, p)
+ | PExpr.GenericSpecifier(_, p) => p
| _ => []
}
- match (ast_args.Find((p) => p.Location.Contains(line, col)))
+ match (pargs.Find((p) => p.Location.Contains(line, col)))
{
| Some(p) =>
- def ty_args =
- match (ty)
+ def targs =
+ match (texpr)
{
| MType.Array (p, _) => [p]
| MType.Fun (f, t) => [f,t]
@@ -127,10 +123,10 @@
| _ => []
}
- def idx = ast_args.IndexOf(p);
- checkType(p, ty_args.Nth(idx))
+ def idx = pargs.IndexOf(p);
+ checkType(p, targs.Nth(idx))
- | _ => (ast.Location, null, ty)
+ | _ => (pexpr.Location, null, texpr)
}
}
@@ -235,22 +231,10 @@
{
def (_, _, tObj) = FindObject(typeDecl, fileIndex, line, col);
- def getMembers (ti : TypeInfo) {
- def members = ti.GetMembers(BindingFlags.Static
- %| BindingFlags.Instance %| BindingFlags.Public
- %| BindingFlags.NonPublic %| BindingFlags.DeclaredOnly)
- .Filter((p) => System.Attribute.GetCustomAttribute(p.GetHandle(),
- typeof(CompilerGeneratedAttribute)) == null);
-
- List.Map(members, GotoInfo);
- }
-
def getTypeGotoInfo(tv)
{
- | MType.Class(tycon is TypeBuilder, _) =>
- List.Map(tycon.PartsLocation, GotoInfo);
-
- | MType.Class(tycon, _) => getMembers(tycon);
+ | MType.Class(ty is TypeBuilder, _) => List.Map(ty.PartsLocation, GotoInfo);
+ | MType.Class(ty, _) => [GotoInfo(ty)]
| _ => []
}
@@ -261,11 +245,8 @@
| tc is TExpr.ImplicitValueTypeCtor => getTypeGotoInfo(tc.ty)
| tv is TyVar => getTypeGotoInfo(tv)
| tb is TypeBuilder => List.Map(tb.PartsLocation, GotoInfo);
- | ti is TypeInfo => getMembers(ti);
| fh is Typedtree.Fun_header => [(GotoInfo(fh))]
- | fb is FieldBuilder => [(GotoInfo(fb))]
- | pb is PropertyBuilder => [(GotoInfo(pb))]
- | mm is IMember => [(GotoInfo(mm))]
+ | m is IMember => [(GotoInfo(m))]
| _ => []
}
}
Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.n (original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Project.n Wed Nov 15 12:51:54 2006
@@ -6,12 +6,14 @@
using Nemerle.Compiler.Parsetree;
using Nemerle.Compiler.Typedtree;
using Nemerle.Compiler.Utils;
+using Nemerle.Collections;
using Nemerle.Assertions;
using Nemerle.Utility;
using Nemerle.Imperative;
using SCG = System.Collections.Generic;
+using SR = System.Reflection;
namespace Nemerle.Completion2
{
@@ -178,6 +180,28 @@
}
}
+ public GetGotoInfo(member : SR.MemberInfo) : array [GotoInfo]
+ {
+ def isType = member is System.Type && Attribute.GetCustomAttribute(member, typeof(Nemerle.Internal.VariantOptionAttribute)) == null;
+ def ty = if (isType) member :> System.Type else member.DeclaringType;
+
+ def typeBuilder = Array.Find(NamespaceTree.GetTypeBuilders(), (p) => p.FullName == ty.FullName);
+ if (typeBuilder != null)
+ {
+ def lst =
+ if (isType)
+ List.Map(typeBuilder.PartsLocation, GotoInfo);
+ else
+ if (typeBuilder.LookupMemberAvailable)
+ List.Map(typeBuilder.GetMembers() .Filter(m => m.Name == member.Name), GotoInfo);
+ else
+ List.Map(typeBuilder.GetParsedMembers().Filter(m => m.Name == member.Name), GotoInfo);
+ lst.ToArray();
+ }
+ else
+ null
+ }
+
public GetUsages([NotNull] filePath : string, line : int, col : int) : array [GotoInfo]
{
def fileIndex = _compileUnits.GetFileIndex(filePath);
Modified: vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.Designer.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.Designer.cs (original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.Designer.cs Wed Nov 15 12:51:54 2006
@@ -28,7 +28,7 @@
/// </summary>
private void InitializeComponent()
{
- this._listView = new AutoSizeListView();
+ this._listView = new Nemerle.VisualStudio.GUI.AutoSizeListView();
this.colFile = new System.Windows.Forms.ColumnHeader();
this.colLine = new System.Windows.Forms.ColumnHeader();
this.colPath = new System.Windows.Forms.ColumnHeader();
@@ -46,11 +46,11 @@
this._listView.Location = new System.Drawing.Point(0, 0);
this._listView.Name = "_listView";
this._listView.ShowItemToolTips = true;
- this._listView.Size = new System.Drawing.Size(555, 272);
+ this._listView.Size = new System.Drawing.Size(292, 274);
this._listView.TabIndex = 0;
this._listView.UseCompatibleStateImageBehavior = false;
this._listView.View = System.Windows.Forms.View.Details;
- this._listView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseDoubleClick);
+ this._listView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.HandleListViewMouseDoubleClick);
//
// colFile
//
@@ -72,7 +72,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(555, 272);
+ this.ClientSize = new System.Drawing.Size(292, 274);
this.Controls.Add(this._listView);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.KeyPreview = true;
Modified: vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.cs (original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/GUI/GoToTypeForm.cs Wed Nov 15 12:51:54 2006
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
-using System.Runtime.InteropServices;
using System.Windows.Forms;
using Nemerle.Completion2;
using System.IO;
@@ -33,16 +32,21 @@
{
base.OnLoad(e);
- // TODO: when the list is large, the form is out of a screen (bound it)
+ Rectangle parentRect = Screen.FromControl(this).WorkingArea;
+
// Adjust size
//
_listView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
+
ClientSize = _listView.PreferredSize;
+ if (Width > parentRect.Width *2/3)
+ Width = parentRect.Width *2/3;
+ if (Height > parentRect.Height*2/3)
+ Height = parentRect.Height*2/3;
+
// Adjust position
//
- Rectangle parentRect = Screen.FromControl(this).WorkingArea;
-
Left = parentRect.Left + (parentRect.Width - Width) / 2;
Top = parentRect.Top + (parentRect.Height - Height) / 2;
@@ -57,13 +61,9 @@
base.OnKeyPress(e);
if (e.KeyChar == (char)Keys.Escape)
- DialogResult = DialogResult.Cancel;
+ Close(DialogResult.Cancel);
else if (e.KeyChar == '\r' || e.KeyChar == ' ')
- DialogResult = DialogResult.OK;
- else
- return;
-
- Close();
+ Close(DialogResult.OK);
}
protected override void OnFormClosing(FormClosingEventArgs e)
@@ -74,16 +74,21 @@
if (_listView.FocusedItem.Tag == null)
{
e.Cancel = true;
- MessageBox.Show(this, "You must select item.", "Goto",
+ MessageBox.Show(this, "You must select an item.", "Goto",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
Result = (GotoInfo)_listView.FocusedItem.Tag;
}
- private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
+ private void HandleListViewMouseDoubleClick(object sender, MouseEventArgs e)
+ {
+ Close(DialogResult.OK);
+ }
+
+ private void Close(DialogResult result)
{
- DialogResult = DialogResult.OK;
+ DialogResult = result;
Close();
}
}
Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleAuthoringScope.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleAuthoringScope.cs (original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleAuthoringScope.cs Wed Nov 15 12:51:54 2006
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.SymbolStore;
using System.Windows.Forms;
@@ -57,7 +60,22 @@
private ProjectInfo _project;
private string _filePath;
private ISource _sourceText;
+
+ // Configurable option:
+ //
+ // When true, all files recovered from the .pdb will be recompiled to find real location.
+ // When false, the relevant method locations will be returned.
+ //
+ private bool _findExactLocation = true;
+
+ #endregion
+
+ #region Constants
+
private /*readonly*/ Guid IID_MetaDataImport = new Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44");
+ private const BindingFlags AllMethods = BindingFlags.DeclaredOnly
+ | BindingFlags.Instance | BindingFlags.Static
+ | BindingFlags.Public | BindingFlags.NonPublic;
#endregion
@@ -115,31 +133,27 @@
return null;
}
- LookupMethodLocationsFromPdb(info);
-
- List<GotoInfo> gotoInfos = new List<GotoInfo>(info.Length);
-
- // Remove duplicates and members which location still is not known.
- //
- for (int i = 0; i < info.Length; ++i)
+ if (!info[0].HasLocation)
{
- if (info[i].HasLocation && gotoInfos.FindIndex(
- delegate (GotoInfo item)
+ Debug.Assert(info.Length == 1, "Multiple unknown locations are unexpected");
+ info = LookupLocationsFromPdb(info[0]);
+
+ if (info == null)
{
- return item.FilePath == info[i].FilePath
- && item.LineStart == info[i].LineStart;
- }) < 0)
- gotoInfos.Add(info[i]);
+ // PB061115: Generate code here
+ //
+ return null;
+ }
}
- if (gotoInfos.Count == 1)
- return SetTextSpan(ref span, gotoInfos[0]);
- else if (gotoInfos.Count > 0)
+ if (info.Length == 1)
+ return SetTextSpan(ref span, info[0]);
+ else if (info.Length > 0)
{
NativeWindow textEditorWnd =
NativeWindow.FromHandle(textView.GetWindowHandle());
- using (GoToTypeForm popup = new GoToTypeForm(gotoInfos))
+ using (GoToTypeForm popup = new GoToTypeForm(info))
if (popup.ShowDialog(textEditorWnd) == DialogResult.OK)
return SetTextSpan(ref span, popup.Result);
}
@@ -162,38 +176,33 @@
#region Implementation
- private void LookupMethodLocationsFromPdb(GotoInfo[] info)
+ private GotoInfo[] LookupLocationsFromPdb(GotoInfo info)
{
- IntPtr mdiPtr = IntPtr.Zero;
- ISymbolBinder1 binder = null;
- ISymbolDocument[] documents = null;
- int[] lines = null;
- int[] columns = null;
- int[] endLines = null;
- int[] endColumns = null;
- int[] offsets = null;
- string prevFile = null;
- ISymbolReader reader = null;
+ Debug.Assert(info != null, "LookupLocationsFromPdb lacks required parameter");
- try
- {
- foreach (GotoInfo gotoInfo in info)
- {
- if (gotoInfo.HasLocation)
- continue;
- if (gotoInfo.Member == null || string.IsNullOrEmpty(gotoInfo.FilePath))
- continue;
+ if (info.Member == null || string.IsNullOrEmpty(info.FilePath) || !File.Exists(info.FilePath))
+ return new GotoInfo[0];
- // First time init
- //
- if (mdiPtr == IntPtr.Zero)
- {
- object mdiUnk;
+ object unkMetaDataImport;
+ IntPtr ptrMetaDataImport;
+ ISymbolBinder1 binder;
+ ISymbolReader reader;
+ ISymbolDocument[] documents;
+ int[] lines;
+ int[] columns;
+ int[] endLines;
+ int[] endColumns;
+ int[] offsets;
+ int hr;
+ List<GotoInfo> infos = new List<GotoInfo>();
+ List<MethodBase> methods = new List<MethodBase>();
- if (VSConstants.S_OK == _project.SmartOpenScope.OpenScope(info[0].FilePath, 0, ref IID_MetaDataImport, out mdiUnk))
+ hr = _project.SmartOpenScope.OpenScope(info.FilePath, 0, ref IID_MetaDataImport, out unkMetaDataImport);
+ if (hr == VSConstants.S_OK)
{
- mdiPtr = Marshal.GetIUnknownForObject(mdiUnk);
+ ptrMetaDataImport = Marshal.GetIUnknownForObject(unkMetaDataImport);
binder = new SymBinder();
+ reader = binder.GetReader(ptrMetaDataImport, info.FilePath, null);
documents = new ISymbolDocument[1];
lines = new int[1];
columns = new int[1];
@@ -203,34 +212,68 @@
}
else
{
- Debug.WriteLineIf(TS.TraceWarning, "Failed to obtain MetaDataImport from VS", TS.DisplayName);
- break;
- }
+ Debug.WriteLineIf(TS.TraceWarning,
+ string.Format("Failed to obtain MetaDataImport from VS, hr 0x{0:X8}", hr), TS.DisplayName);
+ return null;
}
try
{
- if (gotoInfo.FilePath != prevFile)
+ if (info.Member is MethodBase)
+ methods.Add((MethodBase)info.Member);
+ else if (info.Member is PropertyInfo)
{
- reader = binder.GetReader(mdiPtr, gotoInfo.FilePath, null);
- prevFile = gotoInfo.FilePath;
+ PropertyInfo pi = (PropertyInfo)info.Member;
+ methods.AddRange(pi.GetAccessors(true));
}
+ else if (info.Member is FieldInfo)
+ {
+ Type t = info.Member.DeclaringType;
+ methods.AddRange(t.GetMethods(AllMethods));
+ }
+ else if (info.Member is EventInfo)
+ {
+ EventInfo ei = (EventInfo)info.Member;
+ methods.Add (ei.GetAddMethod (true));
+ methods.Add (ei.GetRemoveMethod(true));
+ methods.Add (ei.GetRaiseMethod (true));
+ methods.AddRange(ei.GetOtherMethods(true));
+ }
+ else if (info.Member is Type)
+ {
+ Type t = (Type)info.Member;
+ methods.AddRange(t.GetMethods(AllMethods));
+ }
+ else
+ Trace.Fail("Unexpected MemberInfo " + info.Member.GetType().FullName);
- SymbolToken token = new SymbolToken(gotoInfo.Member.MetadataToken);
+ foreach (MethodBase mb in methods)
+ {
+ if (Attribute.GetCustomAttribute(mb, typeof(CompilerGeneratedAttribute)) != null)
+ continue;
+
+ try
+ {
+ SymbolToken token = new SymbolToken(mb.MetadataToken);
ISymbolMethod method = reader.GetMethod(token);
if (method.SequencePointCount > 0)
{
method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);
- gotoInfo.SetLocation(documents[0].URL, lines[0], columns[0], endLines[0], endColumns[0]);
+
+ // We are interested in unique files only.
+ //
+ if (infos.Find(delegate (GotoInfo item){ return item.FilePath == documents[0].URL; }) == null)
+ infos.Add(new GotoInfo(documents[0].URL, lines[0], columns[0], endLines[0], endColumns[0]));
}
}
catch (COMException ex)
{
- // Abstract method or not a method at all. Sequence points are available only for methods.
+ // Abstract method or not a method at all.
+ // Sequence points are available only for methods.
//
Trace.WriteLineIf(TS.TraceError,
- string.Format("{0}, code 0x{1:X8}", ex.Message, ex.ErrorCode), TS.DisplayName);
+ string.Format("({0}) {1}, code 0x{2:X8}", mb.Name, ex.Message, ex.ErrorCode), TS.DisplayName);
}
}
}
@@ -243,9 +286,34 @@
}
finally
{
- if (IntPtr.Zero != mdiPtr)
- Marshal.Release(mdiPtr);
+ if (IntPtr.Zero != ptrMetaDataImport)
+ Marshal.Release(ptrMetaDataImport);
}
+
+ // In case of a Method we already succeeded
+ //
+ if (info.Member is MethodBase)
+ {
+ Debug.Assert(infos.Count < 2, "Partial method is not expected.");
+ return infos.ToArray();
+ }
+
+ if (_findExactLocation)
+ {
+ // Quickly compile and find the _exact_ location(s)
+ //
+ Nemerle.Completion2.ProjectManager pm = new Nemerle.Completion2.ProjectManager();
+ Nemerle.Completion2.Engine e = new Nemerle.Completion2.Engine(pm, new TraceWriter());
+
+ pm.Engine = e;
+
+ foreach (GotoInfo gi in infos)
+ e.Sources.AddOrUpdate(gi.FilePath, File.ReadAllText(gi.FilePath));
+
+ return e.Project.GetGotoInfo(info.Member);
+ }
+
+ return infos.ToArray();
}
private static string SetTextSpan(ref TextSpan span, GotoInfo result)
Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs (original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs Wed Nov 15 12:51:54 2006
@@ -252,12 +252,13 @@
{
ProjectInfo projectInfo = ProjectInfo.FindProject(request.FileName);
- Nemerle.Completion2.Project p = projectInfo.Engine.Project;
- Trace.Assert(p != null);
if (projectInfo == null)
return null;
+ Nemerle.Completion2.Project p = projectInfo.Engine.Project;
+ Trace.Assert(p != null);
+
NemerleSource source = projectInfo.GetSource(request.FileName);
int nErrors = 0;
More information about the svn
mailing list