/// <summary> /// Explores given variable initializer using C# lookuper /// </summary> protected virtual void Explore(AbstractBatchCommand parentCommand, CodeVariable2 codeVariable, CodeNamespace parentNamespace, CodeElement2 codeClassOrStruct, Predicate <CodeElement> exploreable, bool isLocalizableFalse) { if (codeVariable.InitExpression == null) { return; // variable must have an initializer } if (codeClassOrStruct.Kind == vsCMElement.vsCMElementStruct && !codeVariable.IsShared) { return; // instance variable of structs cannot have initializers } if (!exploreable(codeVariable as CodeElement)) { return; // predicate must evaluate to true } string initExpression = codeVariable.GetText(); // get text of initializer if (string.IsNullOrEmpty(initExpression)) { return; } TextPoint startPoint = codeVariable.StartPoint; // is variable decorated with Localizable(false) bool variableLocalizableFalse = (codeVariable as CodeElement).HasLocalizableFalseAttribute(); // run lookuper using parent command var list = parentCommand.LookupInCSharp(initExpression, startPoint, parentNamespace, codeClassOrStruct, null, codeVariable.Name, isLocalizableFalse || variableLocalizableFalse); // add context to result items (surounding few lines of code) EditPoint2 editPoint = (EditPoint2)startPoint.CreateEditPoint(); foreach (AbstractResultItem item in list) { item.IsConst = codeVariable.ConstKind == vsCMConstKind.vsCMConstKindConst; item.CodeModelSource = codeVariable; AddContextToItem(item, editPoint); } }
/// <summary> /// Used by C# ad-hoc methods (move and inline) to get information about the block of code, where right-click was performed. /// This methods makes use of document's FileCodeModel, which is not available for ASP .NET files - these files are thus /// handled by their own parser. /// </summary> /// <param name="text">Text of the block (e.g. code of a method, declaration of a variable...)</param> /// <param name="startPoint">Beginning of the text</param> /// <param name="codeFunctionName">Name of the function, where right-click was performed, null if right-click was performed on a variable.</param> /// <param name="codeVariableName">Name of the variable, where right-click was performed, null otherwise.</param> /// <param name="codeClass">Name of the class, where the code block is located.</param> /// <param name="selectionSpan">Current selection span.</param> /// <returns>True, if all necessary information was succesfully obtained, false otherwise.</returns> protected bool GetCodeBlockFromSelection(out string text, out TextPoint startPoint, out string codeFunctionName, out string codeVariableName, out CodeElement2 codeClass, out TextSpan selectionSpan, out bool isConst, out object codeModelSource) { // get current selection span TextSpan[] spans = new TextSpan[1]; int hr = textView.GetSelectionSpan(spans); Marshal.ThrowExceptionForHR(hr); selectionSpan = spans[0]; object o; hr = textLines.CreateTextPoint(selectionSpan.iStartLine, selectionSpan.iStartIndex, out o); Marshal.ThrowExceptionForHR(hr); TextPoint selectionPoint = (TextPoint)o; startPoint = null; text = null; bool ok = false; codeFunctionName = null; codeVariableName = null; codeClass = null; isConst = false; codeModelSource = null; // It is impossible to find out the code block, where right-click was performed. Following code // assumes that valid string literals or references can only be found in a method, in a class variable (as initializers) // or in a property code. C# syntax permits more locations (attributes, default argument values in .NET 4+) but we can ignore // these, because they are all evaluated at compile-time, making resource references impossible. // assume we are in a function (method) try { CodeFunction2 codeFunction = (CodeFunction2)currentCodeModel.CodeElementFromPoint(selectionPoint, vsCMElement.vsCMElementFunction); codeFunctionName = codeFunction.Name; codeClass = codeFunction.GetClass(); // extension codeModelSource = codeFunction; text = codeFunction.GetText(); if (!string.IsNullOrEmpty(text)) { startPoint = codeFunction.GetStartPoint(vsCMPart.vsCMPartBody); ok = true; } } catch (Exception) { // it's not a method - maybe a property? try { CodeProperty codeProperty = (CodeProperty)currentCodeModel.CodeElementFromPoint(selectionPoint, vsCMElement.vsCMElementProperty); codeFunctionName = codeProperty.Name; codeClass = codeProperty.GetClass(); codeModelSource = codeProperty; text = codeProperty.GetText(); if (!string.IsNullOrEmpty(text)) { startPoint = codeProperty.GetStartPoint(vsCMPart.vsCMPartBody); ok = true; } } catch (Exception) { // not a property, either. It must be a variable - or there's no valid code block try { CodeVariable2 codeVariable = (CodeVariable2)currentCodeModel.CodeElementFromPoint(selectionPoint, vsCMElement.vsCMElementVariable); if (codeVariable.InitExpression != null) { codeVariableName = codeVariable.Name; codeClass = codeVariable.GetClass(); isConst = codeVariable.ConstKind == vsCMConstKind.vsCMConstKindConst; codeModelSource = codeVariable; startPoint = codeVariable.StartPoint; text = codeVariable.GetText(); if ((codeClass.Kind == vsCMElement.vsCMElementStruct && codeVariable.IsShared) || (codeClass.Kind == vsCMElement.vsCMElementClass || codeClass.Kind == vsCMElement.vsCMElementModule) && !string.IsNullOrEmpty(text)) { ok = true; } } } catch (Exception) { return(false); } } } return(ok); }