Skip to content

EnvDTE.CodeElement.GetStartPoint(part)/GetEndPoint(part) not implemented for many parts #2461

Description

@carlos-quintero

When you use the EnvDTE.ProjectItem.FileCodeModel to call EnvDTE.CodeElement.GetStartPoint(part) and EnvDTE.CodeElement.GetEndPoint(part), many calls fail as "not implemented"

Steps to reproduce the problem:

  1. Create a package with a menu command that uses this code:
  private void MenuItemCallback(object sender, EventArgs e)
  {
     try
     {
        EnvDTE.DTE dte = this.ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
        ShowCodeElements(dte.ActiveDocument.ProjectItem.FileCodeModel.CodeElements);
     }
     catch (Exception ex)
     {
        System.Windows.Forms.MessageBox.Show(ex.ToString());
     }
  }

  private void ShowCodeElements(EnvDTE.CodeElements codeElements)
  {
     foreach (EnvDTE.CodeElement codeElement in codeElements)
     {
        ShowCodeElement(codeElement);
     }
  }

  private void ShowCodeElement(EnvDTE.CodeElement codeElement)
  {
     ShowStartEndTextPoints(codeElement);

     switch (codeElement.Kind)
     {
        case EnvDTE.vsCMElement.vsCMElementNamespace:

           EnvDTE.CodeNamespace codeNamespace = codeElement as EnvDTE.CodeNamespace;

           ShowCodeElements(codeNamespace.Members);
           break;

        case EnvDTE.vsCMElement.vsCMElementProperty:

           EnvDTE.CodeProperty codeProperty = codeElement as EnvDTE.CodeProperty;

           try
           {
              ShowCodeElement(codeProperty.Getter as EnvDTE.CodeElement);
           }
           catch
           {
           }
           try
           {
              ShowCodeElement(codeProperty.Setter as EnvDTE.CodeElement);
           }
           catch
           {
           }
           break;

        case EnvDTE.vsCMElement.vsCMElementEvent:

           EnvDTE80.CodeEvent codeEvent = codeElement as EnvDTE80.CodeEvent;
           try
           {
              ShowStartEndTextPoints(codeEvent.Adder as EnvDTE.CodeElement);
           }
           catch
           {
           }
           try
           {
              ShowStartEndTextPoints(codeEvent.Remover as EnvDTE.CodeElement);
           }
           catch
           {
           }
           try
           {
              ShowStartEndTextPoints(codeEvent.Thrower as EnvDTE.CodeElement);
           }
           catch
           {
           }
           break;

        case EnvDTE.vsCMElement.vsCMElementFunction:

           EnvDTE.CodeFunction codeFunction = codeElement as EnvDTE.CodeFunction;
           ShowCodeElements(codeFunction.Parameters);
           break;

        default:

           EnvDTE.CodeType codeType = codeElement as EnvDTE.CodeType;
           if (codeType != null)
           {
              ShowCodeElements(codeType.Members);
           }
           break;
     }
  }

  private void ShowStartEndTextPoints(EnvDTE.CodeElement codeElement)
  {
     if (codeElement != null)
     {
        ShowStartEndTextPoints(codeElement, EnvDTE.vsCMPart.vsCMPartWholeWithAttributes);
        ShowStartEndTextPoints(codeElement, EnvDTE.vsCMPart.vsCMPartWhole);
        ShowStartEndTextPoints(codeElement, EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes);
        ShowStartEndTextPoints(codeElement, EnvDTE.vsCMPart.vsCMPartHeader);
        ShowStartEndTextPoints(codeElement, EnvDTE.vsCMPart.vsCMPartName);
     }
  }

  private void ShowStartEndTextPoints(EnvDTE.CodeElement codeElement, EnvDTE.vsCMPart part)
  {
     EnvDTE.TextPoint textPoint;
     string info;

     info = "Kind: " + codeElement.Kind.ToString() + "\nName: " + codeElement.Name + "\nPart: " + part.ToString() + "\nPoint: ";

     try
     {
        textPoint = codeElement.GetStartPoint(part);
        System.Windows.Forms.MessageBox.Show("Start\n" + info + textPoint.Line.ToString() + "," + textPoint.LineCharOffset.ToString(),
           "", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
     }
     catch (Exception ex)
     {
        System.Windows.Forms.MessageBox.Show("Start\n" + info + " " + ex.Message, "", System.Windows.Forms.MessageBoxButtons.OK, 
           System.Windows.Forms.MessageBoxIcon.Error);
     }

     try
     {
        textPoint = codeElement.GetEndPoint(part);
        System.Windows.Forms.MessageBox.Show("End\n" + info + textPoint.Line.ToString() + "," + textPoint.LineCharOffset.ToString(),
           "", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
     }
     catch (Exception ex)
     {
        System.Windows.Forms.MessageBox.Show("End\n" + info + " " + ex.Message, "", System.Windows.Forms.MessageBoxButtons.OK, 
           System.Windows.Forms.MessageBoxIcon.Error);
     }
  }
  1. Run the package and in the second VS instance, create a C# Class Library with this code:

namespace Namespace1
{

public class SkipReview : System.Attribute
{
}

[SkipReview]
public delegate void Delegate1(int p1);

[SkipReview]
public interface Interface1
{

  [SkipReview]
  void Function1();

  [SkipReview]
  event Delegate1 Event1;

  [SkipReview]
  int Property1 { get; set; }

}

[SkipReview]
public class Class1 : Interface1
{

  [SkipReview]
  const int CONST1 = 0;

  [SkipReview]
  int Field1 = 0;

  [SkipReview]
  void Interface1.Function1() 
  {
  }

  [SkipReview]
  event Delegate1 Interface1.Event1
  {
     [SkipReview]
     add
     {
     }
     [SkipReview]
     remove
     {
     }
  }

  [SkipReview]
  int Interface1.Property1
  {
     [SkipReview]
     get
     {
        return Field1;
     }
     [SkipReview]
     set
     {
     }
  }

  [SkipReview]
  void Function2()
  {
  }

  [SkipReview]
  event Delegate1 Event2
  {
     [SkipReview]
     add
     {
     }
     [SkipReview]
     remove
     {
     }
  }

  [SkipReview]
  int Property2
  {
     [SkipReview]
     get
     {
        return 0;
     }
     [SkipReview]
     set
     {
     }
  }

}

[SkipReview]
public struct Struct1
{

  [SkipReview]
  const int CONST1 = 0;

  [SkipReview]
  int Field1;

  [SkipReview]
  void Function2()
  {
  }

  [SkipReview]
  event System.EventHandler Event2
  {
     [SkipReview]
     add
     {
     }
     [SkipReview]
     remove
     {
     }
  }

  [SkipReview]
  int Property2
  {
     [SkipReview]
     get
     {
        Field1 = 0;
        return Field1;
     }

     [SkipReview]
     set
     {
     }

  }

}

[SkipReview]
public enum Enum1
{

  [SkipReview]
  EnumItem1 = 1,

  [SkipReview]
  EnumItem2 = 2

}

}

  1. Click the package command. You will find lots of "not implemented" exceptions. Notice that:

vsCMPart.vsCMPartWholeWithAttributes
vsCMPart.vsCMPartWhole
vsCMPart.vsCMPartHeaderWithAttributes
vsCMPart.vsCMPartHeader
vsCMPartName

should be "valid" parts (ie, "implemented") for any kind of code element.

vsCMPartBody (not shown in this report) may fail for code elements that lack body (parameters, members of interfaces, abstract method/properties, etc.)

Test also with VB.NET code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-IDEBugTenet-CompatibilityViolation of forwards/backwards compatibility in a design-time piece.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions