void FindReferencesButtonClick(object sender, EventArgs e) { if (csharpTreeView.SelectedNode == null) { return; } SimpleProjectContent project = new SimpleProjectContent(); var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); project.UpdateProjectContent(null, parsedFile); List <ITypeResolveContext> projects = new List <ITypeResolveContext>(); projects.Add(project); projects.AddRange(builtInLibs.Value); using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { CSharpResolver resolver = new CSharpResolver(context); AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag; IResolveVisitorNavigator navigator = new NodeListResolveVisitorNavigator(new[] { node }); ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); visitor.Scan(compilationUnit); IEntity entity; MemberResolveResult mrr = visitor.GetResolveResult(node) as MemberResolveResult; TypeResolveResult trr = visitor.GetResolveResult(node) as TypeResolveResult; if (mrr != null) { entity = mrr.Member; } else if (trr != null) { entity = trr.Type.GetDefinition(); } else { return; } FindReferences fr = new FindReferences(); int referenceCount = 0; FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { referenceCount++; }; var searchScopes = fr.GetSearchScopes(entity); navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); visitor = new ResolveVisitor(resolver, parsedFile, navigator); visitor.Scan(compilationUnit); csharpTreeView.BeginUpdate(); ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); csharpTreeView.EndUpdate(); MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); } }
public static ResolveResult Resolve(ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, CancellationToken cancellationToken = default(CancellationToken)) { AstNode node = cu.GetNodeAt(location); if (node == null) return null; AstNode resolvableNode; if (node is AstType) { resolvableNode = node; if (resolvableNode.Parent is ComposedType) { while (resolvableNode.Parent is ComposedType) resolvableNode = resolvableNode.Parent; //node is preffered over the resolvable node. Which shouldn't be done in the case of nullables, arrays etc. node = resolvableNode; } } else if (node is Identifier) { resolvableNode = node.Parent; } else if (node.NodeType == NodeType.Token) { if (node.Parent is ConstructorInitializer) { resolvableNode = node.Parent; } else { return null; } } else { // don't resolve arbitrary nodes - we don't want to show tooltips for everything return null; } if (resolvableNode != null && resolvableNode.Parent is ObjectCreateExpression) { resolvableNode = resolvableNode.Parent; } InvocationExpression parentInvocation = null; if ((resolvableNode is IdentifierExpression || resolvableNode is MemberReferenceExpression || resolvableNode is PointerReferenceExpression)) { // we also need to resolve the invocation parentInvocation = resolvableNode.Parent as InvocationExpression; } IResolveVisitorNavigator navigator; if (parentInvocation != null) navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode, parentInvocation }); else navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode }); CSharpResolver resolver = new CSharpResolver(compilation); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); v.Scan(cu); // Prefer the RR from the token itself, if it was assigned a ResolveResult // (this can happen with the identifiers in various nodes such as catch clauses or foreach statements) ResolveResult rr = v.GetResolveResult(node) ?? v.GetResolveResult(resolvableNode); if (rr is MethodGroupResolveResult && parentInvocation != null) return v.GetResolveResult(parentInvocation); else return rr; }
string Convert(Expression expr) { ResolveVisitor rv = new ResolveVisitor(resolver, null); rv.Scan(expr); var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv); StringWriter writer = new StringWriter(); writer.NewLine = " "; new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); return Regex.Replace(writer.ToString(), @"\s+", " "); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: outside the root node).</param> /// <param name="rootNode">The root node of the resolved tree.</param> /// <param name="parsedFile">The parsed file for the nodes being resolved. This parameter is used only /// when the root node is on the type level; it is not necessary when an expression is passed. /// This parameter may be null.</param> public CppAstResolver(CppResolver resolver, AstNode rootNode, CppParsedFile parsedFile = null) { if (resolver == null) throw new ArgumentNullException("resolver"); if (rootNode == null) throw new ArgumentNullException("rootNode"); this.initialResolverState = resolver; this.rootNode = rootNode; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor) { if (rootStatement == null) { throw new ArgumentNullException("rootStatement"); } if (resolveVisitor == null) { throw new ArgumentNullException("resolveVisitor"); } this.resolveVisitor = resolveVisitor; this.cancellationToken = resolveVisitor.CancellationToken; visitor.analysis = this; if (resolveVisitor.TypeResolveContext is MinimalResolveContext) { cfgBuilder.EvaluateOnlyPrimitiveConstants = true; } allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolveVisitor).Cast <DefiniteAssignmentNode>()); for (int i = 0; i < allNodes.Count; i++) { DefiniteAssignmentNode node = allNodes[i]; node.Index = i; // assign numbers to the nodes if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) { // Anonymous methods have separate control flow graphs, but we also need to analyze those. // Iterate backwards so that anonymous methods are inserted in the correct order for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling) { InsertAnonymousMethods(i + 1, child); } } // Now register the node in the dictionaries: if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) { beginNodeDict.Add(node.NextStatement, node); } if (node.Type == ControlFlowNodeType.BetweenStatements || node.Type == ControlFlowNodeType.EndNode) { endNodeDict.Add(node.PreviousStatement, node); } if (node.Type == ControlFlowNodeType.LoopCondition) { conditionNodeDict.Add(node.NextStatement, node); } } // Verify that we created nodes for all statements: Debug.Assert(!rootStatement.DescendantsAndSelf.OfType <Statement>().Except(allNodes.Select(n => n.NextStatement)).Any()); // Verify that we put all nodes into the dictionaries: Debug.Assert(rootStatement.DescendantsAndSelf.OfType <Statement>().All(stmt => beginNodeDict.ContainsKey(stmt))); Debug.Assert(rootStatement.DescendantsAndSelf.OfType <Statement>().All(stmt => endNodeDict.ContainsKey(stmt))); this.analyzedRangeStart = 0; this.analyzedRangeEnd = allNodes.Count - 1; }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="compilationUnit">The compilation unit corresponding to the specified parsed file.</param> /// <param name="parsedFile"> /// Optional: Result of the <see cref="TypeSystemConvertVisitor"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The parsed file must be registered in the compilation. /// </para> /// <para> /// When a parsedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no parsedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile = null) { if (compilation == null) throw new ArgumentNullException("compilation"); if (compilationUnit == null) throw new ArgumentNullException("compilationUnit"); this.initialResolverState = new CSharpResolver(compilation); this.rootNode = compilationUnit; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="syntaxTree">The syntax tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile = null) { if (compilation == null) throw new ArgumentNullException("compilation"); if (syntaxTree == null) throw new ArgumentNullException("syntaxTree"); this.initialResolverState = new CSharpResolver(compilation); this.rootNode = syntaxTree; this.unresolvedFile = unresolvedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile); }
/// <summary> /// Creates a new BVE5 AST resolver. /// Use this overload if you are resolving within a complete BVE5 file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="syntaxTree">The syntax tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public BVE5AstResolver(ICompilation compilation, SyntaxTree syntaxTree, BVE5UnresolvedFile unresolvedFile = null) { if(compilation == null) throw new ArgumentNullException("compilation"); if(syntaxTree == null) throw new ArgumentNullException("syntaxTree"); initial_resolver_state = new BVE5Resolver(compilation); root_node = syntaxTree; unresolved_file = unresolvedFile; resolve_visitor = new ResolveVisitor(initial_resolver_state, unresolvedFile); }
/// <summary> /// Creates a new BVE5 AST resolver. /// Use this overload if you are resolving within a complete BVE5 file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="syntaxTree">The syntax tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When the unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public BVE5AstResolver(BVE5Compilation compilation, SyntaxTree syntaxTree, BVE5UnresolvedFile unresolvedFile = null) { if(compilation == null) throw new ArgumentNullException("compilation"); if(syntaxTree == null) throw new ArgumentNullException("syntaxTree"); initial_resolver_state = new BVE5Resolver(compilation); root_node = syntaxTree; unresolved_file = unresolvedFile; resolve_visitor = new ResolveVisitor(initial_resolver_state, unresolvedFile, FileKindHelper.GetTypeNameFromFileKind(syntaxTree.Kind)); }
string Convert(Expression expr) { ResolveVisitor rv = new ResolveVisitor(resolver, null); rv.Scan(expr); var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv); StringWriter writer = new StringWriter(); writer.NewLine = " "; new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); return(Regex.Replace(writer.ToString(), @"\s+", " ")); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: outside the root node).</param> /// <param name="rootNode">The root node of the resolved tree.</param> /// <param name="parsedFile">The parsed file for the nodes being resolved. This parameter is used only /// when the root node is on the type level; it is not necessary when an expression is passed. /// This parameter may be null.</param> public CppAstResolver(CppResolver resolver, AstNode rootNode, CppParsedFile parsedFile = null) { if (resolver == null) { throw new ArgumentNullException("resolver"); } if (rootNode == null) { throw new ArgumentNullException("rootNode"); } this.initialResolverState = resolver; this.rootNode = rootNode; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: just outside the root node).</param> /// <param name="rootNode">The root node of the tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpUnresolvedFile unresolvedFile = null) { if (resolver == null) { throw new ArgumentNullException("resolver"); } if (rootNode == null) { throw new ArgumentNullException("rootNode"); } this.initialResolverState = resolver; this.rootNode = rootNode; this.unresolvedFile = unresolvedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile); }
public HlslVisitor(BlockStatement block, CustomAttribute attr, ResolveVisitor resolver, DecompilerContext ctx) : this() { _attr = attr; _resolver = resolver; _resolver.Scan(block); var trans1 = new ReplaceMethodCallsWithOperators(ctx); var trans2 = new RenameLocals(); ((IAstTransform)trans1).Run(block); trans2.Run(block); Result = block.AcceptVisitor(this, 0).ToString(); Result += Environment.NewLine; }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="syntaxTree">The syntax tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile = null) { if (compilation == null) { throw new ArgumentNullException("compilation"); } if (syntaxTree == null) { throw new ArgumentNullException("syntaxTree"); } this.initialResolverState = new CSharpResolver(compilation); this.rootNode = syntaxTree; this.unresolvedFile = unresolvedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile); }
public HlslVisitor(BlockStatement block, CustomAttribute attr, ResolveVisitor resolver, DecompilerContext ctx) : this() { _attr = attr; _resolver = resolver; _resolver.Scan(block); var trans1 = new ReplaceMethodCallsWithOperators(ctx); var trans2 = new RenameLocals(); ((IAstTransform)trans1).Run(block); trans2.Run(block); Result = block.AcceptVisitor(this, 0).ToString(); Result += Environment.NewLine; }
public IList <ControlFlowNode> BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor) { if (statement == null) { throw new ArgumentNullException("statement"); } if (resolveVisitor == null) { throw new ArgumentNullException("resolveVisitor"); } NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor(); nodeCreationVisitor.builder = this; try { this.nodes = new List <ControlFlowNode>(); this.labels = new Dictionary <string, ControlFlowNode>(); this.gotoStatements = new List <ControlFlowNode>(); this.rootStatement = statement; this.resolveVisitor = resolveVisitor; ControlFlowNode entryPoint = CreateStartNode(statement); statement.AcceptVisitor(nodeCreationVisitor, entryPoint); // Resolve goto statements: foreach (ControlFlowNode gotoStmt in gotoStatements) { string label = ((GotoStatement)gotoStmt.NextStatement).Label; ControlFlowNode labelNode; if (labels.TryGetValue(label, out labelNode)) { nodeCreationVisitor.Connect(gotoStmt, labelNode, ControlFlowEdgeType.Jump); } } AnnotateLeaveEdgesWithTryFinallyBlocks(); return(nodes); } finally { this.nodes = null; this.labels = null; this.gotoStatements = null; this.rootStatement = null; this.resolveVisitor = null; } }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="parsedFile"> /// Result of the <see cref="TypeSystemConvertVisitor"/> for the file being passed. This is used for setting up the context on the resolver. The parsed file must be registered in the compilation. /// </param> /// <param name="compilationUnit">The compilation unit corresponding to the specified parsed file.</param> public CppAstResolver(ICompilation compilation, CompilationUnit compilationUnit, CppParsedFile parsedFile) { if (compilation == null) { throw new ArgumentNullException("compilation"); } if (parsedFile == null) { throw new ArgumentNullException("parsedFile"); } if (compilationUnit == null) { throw new ArgumentNullException("compilationUnit"); } this.initialResolverState = new CppResolver(compilation); this.rootNode = compilationUnit; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
void ShowResolveResultsInTree(TreeNodeCollection c, ResolveVisitor v) { foreach (TreeNode t in c) { AstNode node = t.Tag as AstNode; if (node != null) { ResolveResult rr = v.GetResolveResult(node); if (rr != null) { t.Text = GetNodeTitle(node) + " " + rr.ToString(); } else { t.Text = GetNodeTitle(node); } } ShowResolveResultsInTree(t.Nodes, v); } }
/// <summary> /// Public translation interface. /// Translates the given method to HLSL /// </summary> /// <param name="s">Shader type definition.</param> /// <param name="m">A method representing a shader to translate.</param> /// <param name="attr">The shader type as attribute (either FragmentShaderAttribute or VertexShaderAttribute</param> /// <param name="type">The shader type as ShaderType</param> /// <returns>The translated GLSL shader source</returns> public FunctionDescription Transform(TypeDefinition s, MethodDefinition m, CustomAttribute attr, ShaderType type) { if (s == null) { throw new ArgumentNullException("s"); } if (m == null) { throw new ArgumentNullException("m"); } if (attr == null) { throw new ArgumentNullException("attr"); } var sbase = s.BaseType.Resolve(); while (sbase.MetadataToken.ToInt32() != typeof(Shader).MetadataToken) { sbase = sbase.BaseType.Resolve(); } var dctx = new DecompilerContext(s.Module) { CurrentType = s, CurrentMethod = m, CancellationToken = CancellationToken.None }; var d = AstMethodBodyBuilder.CreateMethodBody(m, dctx); //var ctx = new CecilTypeResolveContext(sbase.Module); var loader = new CecilLoader(); var mscorlib = loader.LoadAssemblyFile(typeof(object).Assembly.Location); var slsharp = loader.LoadAssembly(sbase.Module.Assembly); var project = loader.LoadAssembly(s.Module.Assembly); var ctx = new CompositeTypeResolveContext(new[] { project, slsharp, mscorlib }); var resolver = new CSharpResolver(ctx, CancellationToken.None) { UsingScope = new UsingScope(project) }; /* * foreach (var v in m.Body.Variables) * { * resolver.AddVariable(v.VariableType, null, v.Name) * }*/ //resolver.AddVariable() //resolver.LocalVariables = m.Body.Variables; // TODO: need a more sane way to get the correct class + member var ss = ctx.GetAllTypes().First(c => c.FullName == s.FullName); resolver.CurrentTypeDefinition = ss; resolver.CurrentMember = ss.Methods.First(n => SameMethod(m, n, ctx)); var rv = new ResolveVisitor(resolver, new ParsedFile("memory", resolver.UsingScope), null); var glsl = new HlslVisitor(d, attr, rv, dctx); _functions.UnionWith(glsl.Functions); var entry = (bool)attr.ConstructorArguments.FirstOrDefault().Value; var sig = HlslVisitor.GetSignature(m); var code = glsl.Result; var desc = new FunctionDescription(Shader.GetMethodName(m), sig + code, entry, type); _dependencies.UnionWith(glsl.Dependencies); return(desc); }
/// <summary> /// Public translation interface. /// Translates the given method to HLSL /// </summary> /// <param name="s">Shader type definition.</param> /// <param name="m">A method representing a shader to translate.</param> /// <param name="attr">The shader type as attribute (either FragmentShaderAttribute or VertexShaderAttribute</param> /// <param name="type">The shader type as ShaderType</param> /// <returns>The translated GLSL shader source</returns> public FunctionDescription Transform(TypeDefinition s, MethodDefinition m, CustomAttribute attr, ShaderType type) { if (s == null) throw new ArgumentNullException("s"); if (m == null) throw new ArgumentNullException("m"); if (attr == null) throw new ArgumentNullException("attr"); var sbase = s.BaseType.Resolve(); while (sbase.MetadataToken.ToInt32() != typeof(Shader).MetadataToken) sbase = sbase.BaseType.Resolve(); var dctx = new DecompilerContext(s.Module) { CurrentType = s, CurrentMethod = m, CancellationToken = CancellationToken.None }; var d = AstMethodBodyBuilder.CreateMethodBody(m, dctx); //var ctx = new CecilTypeResolveContext(sbase.Module); var loader = new CecilLoader(); var mscorlib = loader.LoadAssemblyFile(typeof(object).Assembly.Location); var slsharp = loader.LoadAssembly(sbase.Module.Assembly); var project = loader.LoadAssembly(s.Module.Assembly); var ctx = new CompositeTypeResolveContext(new[] { project, slsharp, mscorlib }); var resolver = new CSharpResolver(ctx, CancellationToken.None) {UsingScope = new UsingScope(project)}; /* foreach (var v in m.Body.Variables) { resolver.AddVariable(v.VariableType, null, v.Name) }*/ //resolver.AddVariable() //resolver.LocalVariables = m.Body.Variables; // TODO: need a more sane way to get the correct class + member var ss = ctx.GetAllTypes().First(c => c.FullName == s.FullName); resolver.CurrentTypeDefinition = ss; resolver.CurrentMember = ss.Methods.First(n => SameMethod(m, n, ctx)); var rv = new ResolveVisitor(resolver, new ParsedFile("memory", resolver.UsingScope), null); var glsl = new HlslVisitor(d, attr, rv, dctx); _functions.UnionWith(glsl.Functions); var entry = (bool)attr.ConstructorArguments.FirstOrDefault().Value; var sig = HlslVisitor.GetSignature(m); var code = glsl.Result; var desc = new FunctionDescription(Shader.GetMethodName(m), sig + code, entry, type); _dependencies.UnionWith(glsl.Dependencies); return desc; }
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(CSharpParsedFile file, AstNode expr, CompilationUnit unit) { if (expr == null) return null; AstNode resolveNode; if (expr is Expression || expr is AstType) { resolveNode = expr; } else if (expr is VariableDeclarationStatement) { resolveNode = ((VariableDeclarationStatement)expr).Type; } else { resolveNode = expr; } // var newContent = ProjectContent.UpdateProjectContent (CSharpParsedFile, file); var csResolver = new CSharpResolver (ctx); var navigator = new NodeListResolveVisitorNavigator (new[] { resolveNode }); var visitor = new ResolveVisitor (csResolver, CSharpParsedFile, navigator); visitor.Scan (unit); var state = visitor.GetResolverStateBefore (resolveNode); var result = visitor.GetResolveResult (resolveNode); return Tuple.Create (result, state); }
IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace) { switch (completionChar) { // Magic key completion case ':': case '.': if (IsInsideCommentOrString ()) return Enumerable.Empty<ICompletionData> (); var expr = GetExpressionBeforeCursor (); if (expr == null) return null; // do not complete <number>. (but <number>.<number>.) if (expr.Item2 is PrimitiveExpression) { var pexpr = (PrimitiveExpression)expr.Item2; if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains ('.')) return null; } var resolveResult = ResolveExpression (expr.Item1, expr.Item2, expr.Item3); if (resolveResult == null) return null; if (expr.Item2 is AstType) return CreateTypeAndNamespaceCompletionData (location, resolveResult.Item1, expr.Item2, resolveResult.Item2); return CreateCompletionData (location, resolveResult.Item1, expr.Item2, resolveResult.Item2); case '#': if (IsInsideCommentOrString ()) return null; return GetDirectiveCompletionData (); // XML doc completion case '<': if (IsInsideDocComment ()) return GetXmlDocumentationCompletionData (); if (controlSpace) return DefaultControlSpaceItems (); return null; case '>': if (!IsInsideDocComment ()) return null; string lineText = document.GetText (document.GetLineByNumber (location.Line)); int startIndex = Math.Min (location.Column - 1, lineText.Length - 1); while (startIndex >= 0 && lineText [startIndex] != '<') { --startIndex; if (lineText [startIndex] == '/') { // already closed. startIndex = -1; break; } } if (startIndex >= 0) { int endIndex = startIndex; while (endIndex <= location.Column && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText [endIndex])) { endIndex++; } string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null; if (!string.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) document.Insert (offset, "</" + tag + ">"); } return null; // Parameter completion case '(': if (IsInsideCommentOrString ()) return null; var invoke = GetInvocationBeforeCursor (true); if (invoke == null) return null; if (invoke.Item2 is TypeOfExpression) return CreateTypeList (); var invocationResult = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); if (invocationResult == null) return null; var methodGroup = invocationResult.Item1 as MethodGroupResolveResult; if (methodGroup != null) return CreateParameterCompletion (methodGroup, invocationResult.Item2, invoke.Item2, 0, controlSpace); if (controlSpace) return DefaultControlSpaceItems (invoke); return null; case '=': return controlSpace ? DefaultControlSpaceItems () : null; case ',': int cpos2; if (!GetParameterCompletionCommandOffset (out cpos2)) return null; // completionContext = CompletionWidget.CreateCodeCompletionContext (cpos2); // int currentParameter2 = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, completionContext) - 1; // return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.MethodBody, provider.Methods, currentParameter); break; // Completion on space: case ' ': if (IsInsideCommentOrString ()) return null; int tokenIndex = offset; string token = GetPreviousToken (ref tokenIndex, false); // check propose name, for context <variable name> <ctrl+space> (but only in control space context) //IType isAsType = null; var isAsExpression = GetExpressionAt (offset); if (controlSpace && isAsExpression != null && isAsExpression.Item2 is VariableDeclarationStatement && token != "new") { var parent = isAsExpression.Item2 as VariableDeclarationStatement; var proposeNameList = new CompletionDataWrapper (this); foreach (var possibleName in GenerateNameProposals (parent.Type)) { if (possibleName.Length > 0) proposeNameList.Result.Add (factory.CreateLiteralCompletionData (possibleName.ToString ())); } AutoSelect = false; AutoCompleteEmptyMatch = false; return proposeNameList.Result; } // int tokenIndex = offset; // string token = GetPreviousToken (ref tokenIndex, false); // if (result.ExpressionContext == ExpressionContext.ObjectInitializer) { // resolver = CreateResolver (); // ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (document, resolver.Unit, Document.FileName, resolver.CallingType); // IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType; // if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ",")) // return CreateCtrlSpaceCompletionData (completionContext, result); // } if (token == "=") { int j = tokenIndex; string prevToken = GetPreviousToken (ref j, false); if (prevToken == "=" || prevToken == "+" || prevToken == "-") { token = prevToken + token; tokenIndex = j; } } switch (token) { case "(": case ",": int cpos; if (!GetParameterCompletionCommandOffset (out cpos)) break; int currentParameter = GetCurrentParameterIndex (cpos, 0) - 1; if (currentParameter < 0) return null; invoke = GetInvocationBeforeCursor (token == "("); if (invoke == null) return null; invocationResult = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); if (invocationResult == null) return null; methodGroup = invocationResult.Item1 as MethodGroupResolveResult; if (methodGroup != null) return CreateParameterCompletion (methodGroup, invocationResult.Item2, invoke.Item2, currentParameter, controlSpace); return null; case "=": case "==": GetPreviousToken (ref tokenIndex, false); var expressionOrVariableDeclaration = GetExpressionAt (tokenIndex); if (expressionOrVariableDeclaration == null) return null; resolveResult = ResolveExpression (expressionOrVariableDeclaration.Item1, expressionOrVariableDeclaration.Item2, expressionOrVariableDeclaration.Item3); if (resolveResult == null) return null; if (resolveResult.Item1.Type.Kind == TypeKind.Enum) { var wrapper = new CompletionDataWrapper (this); AddContextCompletion (wrapper, resolveResult.Item2, expressionOrVariableDeclaration.Item2); AddEnumMembers (wrapper, resolveResult.Item1.Type, resolveResult.Item2); AutoCompleteEmptyMatch = false; return wrapper.Result; } // // if (resolvedType.FullName == DomReturnType.Bool.FullName) { // CompletionDataList completionList = new ProjectDomCompletionDataList (); // CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location); // completionList.AutoCompleteEmptyMatch = false; // cdc.Add ("true", "md-keyword"); // cdc.Add ("false", "md-keyword"); // resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc); // return completionList; // } // if (resolvedType.ClassType == ClassType.Delegate && token == "=") { // CompletionDataList completionList = new ProjectDomCompletionDataList (); // string parameterDefinition = AddDelegateHandlers (completionList, resolvedType); // string varName = GetPreviousMemberReferenceExpression (tokenIndex); // completionList.Add (new EventCreationCompletionData (document, varName, resolvedType, null, parameterDefinition, resolver.CallingMember, resolvedType)); // // CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location); // resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc); // foreach (var data in completionList) { // if (data is MemberCompletionData) // ((MemberCompletionData)data).IsDelegateExpected = true; // } // return completionList; // } return null; case "+=": case "-=": GetPreviousToken (ref tokenIndex, false); expressionOrVariableDeclaration = GetExpressionAt (tokenIndex); if (expressionOrVariableDeclaration == null) return null; resolveResult = ResolveExpression (expressionOrVariableDeclaration.Item1, expressionOrVariableDeclaration.Item2, expressionOrVariableDeclaration.Item3); if (resolveResult == null) return null; var mrr = resolveResult.Item1 as MemberResolveResult; if (mrr != null) { var evt = mrr.Member as IEvent; if (evt == null) return null; var delegateType = evt.ReturnType; if (delegateType.Kind != TypeKind.Delegate) return null; var wrapper = new CompletionDataWrapper (this); if (currentType != null) { // bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType); foreach (var method in currentType.Methods) { if (MatchDelegate (delegateType, method) /*&& method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) { wrapper.AddMember (method); // data.SetText (data.CompletionText + ";"); } } } if (token == "+=") { string parameterDefinition = AddDelegateHandlers (wrapper, delegateType); string varName = GetPreviousMemberReferenceExpression (tokenIndex); wrapper.Result.Add (factory.CreateEventCreationCompletionData (varName, delegateType, evt, parameterDefinition, currentMember, currentType)); } return wrapper.Result; } return null; case ":": if (currentMember == null) { var wrapper = new CompletionDataWrapper (this); AddTypesAndNamespaces (wrapper, GetState (), null, t => currentType != null ? !currentType.Equals (t) : true); return wrapper.Result; } return null; } var keywordCompletion = HandleKeywordCompletion (tokenIndex, token); if (keywordCompletion == null && controlSpace) goto default; return keywordCompletion; // Automatic completion default: if (IsInsideCommentOrString ()) return null; if (IsInLinqContext (offset)) { tokenIndex = offset; token = GetPreviousToken (ref tokenIndex, false); // token last typed if (linqKeywords.Contains (token)) { if (token == "from") // after from no auto code completion. return null; return DefaultControlSpaceItems (); } var dataList = new CompletionDataWrapper (this); AddKeywords (dataList, linqKeywords); return dataList.Result; } if (currentType != null && currentType.Kind == TypeKind.Enum) return HandleEnumContext (); var contextList = new CompletionDataWrapper (this); var identifierStart = GetExpressionAtCursor (); if (identifierStart != null && identifierStart.Item2 is TypeParameterDeclaration) return null; if (identifierStart != null && identifierStart.Item2 is VariableInitializer && location <= ((VariableInitializer)identifierStart.Item2).NameToken.EndLocation) { return controlSpace ? HandleAccessorContext () ?? DefaultControlSpaceItems (identifierStart) : null; } if (!(char.IsLetter (completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null || !(identifierStart.Item2 is ArrayInitializerExpression))) { return controlSpace ? HandleAccessorContext () ?? DefaultControlSpaceItems (identifierStart) : null; } char prevCh = offset > 2 ? document.GetCharAt (offset - 2) : ';'; char nextCh = offset < document.TextLength ? document.GetCharAt (offset) : ' '; const string allowedChars = ";,[](){}+-*/%^?:&|~!<>="; if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0) return null; if (!(Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0)) return null; // Do not pop up completion on identifier identifier (should be handled by keyword completion). tokenIndex = offset - 1; token = GetPreviousToken (ref tokenIndex, false); int prevTokenIndex = tokenIndex; var prevToken2 = GetPreviousToken (ref prevTokenIndex, false); if (identifierStart == null && !string.IsNullOrEmpty (token) && !(IsInsideComment (tokenIndex) || IsInsideString (tokenIndex)) && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) { char last = token [token.Length - 1]; if (char.IsLetterOrDigit (last) || last == '_' || token == ">") { return HandleKeywordCompletion (tokenIndex, token); } } if (identifierStart == null) return HandleAccessorContext () ?? DefaultControlSpaceItems (); CSharpResolver csResolver; AstNode n = identifierStart.Item2; // Handle foreach (type name _ if (n is IdentifierExpression) { var prev = n.GetPrevNode () as ForeachStatement; if (prev != null && prev.InExpression.IsNull) { if (controlSpace) { contextList.AddCustom ("in"); return contextList.Result; } return null; } } if (n is Identifier && n.Parent is ForeachStatement) { if (controlSpace) return DefaultControlSpaceItems (); return null; } if (n is ArrayInitializerExpression) { // check for new [] {...} expression -> no need to resolve the type there var parent = n.Parent as ArrayCreateExpression; if (parent != null && parent.Type.IsNull) return DefaultControlSpaceItems (); var initalizerResult = ResolveExpression (identifierStart.Item1, n.Parent, identifierStart.Item3); var concreteNode = identifierStart.Item3.GetNodeAt<IdentifierExpression> (location); // check if we're on the right side of an initializer expression if (concreteNode != null && concreteNode.Parent != null && concreteNode.Parent.Parent != null && concreteNode.Identifier != "a" && concreteNode.Parent.Parent is NamedExpression) { return DefaultControlSpaceItems (); } if (initalizerResult != null && initalizerResult.Item1.Type.Kind != TypeKind.Unknown) { foreach (var property in initalizerResult.Item1.Type.GetProperties ()) { if (!property.IsPublic) continue; contextList.AddMember (property); } foreach (var field in initalizerResult.Item1.Type.GetFields ()) { if (!field.IsPublic) continue; contextList.AddMember (field); } return contextList.Result; } Console.WriteLine ("blub"); return DefaultControlSpaceItems (); } if (n != null/* && !(identifierStart.Item2 is TypeDeclaration)*/) { csResolver = new CSharpResolver (ctx); var nodes = new List<AstNode> (); nodes.Add (n); if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) nodes.Add (n.Parent); var navigator = new NodeListResolveVisitorNavigator (nodes); var visitor = new ResolveVisitor (csResolver, identifierStart.Item1, navigator); visitor.Scan (identifierStart.Item3); try { csResolver = visitor.GetResolverStateBefore (n); } catch (Exception) { csResolver = GetState (); } // add attribute properties. if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) { var resolved = visitor.GetResolveResult (n.Parent); if (resolved != null && resolved.Type != null) { foreach (var property in resolved.Type.GetProperties (p => p.Accessibility == Accessibility.Public)) { contextList.AddMember (property); } foreach (var field in resolved.Type.GetFields (p => p.Accessibility == Accessibility.Public)) { contextList.AddMember (field); } } } } else { csResolver = GetState (); } // identifier has already started with the first letter offset--; AddContextCompletion (contextList, csResolver, identifierStart.Item2); return contextList.Result; // if (stub.Parent is BlockStatement) // result = FindExpression (dom, completionContext, -1); // if (result == null) // return null; // else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) { // triggerWordLength = 1; // bool autoSelect = true; // IType returnType = null; // if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) { // ctx = CompletionWidget.CreateCodeCompletionContext (cpos); // NRefactoryParameterDataProvider dataProvider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider; // if (dataProvider != null) { // int i = dataProvider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1; // foreach (var method in dataProvider.Methods) { // if (i < method.Parameters.Count) { // returnType = dom.GetType (method.Parameters [i].ReturnType); // autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate; // break; // } // } // } // } // // Bug 677531 - Auto-complete doesn't always highlight generic parameter in method signature // //if (result.ExpressionContext == ExpressionContext.TypeName) // // autoSelect = false; // CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result); // AddEnumMembers (dataList, returnType); // dataList.AutoSelect = autoSelect; // return dataList; // } else { // result = FindExpression (dom, completionContext, 0); // tokenIndex = offset; // // // check foreach case, unfortunately the expression finder is too dumb to handle full type names // // should be overworked if the expression finder is replaced with a mcs ast based analyzer. // var possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // starting letter // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varname // // // read return types to '(' token // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varType // if (possibleForeachToken == ">") { // while (possibleForeachToken != null && possibleForeachToken != "(") { // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // } // } else { // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // ( // if (possibleForeachToken == ".") // while (possibleForeachToken != null && possibleForeachToken != "(") // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // } // possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // foreach // // if (possibleForeachToken == "foreach") { // result.ExpressionContext = ExpressionContext.ForeachInToken; // } else { // return null; // // result.ExpressionContext = ExpressionContext.IdentifierExpected; // } // result.Expression = ""; // result.Region = DomRegion.Empty; // // return CreateCtrlSpaceCompletionData (completionContext, result); // } // break; } return null; }
void FindReferencesButtonClick(object sender, EventArgs e) { if (csharpTreeView.SelectedNode == null) return; SimpleProjectContent project = new SimpleProjectContent(); var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); project.UpdateProjectContent(null, parsedFile); List<ITypeResolveContext> projects = new List<ITypeResolveContext>(); projects.Add(project); projects.AddRange(builtInLibs.Value); using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { CSharpResolver resolver = new CSharpResolver(context); AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag; IResolveVisitorNavigator navigator = new NodeListResolveVisitorNavigator(new[] { node }); ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); visitor.Scan(compilationUnit); IEntity entity; MemberResolveResult mrr = visitor.GetResolveResult(node) as MemberResolveResult; TypeResolveResult trr = visitor.GetResolveResult(node) as TypeResolveResult; if (mrr != null) { entity = mrr.Member; } else if (trr != null) { entity = trr.Type.GetDefinition(); } else { return; } FindReferences fr = new FindReferences(); int referenceCount = 0; FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { referenceCount++; }; var searchScopes = fr.GetSearchScopes(entity); navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); visitor = new ResolveVisitor(resolver, parsedFile, navigator); visitor.Scan(compilationUnit); csharpTreeView.BeginUpdate(); ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); csharpTreeView.EndUpdate(); MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); } }
public ResolveResult ResolveIdentifier(ResolveVisitor visitor, string identifier) { ResolveResult result = null; if (resultTable.TryGetValue (identifier, out result)) return result; resultTable[identifier] = result; foreach (KeyValuePair<string, List<LocalLookupVariable>> pair in this.lookupTableVisitor.Variables) { if (identifier == pair.Key) { LocalLookupVariable var = null; // Console.WriteLine ("--- RP:" + this.resolvePosition + "/" + pair.Value.Count); foreach (LocalLookupVariable v2 in pair.Value) { DomLocation varStartPos = new DomLocation (lookupVariableLine + v2.StartPos.Line, v2.StartPos.Column - 1); DomLocation varEndPos = new DomLocation (lookupVariableLine + v2.EndPos.Line, v2.EndPos.Column - 1); // Console.WriteLine (v2.Name + ":" + varStartPos + " <> " + varEndPos); if (varStartPos > this.resolvePosition || (!v2.EndPos.IsEmpty && varEndPos < this.resolvePosition)) continue; var = v2; } // Console.WriteLine ("var:" + var); if (var == null) continue; IReturnType varType = null; IReturnType varTypeUnresolved = null; if (var.IsQueryContinuation) { QueryExpression query = var.Initializer as QueryExpression; QueryExpressionGroupClause grouBy = query.SelectOrGroupClause as QueryExpressionGroupClause; DomLocation old = resolvePosition; try { resolvePosition = new DomLocation (lookupVariableLine + grouBy.Projection.StartLocation.Line, grouBy.Projection.StartLocation.Column); ResolveResult initializerResolve = visitor.Resolve (grouBy.Projection); ResolveResult groupByResolve = visitor.Resolve (grouBy.GroupBy); DomReturnType resolved = new DomReturnType (dom.GetType ("System.Linq.IGrouping", new IReturnType [] { DomType.GetComponentType (dom, initializerResolve.ResolvedType), groupByResolve.ResolvedType})); varTypeUnresolved = varType = resolved; } finally { resolvePosition = old; } } else if ((var.TypeRef == null || var.TypeRef.Type == "var" || var.TypeRef.IsNull)) { if (var.ParentLambdaExpression != null) { ResolveResult lambdaResolve = ResolveLambda (visitor, var.ParentLambdaExpression); if (lambdaResolve != null) { varType = lambdaResolve.ResolvedType; varTypeUnresolved = lambdaResolve.UnresolvedType; } else { varType = varTypeUnresolved = DomReturnType.Void; } } if (var.Initializer != null) { ResolveResult initializerResolve = visitor.Resolve (var.Initializer); // Console.WriteLine ("initializer : "+ var.Initializer + " result:" + initializerResolve); varType = var.IsLoopVariable ? DomType.GetComponentType (dom, initializerResolve.ResolvedType) : initializerResolve.ResolvedType; varTypeUnresolved = var.IsLoopVariable ? DomType.GetComponentType (dom, initializerResolve.UnresolvedType) : initializerResolve.UnresolvedType; // Console.WriteLine ("resolved type:" + initializerResolve.ResolvedType + " is loop : " + var.IsLoopVariable); // Console.WriteLine (varType); // Console.WriteLine ("----------"); } } else { varTypeUnresolved = varType = ConvertTypeReference (var.TypeRef); } // Console.WriteLine ("-----"); // Console.WriteLine (varType); varType = ResolveType (varType); result = new LocalVariableResolveResult ( new LocalVariable (CallingMember, identifier, varType, new DomRegion (lookupVariableLine + var.StartPos.Line - 1, var.StartPos.Column - 1, lookupVariableLine + var.StartPos.Line - 1, var.EndPos.Column - 1)), var.IsLoopVariable); result.ResolvedType = varType; result.UnresolvedType = varTypeUnresolved; goto end; } } if (this.callingMember != null) { // special handling of property or field return types, they can have the same name as the return type // ex.: MyType MyType { get; set; } Type1 Type1; if ((callingMember is IProperty || callingMember is IField) && identifier == callingMember.Name) { int pos = editor.GetPositionFromLineColumn (resolvePosition.Line, resolvePosition.Column); while (pos < editor.TextLength && !Char.IsWhiteSpace (editor.GetCharAt (pos))) pos++; while (pos < editor.TextLength && Char.IsWhiteSpace (editor.GetCharAt (pos))) pos++; StringBuilder memberName = new StringBuilder (); while (pos < editor.TextLength && (Char.IsLetterOrDigit (editor.GetCharAt (pos)) || editor.GetCharAt (pos) == '_') ) { memberName.Append (editor.GetCharAt (pos)); pos++; } //Console.WriteLine ("id: '" + identifier + "' : '" + memberName.ToString () +"'" + (memberName.ToString () == identifier)); if (memberName.ToString () == identifier) { result = visitor.CreateResult (callingMember.ReturnType); goto end; } } if (identifier == "value" && this.callingMember is IProperty) { result = new MemberResolveResult (this.callingMember); result.UnresolvedType = ((IProperty)this.callingMember).ReturnType; result.ResolvedType = ResolveType (((IProperty)this.callingMember).ReturnType); goto end; } if (this.callingMember is IMethod || this.callingMember is IProperty) { ReadOnlyCollection<IParameter> prms = this.callingMember is IMethod ? ((IMethod)this.callingMember).Parameters : ((IProperty)this.callingMember).Parameters; if (prms != null) { foreach (IParameter para in prms) { if (para.Name == identifier) { result = new ParameterResolveResult (para); result.UnresolvedType = para.ReturnType; result.ResolvedType = ResolveType (para.ReturnType); goto end; } } } } } IType searchedType = dom.SearchType (new SearchTypeRequest (unit, this.CallingType, identifier)); if (this.callingType != null && dom != null) { List<IMember> members = new List <IMember> (); foreach (IType type in dom.GetInheritanceTree (callingType)) { members.AddRange (type.SearchMember (identifier, true)); } bool includeProtected = true; // filter members if (this.CallingMember != null) { for (int i = 0; i < members.Count; i++) { if (this.CallingMember.IsStatic && !members[i].IsStatic || !members[i].IsAccessibleFrom (dom, callingType, this.CallingMember, includeProtected)) { members.RemoveAt (i); i--; continue; } } } if (members.Count > 0) { if (members[0] is IMethod) { result = new MethodResolveResult (members); if (CallingMember != null) result.StaticResolve = CallingMember.IsStatic; } else if (members[0] is IType) { result = new MemberResolveResult (null, true); result.UnresolvedType = result.ResolvedType = new DomReturnType ((IType)members[0]); goto end; } else { result = new MemberResolveResult (members[0]); } result.UnresolvedType = members[0].ReturnType; result.ResolvedType = ResolveType (members[0].ReturnType); if (members[0] is IProperty && searchedType != null && result.ResolvedType.FullName == searchedType.FullName) { result = new AggregatedResolveResult (result, new MemberResolveResult (null, true) { UnresolvedType = new DomReturnType (searchedType), ResolvedType = new DomReturnType (searchedType) }); } goto end; } } if (searchedType != null) { result = new MemberResolveResult (null, true); result.UnresolvedType = result.ResolvedType = new DomReturnType (searchedType); goto end; } if (dom.NamespaceExists (identifier, true)) { result = new NamespaceResolveResult (identifier); goto end; } if (unit != null && unit.Usings != null) { foreach (IUsing u in unit.Usings) { if (u.IsFromNamespace && u.Region.Contains (resolvePosition)) { foreach (string ns in u.Namespaces) { if (dom.NamespaceExists (ns + "." + identifier, true)) { result = new NamespaceResolveResult (ns + "." + identifier); goto end; } } } foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) { if (alias.Key == identifier || alias.Key + ".?" == identifier) { result = new NamespaceResolveResult (alias.Value.FullName); goto end; } } } } end: if (result != null) { result.CallingType = CallingType; result.CallingMember = CallingMember; } resultTable[identifier] = result; return result; }
/// <summary> /// Creates a new BVE5 AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: just outside the root node).</param> /// <param name="rootNode">The root node of the tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public BVE5AstResolver(BVE5Resolver resolver, AstNode rootNode, BVE5UnresolvedFile unresolvedFile = null) { if(resolver == null) throw new ArgumentNullException("resolver"); if(rootNode == null) throw new ArgumentNullException("rootNode"); initial_resolver_state = resolver; root_node = rootNode; unresolved_file = unresolvedFile; resolve_visitor = new ResolveVisitor(initial_resolver_state, unresolvedFile); }
public ResolveResult ResolveLambda(ResolveVisitor visitor, Expression lambdaExpression) { return new LambdaResolver (this).ResolveLambda (visitor, lambdaExpression); }
void ResolveButtonClick(object sender, EventArgs e) { SimpleProjectContent project = new SimpleProjectContent(); TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(project, "dummy.cs"); compilationUnit.AcceptVisitor(convertVisitor, null); project.UpdateProjectContent(null, convertVisitor.ParsedFile.TopLevelTypeDefinitions, null, null); List<ITypeResolveContext> projects = new List<ITypeResolveContext>(); projects.Add(project); projects.AddRange(builtInLibs.Value); using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { CSharpResolver resolver = new CSharpResolver(context); IResolveVisitorNavigator navigator = null; if (csharpTreeView.SelectedNode != null) { navigator = new NodeListResolveVisitorNavigator(new[] { (AstNode)csharpTreeView.SelectedNode.Tag }); } ResolveVisitor visitor = new ResolveVisitor(resolver, convertVisitor.ParsedFile, navigator); visitor.Scan(compilationUnit); csharpTreeView.BeginUpdate(); ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); csharpTreeView.EndUpdate(); } }
/// <summary> /// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the /// navigator of the results. /// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator /// after a portion of the file was already resolved. /// </summary> public void ApplyNavigator(IResolveVisitorNavigator navigator, CancellationToken cancellationToken = default(CancellationToken)) { if (navigator == null) throw new ArgumentNullException("navigator"); if (resolveVisitor != null) throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver."); resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, navigator); lock (resolveVisitor) resolveVisitor.Scan(rootNode); }
void InitResolver(AstNode firstNodeToResolve) { if (resolveVisitor == null) { resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, new NodeListResolveVisitorNavigator(firstNodeToResolve)); resolveVisitor.Scan(rootNode); } }
internal ResolveResult ResolveLambda(ResolveVisitor visitor, Expression lambdaExpression) { if (expressions.Contains (lambdaExpression)) { Console.WriteLine ("LOOP!!!"); return null; } expressions.Add (lambdaExpression); if (lambdaExpression.Parent is LambdaExpression) return ResolveLambda (visitor, lambdaExpression.Parent as Expression); if (lambdaExpression.Parent is ParenthesizedExpression) return ResolveLambda (visitor, lambdaExpression.Parent as Expression); if (lambdaExpression.Parent is AssignmentExpression) return visitor.Resolve (((AssignmentExpression)lambdaExpression.Parent).Left); if (lambdaExpression.Parent is CastExpression) return visitor.Resolve (((CastExpression)lambdaExpression.Parent)); if (lambdaExpression.Parent is VariableDeclaration) { VariableDeclaration varDec = (VariableDeclaration)lambdaExpression.Parent; return resolver.GetFunctionParameterType (resolver.ResolveIdentifier (visitor, varDec.Name)); } if (lambdaExpression.Parent is InvocationExpression) { InvocationExpression invocation = (InvocationExpression)lambdaExpression.Parent; MethodResolveResult result = visitor.Resolve (invocation.TargetObject) as MethodResolveResult; if (result == null) { MonoDevelop.Core.LoggingService.LogWarning ("No compatible method found :" + invocation.TargetObject); return null; } result.ResolveExtensionMethods (); // todo! - not 100% correct, but it's a best-fit until the dom contains token information // This code assumes that the lambda expression is the first parameter of the method. for (int i = 0; i < invocation.Arguments.Count; i++) { if (invocation.Arguments[i] == lambdaExpression && i < result.MostLikelyMethod.Parameters.Count) { IParameter parameter = result.MostLikelyMethod.Parameters[i]; IReturnType returnType = parameter.ReturnType; while (returnType.GenericArguments.Count > 0) { returnType = returnType.GenericArguments[0]; } string invariantString = returnType.ToInvariantString (); if (returnTypeDictionary.ContainsKey (invariantString)) return returnTypeDictionary[invariantString]; ResolveResult createdResult = visitor.CreateResult (returnType); returnTypeDictionary[invariantString] = createdResult; return createdResult; } } LambdaExpression lambda = (LambdaExpression)lambdaExpression; // Console.WriteLine ("lambda:" + lambda); if (!lambda.ExpressionBody.IsNull) { DomLocation old = resolver.resolvePosition; try { resolver.resolvePosition = new DomLocation (resolver.CallingMember.Location.Line + resolver.lookupVariableLine + lambda.ExpressionBody.StartLocation.Line - 2, lambda.ExpressionBody.StartLocation.Column - 1); // Console.WriteLine ("pos:" + resolvePosition); // result.AddArgument (visitor.GetTypeSafe (lambda.ExpressionBody)); // result.ResolveExtensionMethods (); ResolveResult res = visitor.Resolve (lambda.ExpressionBody); // Console.WriteLine (lambda.ExpressionBody); // Console.WriteLine ("RES:" + res.ResolvedType.FullName); if (!string.IsNullOrEmpty (res.ResolvedType.FullName)) return res; } finally { resolver.resolvePosition = old; } } foreach (Expression arg in invocation.Arguments) { var argType = arg is LambdaExpression ? DomReturnType.Void : visitor.GetTypeSafe (arg); result.AddArgument (argType); } result.ResolveExtensionMethods (); //Console.WriteLine ("maybe method:" + result.MostLikelyMethod); for (int i = 0; i < invocation.Arguments.Count; i++) { if (invocation.Arguments [i] == lambdaExpression && i < result.MostLikelyMethod.Parameters.Count) { IParameter parameterType = result.MostLikelyMethod.Parameters [i]; //Console.WriteLine (i + " par: " + parameterType); if (parameterType.ReturnType.Name == "Func" && parameterType.ReturnType.GenericArguments.Count > 0) { return visitor.CreateResult (parameterType.ReturnType.GenericArguments[0]); } } } return result; } if (lambdaExpression.Parent is ObjectCreateExpression) { ObjectCreateExpression objectCreateExpression = (ObjectCreateExpression)lambdaExpression.Parent; int index = objectCreateExpression.Parameters.IndexOf (lambdaExpression); if (index < 0) return null; MemberResolveResult resolvedCreateExpression = visitor.Resolve (objectCreateExpression) as MemberResolveResult; if (resolvedCreateExpression != null) { IMethod method = resolvedCreateExpression.ResolvedMember as IMethod; if (method!= null && index < method.Parameters.Count) { return new ParameterResolveResult (method.Parameters[index]); } else { return null; } } } return null; }
void ShowResolveResultsInTree(TreeNodeCollection c, ResolveVisitor v) { foreach (TreeNode t in c) { AstNode node = t.Tag as AstNode; if (node != null) { ResolveResult rr = v.GetResolveResult(node); if (rr != null) t.Text = GetNodeTitle(node) + " " + rr.ToString(); else t.Text = GetNodeTitle(node); } ShowResolveResultsInTree(t.Nodes, v); } }
/// <summary> /// Finds all references in the given file. /// </summary> /// <param name="searchScopes">The search scopes for which to look.</param> /// <param name="parsedFile">The type system representation of the file being searched.</param> /// <param name="compilationUnit">The compilation unit of the file being searched.</param> /// <param name="context">The type resolve context to use for resolving the file.</param> /// <param name="callback">Callback used to report the references that were found.</param> public void FindReferencesInFile(IList<IFindReferenceSearchScope> searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, ITypeResolveContext context, FoundReferenceCallback callback) { if (searchScopes == null) throw new ArgumentNullException("searchScopes"); if (parsedFile == null) throw new ArgumentNullException("parsedFile"); if (compilationUnit == null) throw new ArgumentNullException("compilationUnit"); if (context == null) throw new ArgumentNullException("context"); this.CancellationToken.ThrowIfCancellationRequested(); if (searchScopes.Count == 0) return; using (var ctx = context.Synchronize()) { IResolveVisitorNavigator navigator; if (searchScopes.Count == 1) navigator = searchScopes[0].GetNavigator(callback); else navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit); CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); v.Scan(compilationUnit); } }
public ResolveResult ResolveExpression(Expression expr, DomLocation resolvePosition) { this.expr = expr; this.SetupResolver (resolvePosition); ResolveVisitor visitor = new ResolveVisitor (this); ResolveResult result = visitor.Resolve (expr); return result; }
public ResolveResult ResolveIdentifier(string identifier, DomLocation resolvePosition) { this.SetupResolver (resolvePosition); ResolveVisitor visitor = new ResolveVisitor (this); ResolveResult result = this.ResolveIdentifier (visitor, identifier); return result; }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: just outside the root node).</param> /// <param name="rootNode">The root node of the tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpUnresolvedFile unresolvedFile = null) { if (resolver == null) throw new ArgumentNullException("resolver"); if (rootNode == null) throw new ArgumentNullException("rootNode"); this.initialResolverState = resolver; this.rootNode = rootNode; this.unresolvedFile = unresolvedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile); }
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; }