public override bool IsValid (RefactoringOptions options) { IResolver resolver = options.GetResolver (); INRefactoryASTProvider provider = options.GetASTProvider (); if (resolver == null || provider == null) return false; TextEditorData data = options.GetTextEditorData (); if (data == null) return false; ResolveResult resolveResult; if (data.IsSomethingSelected) { ExpressionResult expressionResult = new ExpressionResult (data.SelectedText.Trim ()); if (expressionResult.Expression.Contains (" ") || expressionResult.Expression.Contains ("\t")) expressionResult.Expression = "(" + expressionResult.Expression + ")"; resolveResult = resolver.Resolve (expressionResult, new DomLocation (data.Caret.Line, data.Caret.Column)); if (resolveResult == null) return false; return true; } LineSegment lineSegment = data.Document.GetLine (data.Caret.Line); string line = data.Document.GetTextAt (lineSegment); Expression expression = provider.ParseExpression (line); BlockStatement block = provider.ParseText (line) as BlockStatement; if (expression == null || (block != null && block.Children[0] is LocalVariableDeclaration)) return false; resolveResult = resolver.Resolve (new ExpressionResult (line), new DomLocation (options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column)); return resolveResult.ResolvedType != null && !string.IsNullOrEmpty (resolveResult.ResolvedType.FullName) && resolveResult.ResolvedType.FullName != DomReturnType.Void.FullName; }
public NRefactoryTemplateParameterDataProvider (TextEditorData editor, NRefactoryResolver resolver, IEnumerable<string> namespaces, ExpressionResult expressionResult, DomLocation loc) { // this.editor = editor; ResolveResult plainResolveResult = resolver.Resolve (expressionResult, loc); MethodResolveResult resolveResult = plainResolveResult as MethodResolveResult; if (resolveResult != null) { foreach (IMethod method in resolveResult.Methods) { if (method.TypeParameters.Count > 0) this.types.Add (method); } } else { string typeName = expressionResult.Expression.Trim (); foreach (string ns in namespaces) { string prefix = ns + (ns.Length > 0 ? "." : "") + typeName + "`"; for (int i = 1; i < 99; i++) { IType possibleType = resolver.Dom.GetType (prefix + i); if (possibleType != null) this.types.Add (possibleType); } } IType resolvedType = plainResolveResult != null ? resolver.Dom.GetType (plainResolveResult.ResolvedType) : null; if (resolvedType == null) { int idx = expressionResult.Expression.LastIndexOf ("."); if (idx < 0) return; typeName = expressionResult.Expression.Substring (idx + 1); expressionResult.Expression = expressionResult.Expression.Substring (0, idx); plainResolveResult = resolver.Resolve (expressionResult, loc); resolvedType = resolver.Dom.GetType (plainResolveResult.ResolvedType); } if (resolvedType == null) return; foreach (IType innerType in resolvedType.InnerTypes) { this.types.Add (innerType); } } }
public bool IsInLinqContext (ExpressionResult result) { if (result.Contexts == null) return false; var ctx = (ExpressionContext.LinqContext)result.Contexts.FirstOrDefault (c => c is ExpressionContext.LinqContext); if (ctx == null) return false; int offset = this.textEditorData.Document.LocationToOffset (ctx.Line, ctx.Column); return !GetTextWithoutCommentsAndStrings (this.textEditorData.Document, offset, textEditorData.Caret.Offset).Any (p => p.Key == ';'); }
ICompletionDataList CreateCaseCompletionData (DomLocation location, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (location); SwitchFinder switchFinder = new SwitchFinder (location); if (resolver.MemberCompilationUnit != null) switchFinder.VisitCompilationUnit (resolver.MemberCompilationUnit, null); CompletionDataList result = new ProjectDomCompletionDataList (); if (switchFinder.SwitchStatement == null) return result; ResolveResult resolveResult = resolver.ResolveExpression (switchFinder.SwitchStatement.SwitchExpression, location); IType type = dom.GetType (resolveResult.ResolvedType); if (type != null && type.ClassType == ClassType.Enum) { OutputFlags flags = OutputFlags.None; var declaringType = resolver.CallingType; if (declaringType != null && dom != null) { foreach (IType t in new List<IType>(dom.GetInheritanceTree (declaringType))) { if (t.SearchMember (type.Name, true).Any (m => m.MemberType != MonoDevelop.Projects.Dom.MemberType.Type)) { flags |= OutputFlags.UseFullName; break; } } } // if (!foundType && (NamePrefix.Length == 0 || !type.Namespace.StartsWith (NamePrefix)) && !type.Namespace.EndsWith ("." + NamePrefix) && type.DeclaringType == null && NamePrefix != null && !NamePrefix.Contains ("::")) // flags |= OutputFlags.UseFullName; CompletionDataCollector cdc = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, location); cdc.Add (type, flags); } return result; }
CompletionDataList CreateCtrlSpaceCompletionData (CodeCompletionContext ctx, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); DomLocation cursorLocation = new DomLocation (ctx.TriggerLine, ctx.TriggerLineOffset); resolver.SetupResolver (cursorLocation); CompletionDataList result = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, cursorLocation); if (expressionResult == null) { AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (ExpressionContext.Global, col); } else if (expressionResult.ExpressionContext == ExpressionContext.TypeDeclaration) { AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.TypeLevel); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.InterfaceDeclaration) { AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.InterfaceLevel); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.MethodBody) { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.StatementStart); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.InterfacePropertyDeclaration) { col.Add ("get", "md-keyword"); col.Add ("set", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.ConstraintsStart) { col.Add ("where", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.Constraints) { col.Add ("new", "md-keyword"); col.Add ("class", "md-keyword"); col.Add ("struct", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.Attribute) { col.Add ("assembly", "md-keyword"); col.Add ("module", "md-keyword"); col.Add ("type", "md-keyword"); col.Add ("method", "md-keyword"); col.Add ("field", "md-keyword"); col.Add ("property", "md-keyword"); col.Add ("event", "md-keyword"); col.Add ("param", "md-keyword"); col.Add ("return", "md-keyword"); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.BaseConstructorCall) { col.Add ("this", "md-keyword"); col.Add ("base", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.ParameterType || expressionResult.ExpressionContext == ExpressionContext.FirstParameterType) { col.Add ("ref", "md-keyword"); col.Add ("out", "md-keyword"); col.Add ("params", "md-keyword"); // C# 3.0 extension method if (expressionResult.ExpressionContext == ExpressionContext.FirstParameterType) col.Add ("this", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.PropertyDeclaration) { AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.InPropertyDeclaration); } else if (expressionResult.ExpressionContext == ExpressionContext.EventDeclaration) { col.Add ("add", "md-keyword"); col.Add ("remove", "md-keyword"); } //else if (expressionResult.ExpressionContext == ExpressionContext.FullyQualifiedType) {} else if (expressionResult.ExpressionContext == ExpressionContext.Default) { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.ExpressionStart); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.ExpressionContent); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.Global) { AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.GlobalLevel); CodeTemplateService.AddCompletionDataForMime ("text/x-csharp", result); } else if (expressionResult.ExpressionContext == ExpressionContext.ObjectInitializer) { ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType); if (exactContext is ExpressionContext.TypeExpressionContext) { IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType; if (objectInitializer.ArrayDimensions > 0 || objectInitializer.PointerNestingLevel > 0) { col.Add ("global", "md-keyword"); col.Add ("new", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); return result; } IType foundType = resolver.SearchType (objectInitializer); if (foundType == null) foundType = dom.GetType (objectInitializer); if (foundType != null) { bool includeProtected = DomType.IncludeProtected (dom, foundType, resolver.CallingType); foreach (IType type in dom.GetInheritanceTree (foundType)) { foreach (IProperty property in type.Properties) { if (property.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected)) { col.Add (property); } } foreach (var field in type.Fields) { if (field.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected)) { col.Add (field); } } } } } // result.Add ("global", "md-literal"); // AddPrimitiveTypes (result); // resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, result); } else if (expressionResult.ExpressionContext == ExpressionContext.AttributeArguments) { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); string attributeName = NewCSharpExpressionFinder.FindAttributeName (textEditorData, Document.CompilationUnit, Document.FileName); if (attributeName != null) { IType type = resolver.SearchType (attributeName + "Attribute"); if (type == null) type = resolver.SearchType (attributeName); if (type != null) { foreach (var property in type.Properties) { col.Add (property); } foreach (var field in type.Fields) { if (field.IsPublic) col.Add (field); } } } resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.IdentifierExpected) { if (!string.IsNullOrEmpty (expressionResult.Expression)) expressionResult.Expression = expressionResult.Expression.Trim (); MemberResolveResult resolveResult = resolver.Resolve (expressionResult, cursorLocation) as MemberResolveResult; if (resolveResult != null && resolveResult.ResolvedMember == null && resolveResult.ResolvedType != null) { string name = CSharpAmbience.NetToCSharpTypeName (resolveResult.ResolvedType.FullName); if (name != resolveResult.ResolvedType.FullName) { col.Add (Char.ToLower (name[0]).ToString (), "md-field"); } else { name = resolveResult.ResolvedType.Name; List<string> names = new List<string> (); int lastNameStart = 0; for (int i = 1; i < name.Length; i++) { if (Char.IsUpper (name[i])) { names.Add (name.Substring (lastNameStart, i - lastNameStart)); lastNameStart = i; } } names.Add (name.Substring (lastNameStart, name.Length - lastNameStart)); StringBuilder possibleName = new StringBuilder (); for (int i = 0; i < names.Count; i++) { possibleName.Length = 0; for (int j = i; j < names.Count; j++) { if (string.IsNullOrEmpty (names[j])) continue; if (j == i) names[j] = Char.ToLower (names[j][0]) + names[j].Substring (1); possibleName.Append (names[j]); } if (possibleName.Length > 0) col.Add (possibleName.ToString (), "md-field"); } result.IsSorted = true; } } else { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); if (expressionResult.ExpressionContext == ExpressionContext.Constraints) { col.Add ("struct", "md-keyword"); col.Add ("class", "md-keyword"); col.Add ("new()", "md-keyword"); } else { col.Add ("var", "md-keyword"); } } } else if (expressionResult.ExpressionContext == ExpressionContext.TypeName) { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.ForeachInToken) { col.Add ("in", "md-keyword"); } else { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } if (resolver.CallingMember is IMethod) { foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) { col.Add (tp.Name, "md-keyword"); } } return result; }
ICompletionDataList CreateCompletionData (DomLocation location, ResolveResult resolveResult, ExpressionResult expressionResult, NRefactoryResolver resolver) { if (resolveResult == null || expressionResult == null || dom == null) return null; CompletionDataList result = new ProjectDomCompletionDataList (); IEnumerable<object> objects = resolveResult.CreateResolveResult (dom, resolver != null ? resolver.CallingMember : null); CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver != null ? resolver.CallingType : null, location); col.HideExtensionParameter = !resolveResult.StaticResolve; col.NamePrefix = expressionResult.Expression; bool showOnlyTypes = expressionResult.Contexts.Any (ctx => ctx == ExpressionContext.InheritableType || ctx == ExpressionContext.Constraints); if (objects != null) { foreach (object obj in objects) { if (expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.FilterEntry (obj)) continue; if (expressionResult.ExpressionContext == ExpressionContext.NamespaceNameExcepted && !(obj is Namespace)) continue; if (showOnlyTypes && !(obj is IType)) continue; CompletionData data = col.Add (obj); if (data != null && expressionResult.ExpressionContext == ExpressionContext.Attribute && data.CompletionText != null && data.CompletionText.EndsWith ("Attribute")) { string newText = data.CompletionText.Substring (0, data.CompletionText.Length - "Attribute".Length); data.SetText (newText); } } } return result; }
ICompletionDataList CreateCaseCompletionData (DomLocation location, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (location); SwitchFinder switchFinder = new SwitchFinder (location); if (resolver.MemberCompilationUnit != null) switchFinder.VisitCompilationUnit (resolver.MemberCompilationUnit, null); CompletionDataList result = new ProjectDomCompletionDataList (); if (switchFinder.SwitchStatement == null) return result; ResolveResult resolveResult = resolver.ResolveExpression (switchFinder.SwitchStatement.SwitchExpression, location); IType type = dom.GetType (resolveResult.ResolvedType); if (type != null && type.ClassType == ClassType.Enum) { CompletionDataCollector cdc = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, location); cdc.Add (type); } return result; }
internal static RefactoringOptions CreateRefactoringOptions (string text) { int cursorPosition = -1; int endPos = text.IndexOf ('$'); if (endPos >= 0) { cursorPosition = endPos; text = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1); } int selectionStart = -1; int selectionEnd = -1; int idx = text.IndexOf ("<-"); if (idx >= 0) { selectionStart = idx; text = text.Substring (0, idx) + text.Substring (idx + 2); selectionEnd = idx = text.IndexOf ("->"); text = text.Substring (0, idx) + text.Substring (idx + 2); if (cursorPosition < 0) cursorPosition = selectionEnd - 1; } TestWorkbenchWindow tww = new TestWorkbenchWindow (); TestViewContent sev = new TestViewContent (); // return new RefactoringOptions (); DotNetProject project = new DotNetAssemblyProject ("C#"); Solution solution = new Solution (); solution.RootFolder.Items.Add (project); project.FileName = GetTempFile (".csproj"); string file = GetTempFile (".cs"); project.AddFile (file); string parsedText = text; string editorText = text; ProjectDomService.Load (project); ProjectDom dom = ProjectDomService.GetProjectDom (project); dom.ForceUpdate (true); ProjectDomService.Parse (project, file, delegate { return parsedText; }); ProjectDomService.Parse (project, file, delegate { return parsedText; }); sev.Project = project; sev.ContentName = file; sev.Text = editorText; sev.CursorPosition = cursorPosition; tww.ViewContent = sev; var doc = new MonoDevelop.Ide.Gui.Document (tww); doc.Editor.Document.MimeType = "text/x-csharp"; doc.Editor.Document.FileName = file; doc.ParsedDocument = new McsParser ().Parse (null, sev.ContentName, parsedText); foreach (var e in doc.ParsedDocument.Errors) Console.WriteLine (e); if (cursorPosition >= 0) doc.Editor.Caret.Offset = cursorPosition; if (selectionStart >= 0) doc.Editor.SetSelection (selectionStart, selectionEnd); NRefactoryResolver resolver = new NRefactoryResolver (dom, doc.ParsedDocument.CompilationUnit, sev.Data, file); ExpressionResult expressionResult; if (selectionStart >= 0) { expressionResult = new ExpressionResult (editorText.Substring (selectionStart, selectionEnd - selectionStart).Trim ()); endPos = selectionEnd; } else { expressionResult = new NewCSharpExpressionFinder (dom).FindFullExpression (doc.Editor, cursorPosition + 1); } ResolveResult resolveResult = endPos >= 0 ? resolver.Resolve (expressionResult, new DomLocation (doc.Editor.Caret.Line, doc.Editor.Caret.Column)) : null; RefactoringOptions result = new RefactoringOptions { Document = doc, Dom = dom, ResolveResult = resolveResult, SelectedItem = null }; if (resolveResult is MemberResolveResult) result.SelectedItem = ((MemberResolveResult)resolveResult).ResolvedMember; if (resolveResult is LocalVariableResolveResult) result.SelectedItem = ((LocalVariableResolveResult)resolveResult).LocalVariable; if (resolveResult is ParameterResolveResult) result.SelectedItem = ((ParameterResolveResult)resolveResult).Parameter; result.TestFileProvider = new FileProvider (result); return result; }
public MonoDevelop.Projects.Dom.ResolveResult GetLanguageItem (ProjectDom dom, Mono.TextEditor.TextEditorData data, int offset, string expression) { string fileName = data.Document.FileName; MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.ActiveDocument; if (doc == null) return null; IParser parser = ProjectDomService.GetParser (fileName, data.Document.MimeType); if (parser == null) return null; IResolver resolver = parser.CreateResolver (dom, doc, fileName); IExpressionFinder expressionFinder = parser.CreateExpressionFinder (dom); if (resolver == null || expressionFinder == null) return null; string txt = data.Document.Text; int wordEnd = offset; while (wordEnd < txt.Length && (Char.IsLetterOrDigit (txt[wordEnd]) || txt[wordEnd] == '_')) wordEnd++; ExpressionResult expressionResult = new ExpressionResult (expression); expressionResult.ExpressionContext = ExpressionContext.MethodBody; DocumentLocation loc = data.Document.OffsetToLocation (offset); string savedExpression = null; ResolveResult resolveResult; if (expressionResult.ExpressionContext == ExpressionContext.Attribute) { savedExpression = expressionResult.Expression; expressionResult.Expression += "Attribute"; expressionResult.ExpressionContext = ExpressionContext.ObjectCreation; } resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1)); if (savedExpression != null && resolveResult == null) { expressionResult.Expression = savedExpression; resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1)); } // Search for possible generic parameters. // if (this.resolveResult == null || this.resolveResult.ResolvedType == null || String.IsNullOrEmpty (this.resolveResult.ResolvedType.Name)) { int j = data.Document.LocationToOffset (expressionResult.Region.End.Line - 1, expressionResult.Region.End.Column - 1); int bracket = 0; for (int i = j; i >= 0 && i < data.Document.Length; i++) { char ch = data.Document.GetCharAt (i); if (Char.IsWhiteSpace (ch)) continue; if (ch == '<') { bracket++; } else if (ch == '>') { bracket--; if (bracket == 0) { expressionResult.Expression += data.Document.GetTextBetween (j, i + 1); expressionResult.ExpressionContext = ExpressionContext.ObjectCreation; resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1)); break; } } else { if (bracket == 0) break; } } // } // To resolve method overloads the full expression must be parsed. // ex.: Overload (1)/ Overload("one") - parsing "Overload" gives just a MethodResolveResult if (resolveResult is MethodResolveResult) resolveResult = resolver.Resolve (expressionFinder.FindFullExpression (txt, wordEnd), new DomLocation (loc.Line + 1, loc.Column + 1)) ?? resolveResult; return resolveResult; }
ResolveResult IResolver.Resolve (ExpressionResult expressionResult, DomLocation resolvePosition) { var expr = expressionResult as PythonExpressionResult; if (expr == null) return null; var doc = ProjectDomService.GetParsedDocument (m_dom, m_filename) as PythonParsedDocument; if (doc == null) return null; var unit = doc.CompilationUnit as PythonCompilationUnit; if (unit == null) return null; if (expr.Type == "def") { var type = unit.GetTypeAt (resolvePosition); if (type != null) { // resolving a method foreach (var func in type.Methods) { if (func.Name == expr.Word) { var l = new List<IMember> (); l.Add (func); return new MethodResolveResult (l); } } } } else if (expr.Type == "class") { var type = unit.GetTypeAt (resolvePosition); if (type != null && type.Name == expr.Word) return new MemberResolveResult (type); } else if (expr.Word == "self") { var type = unit.GetTypeAt (resolvePosition); if (type != null) return new MemberResolveResult (type); } else if (expr.Type == "self") { // looking for a member of self var type = unit.GetTypeAt (resolvePosition); if (type != null) { foreach (var attr in type.Fields) { if (attr.Name == expr.Word) return new MemberResolveResult (attr); } foreach (var method in type.Methods) { if (method.Name == expr.Word) return CreateMethodResult (method); } } } return null; }
Expression ParseExpression(ExpressionResult expressionResult) { if (expressionResult == null || String.IsNullOrEmpty (expressionResult.Expression)) return null; string expr = expressionResult.Expression.Trim (); if (!expr.EndsWith (";")) expr += ";"; using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (this.lang, new StringReader (expr))) { Expression result = parser.ParseExpression(); if (result is BinaryOperatorExpression) { TypeReference typeRef = ParseTypeReference (expressionResult); if (typeRef != null) { return new TypeReferenceExpression (typeRef); } } return result; } }
static TypeReference ParseTypeReference(ExpressionResult expressionResult) { if (expressionResult == null || String.IsNullOrEmpty (expressionResult.Expression)) return null; string expr = expressionResult.Expression.Trim (); using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (SupportedLanguage.CSharp, new StringReader ("typeof(" + expr + ");"))) { TypeOfExpression typeOfExpression = parser.ParseExpression () as TypeOfExpression; if (typeOfExpression != null) return typeOfExpression.TypeReference; } return null; }
public ResolveResult Resolve(ExpressionResult expressionResult, DomLocation resolvePosition) { this.SetupResolver (resolvePosition); ResolveVisitor visitor = new ResolveVisitor (this); ResolveResult result; // System.Console.WriteLine("expressionResult:" + expressionResult); if (unit != null && expressionResult.ExpressionContext == ExpressionContext.AttributeArguments) { string attributeName = NewFSharpExpressionFinder.FindAttributeName (editor, unit, unit.FileName); if (attributeName != null) { IType type = dom.SearchType (new SearchTypeRequest (unit, new DomReturnType (attributeName + "Attribute"), CallingType)); if (type == null) type = dom.SearchType (new SearchTypeRequest (unit, new DomReturnType (attributeName), CallingType)); if (type != null) { foreach (IProperty property in type.Properties) { if (property.Name == expressionResult.Expression) { return new MemberResolveResult (property); } } } } } TypeReference typeRef; if (expressionResult != null && expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.IsObjectCreation) { typeRef = ParseTypeReference (expressionResult); if (typeRef != null) { if (dom.NamespaceExists (typeRef.Type)) { // System.Console.WriteLine("namespace resolve result"); result = new NamespaceResolveResult (typeRef.Type); } else { result = visitor.CreateResult (ConvertTypeReference (typeRef)); } // System.Console.WriteLine("type reference resolve result"); result.ResolvedExpression = expressionResult; if (dom.GetType (result.ResolvedType) != null) return result; } } expr = ParseExpression (expressionResult); // System.Console.WriteLine("parsed expression:" + expr); if (expr == null) { // System.Console.WriteLine("Can't parse expression"); return null; } result = visitor.Resolve (expr); // if (CallingMember == null && result != null) // result.StaticResolve = true; // System.Console.WriteLine("result:" + result + "STATIC" + result.StaticResolve); result.ResolvedExpression = expressionResult; return result; }
public static IReturnType ParseReturnType(ExpressionResult expressionResult) { TypeReference typeReference = ParseTypeReference (expressionResult); if (typeReference == null) return null; return ConvertTypeReference (typeReference); }
public ICompletionDataList HandleKeywordCompletion (CodeCompletionContext completionContext, ExpressionResult result, int wordStart, string word) { if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset); switch (word) { case "using": if (result.ExpressionContext != ExpressionContext.NamespaceNameExcepted) return null; return CreateCompletionData (location, new NamespaceResolveResult (""), result, null); case "namespace": result.ExpressionContext = ExpressionContext.NamespaceNameExcepted; return CreateCompletionData (location, new NamespaceResolveResult (""), result, null); case "case": return CreateCaseCompletionData (location, result); case ",": case ":": if (result.ExpressionContext == ExpressionContext.InheritableType) { IType cls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); CompletionDataList completionList = new ProjectDomCompletionDataList (); List<string> namespaceList = GetUsedNamespaces (); CSharpTextEditorCompletion.CompletionDataCollector col = new CSharpTextEditorCompletion.CompletionDataCollector (dom, completionList, Document.CompilationUnit, null, location); bool isInterface = false; HashSet<string> baseTypeNames = new HashSet<string> (); if (cls != null) { baseTypeNames.Add (cls.Name); if (cls.ClassType == ClassType.Struct) isInterface = true; } int tokenIndex = completionContext.TriggerOffset; // Search base types " : [Type1, ... ,TypeN,] <Caret>" string token = null; do { token = GetPreviousToken (ref tokenIndex, false); if (string.IsNullOrEmpty (token)) break; token = token.Trim (); if (Char.IsLetterOrDigit (token[0]) || token[0] == '_') { IType baseType = dom.SearchType (Document.CompilationUnit, Document.CompilationUnit, token); if (baseType != null) { if (baseType.ClassType != ClassType.Interface) isInterface = true; baseTypeNames.Add (baseType.Name); } } } while (token != ":"); foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) { IType type = o as IType; if (type != null && (type.IsStatic || type.IsSealed || baseTypeNames.Contains (type.Name) || isInterface && type.ClassType != ClassType.Interface)) { continue; } if (o is Namespace && !namespaceList.Any (ns => ns.StartsWith (((Namespace)o).FullName))) continue; col.Add (o); } // Add inner classes Stack<IType> innerStack = new Stack<IType> (); innerStack.Push (cls); while (innerStack.Count > 0) { IType curType = innerStack.Pop (); if (curType == null) continue; foreach (IType innerType in curType.InnerTypes) { if (innerType != cls) // don't add the calling class as possible base type col.Add (innerType); } if (curType.DeclaringType != null) innerStack.Push (curType.DeclaringType); } return completionList; } break; case "is": case "as": { CompletionDataList completionList = new ProjectDomCompletionDataList (); ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - textEditorData.Caret.Offset); NRefactoryResolver resolver = CreateResolver (); ResolveResult resolveResult = resolver.Resolve (expressionResult, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (resolveResult != null && resolveResult.ResolvedType != null) { CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); IType foundType = null; if (word == "as") { ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (textEditorData, Document.CompilationUnit, Document.FileName, resolver.CallingType); if (exactContext is ExpressionContext.TypeExpressionContext) { foundType = resolver.SearchType (((ExpressionContext.TypeExpressionContext)exactContext).Type); AddAsCompletionData (col, foundType); } } if (foundType == null) foundType = resolver.SearchType (resolveResult.ResolvedType); if (foundType != null) { if (foundType.ClassType == ClassType.Interface) foundType = resolver.SearchType (DomReturnType.Object); foreach (IType type in dom.GetSubclasses (foundType)) { if (type.IsSpecialName || type.Name.StartsWith ("<")) continue; AddAsCompletionData (col, type); } } List<string> namespaceList = GetUsedNamespaces (); foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) { if (o is IType) { IType type = (IType)o; if (type.ClassType != ClassType.Interface || type.IsSpecialName || type.Name.StartsWith ("<")) continue; // if (foundType != null && !dom.GetInheritanceTree (foundType).Any (x => x.FullName == type.FullName)) // continue; AddAsCompletionData (col, type); continue; } if (o is Namespace) continue; col.Add (o); } return completionList; } result.ExpressionContext = ExpressionContext.TypeName; return CreateCtrlSpaceCompletionData (completionContext, result); } case "override": // Look for modifiers, in order to find the beginning of the declaration int firstMod = wordStart; int i = wordStart; for (int n = 0; n < 3; n++) { string mod = GetPreviousToken (ref i, true); if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") { firstMod = i; } else if (mod == "static") { // static methods are not overridable return null; } else break; } IType overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (overrideCls == null) overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine - 1, 1)); if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) { string modifiers = textEditorData.GetTextBetween (firstMod, wordStart); return GetOverrideCompletionData (completionContext, overrideCls, modifiers); } return null; case "partial": // Look for modifiers, in order to find the beginning of the declaration firstMod = wordStart; i = wordStart; for (int n = 0; n < 3; n++) { string mod = GetPreviousToken (ref i, true); if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") { firstMod = i; } else if (mod == "static") { // static methods are not overridable return null; } else break; } overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) { string modifiers = textEditorData.GetTextBetween (firstMod, wordStart); return GetPartialCompletionData (completionContext, overrideCls, modifiers); } return null; case "new": IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (textEditorData.Caret.Line, textEditorData.Caret.Column)); ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (textEditorData, Document.CompilationUnit, Document.FileName, callingType); if (newExactContext is ExpressionContext.TypeExpressionContext) return CreateTypeCompletionData (location, callingType, newExactContext, ((ExpressionContext.TypeExpressionContext)newExactContext).Type, ((ExpressionContext.TypeExpressionContext)newExactContext).UnresolvedType); if (newExactContext == null) { int j = completionContext.TriggerOffset - 4; string token = GetPreviousToken (ref j, true); string yieldToken = GetPreviousToken (ref j, true); if (token == "return") { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); IReturnType returnType = resolver.CallingMember.ReturnType; if (yieldToken == "yield" && returnType.GenericArguments.Count > 0) returnType = returnType.GenericArguments[0]; if (resolver.CallingMember != null) return CreateTypeCompletionData (location, callingType, newExactContext, null, returnType); } } return CreateCtrlSpaceCompletionData (completionContext, null); case "if": case "elif": if (stateTracker.Engine.IsInsidePreprocessorDirective) return GetDefineCompletionData (); return null; case "yield": CompletionDataList yieldDataList = new CompletionDataList (); yieldDataList.DefaultCompletionString = "return"; yieldDataList.Add ("break", "md-keyword"); yieldDataList.Add ("return", "md-keyword"); return yieldDataList; case "where": CompletionDataList whereDataList = new CompletionDataList (); NRefactoryResolver constraintResolver = CreateResolver (); constraintResolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (constraintResolver.CallingMember is IMethod) { foreach (ITypeParameter tp in ((IMethod)constraintResolver.CallingMember).TypeParameters) { whereDataList.Add (tp.Name, "md-keyword"); } } else { if (constraintResolver.CallingType != null) { foreach (ITypeParameter tp in constraintResolver.CallingType.TypeParameters) { whereDataList.Add (tp.Name, "md-keyword"); } } } return whereDataList; } if (IsInLinqContext (result)) { if (linqKeywords.Contains (word)) { if (word == "from") // after from no auto code completion. return null; result.Expression = ""; return CreateCtrlSpaceCompletionData (completionContext, result); } CompletionDataList dataList = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); foreach (string kw in linqKeywords) { col.Add (kw, "md-keyword"); } return dataList; } return null; }
public override List<Change> PerformChanges (RefactoringOptions options, object prop) { varCount = 0; selectionStart = selectionEnd = -1; List<Change> result = new List<Change> (); IResolver resolver = options.GetResolver (); INRefactoryASTProvider provider = options.GetASTProvider (); if (resolver == null || provider == null) return result; TextEditorData data = options.GetTextEditorData (); if (data == null) return result; ResolveResult resolveResult; LineSegment lineSegment; ICSharpCode.NRefactory.Ast.CompilationUnit unit = provider.ParseFile (data.Document.Text); MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor visitor = new MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor (resolver, new DomLocation (data.Caret.Line, data.Caret.Column)); if (options.ResolveResult == null) { LoggingService.LogError ("resolve result == null:" + options.ResolveResult); return result; } IMember callingMember = options.ResolveResult.CallingMember; if (callingMember != null) visitor.MemberLocation = new Location (callingMember.Location.Column, callingMember.Location.Line); unit.AcceptVisitor (visitor, null); if (data.IsSomethingSelected) { ExpressionResult expressionResult = new ExpressionResult (data.SelectedText.Trim ()); if (expressionResult.Expression.Contains (" ") || expressionResult.Expression.Contains ("\t")) expressionResult.Expression = "(" + expressionResult.Expression + ")"; resolveResult = resolver.Resolve (expressionResult, new DomLocation (data.Caret.Line, data.Caret.Column)); if (resolveResult == null) return result; IReturnType resolvedType = resolveResult.ResolvedType; if (resolvedType == null || string.IsNullOrEmpty (resolvedType.Name)) resolvedType = DomReturnType.Object; varName = CreateVariableName (resolvedType, visitor); TypeReference returnType; if (resolveResult.ResolvedType == null || string.IsNullOrEmpty (resolveResult.ResolvedType.Name)) { returnType = new TypeReference ("var"); returnType.IsKeyword = true; } else { returnType = options.ShortenTypeName (resolveResult.ResolvedType).ConvertToTypeReference (); } options.ParseMember (resolveResult.CallingMember); TextReplaceChange insert = new TextReplaceChange (); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString ("Insert variable declaration"); LocalVariableDeclaration varDecl = new LocalVariableDeclaration (returnType); varDecl.Variables.Add (new VariableDeclaration (varName, provider.ParseExpression (data.SelectedText))); GetContainingEmbeddedStatementVisitor blockVisitor = new GetContainingEmbeddedStatementVisitor (); blockVisitor.LookupLocation = new Location (data.Caret.Column, data.Caret.Line ); unit.AcceptVisitor (blockVisitor, null); StatementWithEmbeddedStatement containing = blockVisitor.ContainingStatement as StatementWithEmbeddedStatement; if (containing != null && !(containing.EmbeddedStatement is BlockStatement)) { insert.Offset = data.Document.LocationToOffset (containing.StartLocation.Line, containing.StartLocation.Column); lineSegment = data.Document.GetLineByOffset (insert.Offset); insert.RemovedChars = data.Document.LocationToOffset (containing.EndLocation.Line, containing.EndLocation.Column) - insert.Offset; BlockStatement insertedBlock = new BlockStatement (); insertedBlock.AddChild (varDecl); insertedBlock.AddChild (containing.EmbeddedStatement); containing.EmbeddedStatement = insertedBlock; insert.InsertedText = provider.OutputNode (options.Dom, containing, options.GetWhitespaces (lineSegment.Offset)).TrimStart (); int offset, length; if (SearchSubExpression (insert.InsertedText, data.SelectedText, 0, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring (0, offset) + varName + insert.InsertedText.Substring (offset + length); insertOffset = insert.Offset + offset; } } else if (blockVisitor.ContainingStatement is IfElseStatement) { IfElseStatement ifElse = blockVisitor.ContainingStatement as IfElseStatement; insert.Offset = data.Document.LocationToOffset (blockVisitor.ContainingStatement.StartLocation.Line, blockVisitor.ContainingStatement.StartLocation.Column); lineSegment = data.Document.GetLineByOffset (insert.Offset); insert.RemovedChars = data.Document.LocationToOffset (blockVisitor.ContainingStatement.EndLocation.Line, blockVisitor.ContainingStatement.EndLocation.Column) - insert.Offset; BlockStatement insertedBlock = new BlockStatement (); insertedBlock.AddChild (varDecl); if (blockVisitor.ContainsLocation (ifElse.TrueStatement[0])) { insertedBlock.AddChild (ifElse.TrueStatement[0]); ifElse.TrueStatement[0] = insertedBlock; } else { insertedBlock.AddChild (ifElse.FalseStatement[0]); ifElse.FalseStatement[0] = insertedBlock; } insert.InsertedText = provider.OutputNode (options.Dom, blockVisitor.ContainingStatement, options.GetWhitespaces (lineSegment.Offset)); int offset, length; if (SearchSubExpression (insert.InsertedText, provider.OutputNode (options.Dom, insertedBlock), 0, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring (0, offset) + varName + insert.InsertedText.Substring (offset + length); insertOffset = insert.Offset + offset; } } else { lineSegment = data.Document.GetLine (data.Caret.Line); insert.Offset = lineSegment.Offset; insert.InsertedText = options.GetWhitespaces (lineSegment.Offset) + provider.OutputNode (options.Dom, varDecl) + Environment.NewLine; insertOffset = insert.Offset + options.GetWhitespaces (lineSegment.Offset).Length + provider.OutputNode (options.Dom, varDecl.TypeReference).Length + " ".Length; TextReplaceChange replace = new TextReplaceChange (); replace.FileName = options.Document.FileName; replace.Offset = data.SelectionRange.Offset; replace.RemovedChars = data.SelectionRange.Length; replace.InsertedText = varName; result.Add (replace); replaceOffset = replace.Offset; if (insert.Offset < replaceOffset) replaceOffset += insert.InsertedText.Length - insert.RemovedChars; varCount++; } result.Add (insert); varCount++; selectionStart = insert.Offset; return result; } lineSegment = data.Document.GetLine (data.Caret.Line); string line = data.Document.GetTextAt (lineSegment); Expression expression = provider.ParseExpression (line); if (expression == null) return result; resolveResult = resolver.Resolve (new ExpressionResult (line), new DomLocation (options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column)); if (resolveResult.ResolvedType != null && !string.IsNullOrEmpty (resolveResult.ResolvedType.FullName)) { TextReplaceChange insert = new TextReplaceChange (); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString ("Insert variable declaration"); insert.Offset = lineSegment.Offset + options.GetWhitespaces (lineSegment.Offset).Length; varName = CreateVariableName (resolveResult.ResolvedType, visitor); LocalVariableDeclaration varDecl = new LocalVariableDeclaration (options.ShortenTypeName (resolveResult.ResolvedType).ConvertToTypeReference ()); varDecl.Variables.Add (new VariableDeclaration (varName, expression)); insert.RemovedChars = expression.EndLocation.Column - 1; insert.InsertedText = provider.OutputNode (options.Dom, varDecl); insertOffset = insert.Offset + provider.OutputNode (options.Dom, varDecl.TypeReference).Length + " ".Length; result.Add (insert); varCount++; int idx = 0; while (idx < insert.InsertedText.Length - varName.Length) { if (insert.InsertedText.Substring (idx, varName.Length) == varName && (idx == 0 || insert.InsertedText[idx - 1] == ' ') && (idx == insert.InsertedText.Length - varName.Length - 1 || insert.InsertedText[idx + varName.Length] == ' ')) { selectionStart = insert.Offset + idx; selectionEnd = selectionStart + varName.Length; break; } idx++; } } return result; }
public override object VisitIdentifierExpression (ICSharpCode.NRefactory.Ast.IdentifierExpression identifierExpression, object data) { if (!variables.ContainsKey (identifierExpression.Identifier)) { ExpressionResult expressionResult = new ExpressionResult (identifierExpression.Identifier); ResolveResult result = resolver.Resolve (expressionResult, position); MemberResolveResult mrr = result as MemberResolveResult; ReferencesMember |= mrr != null && mrr.ResolvedMember != null && !mrr.ResolvedMember.IsStatic; if (!(result is LocalVariableResolveResult || result is ParameterResolveResult)) return base.VisitIdentifierExpression (identifierExpression, data); // result.ResolvedType == null may be true for namespace names or undeclared variables if (!result.StaticResolve && !variables.ContainsKey (identifierExpression.Identifier)) { variables[identifierExpression.Identifier] = new VariableDescriptor (identifierExpression.Identifier) { InitialValueUsed = !valueGetsChanged, Location = new DocumentLocation (MemberLocation.Line + identifierExpression.StartLocation.Line, identifierExpression.StartLocation.Column) }; variables[identifierExpression.Identifier].ReturnType = result.ResolvedType; } if (result != null && !result.StaticResolve && result.ResolvedType != null && !(result is MethodResolveResult) && !(result is NamespaceResolveResult) && !(result is MemberResolveResult)) unknownVariables.Add (new KeyValuePair <string, IReturnType> (identifierExpression.Identifier, result.ResolvedType)); } return base.VisitIdentifierExpression (identifierExpression, data); }