protected bool IsInsideAsmCode(int offset) { var lexer = new MiniLexer(document.Text); lexer.Parse(0, offset); return(lexer.IsInAsmCode); }
protected bool IsInsideAsmCode() { var text = GetMemberTextToCaret(); var lexer = new MiniLexer(text.Item1); lexer.Parse(); return (lexer.IsInAsmCode); }
protected bool IsInsideCommentStringOrDirective(int offset) { var lexer = new MiniLexer(document.Text); lexer.Parse(0, offset); return (lexer.IsInSingleComment || lexer.IsInString || lexer.IsInVerbatimString || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective); }
protected bool IsInsideCommentStringOrDirective() { var text = GetMemberTextToCaret(); var lexer = new MiniLexer(text.Item1); lexer.Parse(); return (lexer.IsInSingleComment || lexer.IsInString || lexer.IsInVerbatimString || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective); }
IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace, out bool isComplete) { isComplete = false; ExpressionResolveResult resolveResult; switch (completionChar) { // Magic key completion case ':': var text = GetMemberTextToCaret(); var lexer = new MiniLexer(text.Item1); lexer.Parse(); if (lexer.IsInSingleComment || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective) { return Enumerable.Empty<ICompletionData>(); } if (lexer.IsInString || lexer.IsInVerbatimString) return HandleStringFormatItems(); return HandleMemberReferenceCompletion(GetExpressionBeforeCursor()); case '"': text = GetMemberTextToCaret(); lexer = new MiniLexer(text.Item1); lexer.Parse(); if (lexer.IsInSingleComment || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective) { return Enumerable.Empty<ICompletionData>(); } if (lexer.IsInString || lexer.IsInVerbatimString) return HandleToStringFormatItems(); return Enumerable.Empty<ICompletionData>(); case '.': if (IsInsideCommentStringOrDirective()) { return Enumerable.Empty<ICompletionData>(); } return HandleMemberReferenceCompletion(GetExpressionBeforeCursor()); case '#': if (!IsInPreprocessorDirective()) return null; return GetDirectiveCompletionData(); // XML doc completion case '<': if (IsInsideDocComment()) { return GetXmlDocumentationCompletionData(); } if (controlSpace) { return DefaultControlSpaceItems(ref isComplete); } return null; case '>': if (!IsInsideDocComment()) { if (offset > 2 && document.GetCharAt(offset - 2) == '-' && !IsInsideCommentStringOrDirective()) { return HandleMemberReferenceCompletion(GetExpressionBeforeCursor()); } return null; } return null; // Parameter completion case '(': if (IsInsideCommentStringOrDirective()) { return null; } var invoke = GetInvocationBeforeCursor(true); if (invoke == null) { if (controlSpace) return DefaultControlSpaceItems(ref isComplete, invoke); return null; } if (invoke.Node is TypeOfExpression) { return CreateTypeList(); } var invocationResult = ResolveExpression(invoke); if (invocationResult == null) { return null; } var methodGroup = invocationResult.Result as MethodGroupResolveResult; if (methodGroup != null) { return CreateParameterCompletion( methodGroup, invocationResult.Resolver, invoke.Node, invoke.Unit, 0, controlSpace ); } if (controlSpace) { return DefaultControlSpaceItems(ref isComplete, invoke); } return null; case '=': return controlSpace ? DefaultControlSpaceItems(ref isComplete) : 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 ' ': int tokenIndex = offset; string token = GetPreviousToken(ref tokenIndex, false); if (IsInsideCommentStringOrDirective()) { return null; } // 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.Node is VariableDeclarationStatement && token != "new") { var parent = isAsExpression.Node as VariableDeclarationStatement; var proposeNameList = new CompletionDataWrapper(this); if (parent.Variables.Count != 1) return DefaultControlSpaceItems(ref isComplete, isAsExpression, controlSpace); foreach (var possibleName in GenerateNameProposals (parent.Type)) { if (possibleName.Length > 0) { proposeNameList.Result.Add(factory.CreateLiteralCompletionData(possibleName.ToString())); } } AutoSelect = false; AutoCompleteEmptyMatch = false; isComplete = true; 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 == "-" || prevToken == "!") { token = prevToken + token; tokenIndex = j; } } switch (token) { case "(": case ",": int cpos; if (!GetParameterCompletionCommandOffset(out cpos)) { break; } int currentParameter = GetCurrentParameterIndex(cpos - 1, this.offset) - 1; if (currentParameter < 0) { return null; } invoke = GetInvocationBeforeCursor(token == "("); if (invoke == null) { return null; } invocationResult = ResolveExpression(invoke); if (invocationResult == null) { return null; } methodGroup = invocationResult.Result as MethodGroupResolveResult; if (methodGroup != null) { return CreateParameterCompletion( methodGroup, invocationResult.Resolver, invoke.Node, invoke.Unit, currentParameter, controlSpace); } return null; case "=": case "==": case "!=": GetPreviousToken(ref tokenIndex, false); var expressionOrVariableDeclaration = GetExpressionAt(tokenIndex); if (expressionOrVariableDeclaration == null) { return null; } resolveResult = ResolveExpression(expressionOrVariableDeclaration); if (resolveResult == null) { return null; } if (resolveResult.Result.Type.Kind == TypeKind.Enum) { var wrapper = new CompletionDataWrapper(this); AddContextCompletion( wrapper, resolveResult.Resolver, expressionOrVariableDeclaration.Node); AddEnumMembers(wrapper, resolveResult.Result.Type, resolveResult.Resolver); 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); if (resolveResult == null) { return null; } var mrr = resolveResult.Result 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 ctx.CurrentTypeDefinition.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) { token = GetPreviousToken(ref tokenIndex, false); token = GetPreviousToken(ref tokenIndex, false); if (token == "enum") return HandleEnumContext(); var wrapper = new CompletionDataWrapper(this); AddTypesAndNamespaces( wrapper, GetState(), null, t => { if (currentType != null && currentType.ReflectionName.Equals(t.ReflectionName)) return null; var def = t.GetDefinition(); if (def != null && t.Kind != TypeKind.Interface && (def.IsSealed ||def.IsStatic)) return null; return t; } ); return wrapper.Result; } return null; } var keywordCompletion = HandleKeywordCompletion(tokenIndex, token); if (keywordCompletion == null && controlSpace) { goto default; } return keywordCompletion; // Automatic completion default: if (IsInsideCommentStringOrDirective()) { tokenIndex = offset; token = GetPreviousToken(ref tokenIndex, false); if (IsInPreprocessorDirective() && (token.Length == 1 && char.IsLetter(completionChar) || controlSpace)) { while (token != null && document.GetCharAt(tokenIndex - 1) != '#') { token = GetPreviousToken(ref tokenIndex, false); } if (token != null) return HandleKeywordCompletion(tokenIndex, token); } return 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) || !(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) { if (!controlSpace) return null; } if (IsInLinqContext(offset)) { if (!controlSpace && !(char.IsLetter(completionChar) || completionChar == '_')) { return null; } tokenIndex = offset; token = GetPreviousToken(ref tokenIndex, false); // token last typed if (!char.IsWhiteSpace(completionChar) && !linqKeywords.Contains(token)) { 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(ref isComplete); } var dataList = new CompletionDataWrapper(this); AddKeywords(dataList, linqKeywords); return dataList.Result; } if (currentType != null && currentType.Kind == TypeKind.Enum) { if (!char.IsLetter(completionChar)) return null; return HandleEnumContext(); } var contextList = new CompletionDataWrapper(this); var identifierStart = GetExpressionAtCursor(); if (!(char.IsLetter(completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null)) { return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(ref isComplete, identifierStart) : null; } if (identifierStart != null) { if (identifierStart.Node is TypeParameterDeclaration) { return null; } if (identifierStart.Node is MemberReferenceExpression) { return HandleMemberReferenceCompletion( new ExpressionResult( ((MemberReferenceExpression)identifierStart.Node).Target, identifierStart.Unit ) ); } if (identifierStart.Node is Identifier) { if (identifierStart.Node.Parent is GotoStatement) return null; // May happen in variable names return controlSpace ? DefaultControlSpaceItems(ref isComplete, identifierStart) : null; } if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) { return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(ref isComplete, identifierStart) : null; } if (identifierStart.Node is CatchClause) { if (((CatchClause)identifierStart.Node).VariableNameToken.IsInside(location)) { return null; } } if (identifierStart.Node is AstType && identifierStart.Node.Parent is CatchClause) { return HandleCatchClauseType(identifierStart); } var pDecl = identifierStart.Node as ParameterDeclaration; if (pDecl != null && pDecl.Parent is LambdaExpression) { return null; } } // Do not pop up completion on identifier identifier (should be handled by keyword completion). tokenIndex = offset - 1; token = GetPreviousToken(ref tokenIndex, false); if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") { // after these always follows a name return null; } var keywordresult = HandleKeywordCompletion(tokenIndex, token); if (keywordresult != null) { return keywordresult; } if ((!Char.IsWhiteSpace(nextCh) && allowedChars.IndexOf(nextCh) < 0) || !(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) { if (controlSpace) return DefaultControlSpaceItems(ref isComplete, identifierStart); } int prevTokenIndex = tokenIndex; var prevToken2 = GetPreviousToken(ref prevTokenIndex, false); if (prevToken2 == "delegate") { // after these always follows a name return null; } if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) { char last = token [token.Length - 1]; if (char.IsLetterOrDigit(last) || last == '_' || token == ">") { return HandleKeywordCompletion(tokenIndex, token); } } if (identifierStart == null) { var accCtx = HandleAccessorContext(); if (accCtx != null) { return accCtx; } return DefaultControlSpaceItems(ref isComplete, null, controlSpace); } CSharpResolver csResolver; AstNode n = identifierStart.Node; if (n.Parent is NamedArgumentExpression) n = n.Parent; if (n != null && n.Parent is AnonymousTypeCreateExpression) { AutoSelect = false; } // new { b$ } if (n is IdentifierExpression && n.Parent is AnonymousTypeCreateExpression) return null; // Handle foreach (type name _ if (n is IdentifierExpression) { var prev = n.GetPrevNode() as ForeachStatement; while (prev != null && prev.EmbeddedStatement is ForeachStatement) prev = (ForeachStatement)prev.EmbeddedStatement; if (prev != null && prev.InExpression.IsNull) { if (IncludeKeywordsInCompletionList) contextList.AddCustom("in"); return contextList.Result; } } // Handle object/enumerable initialzer expressions: "new O () { P$" if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression && !(n.Parent.Parent is ArrayCreateExpression)) { var result = HandleObjectInitializer(identifierStart.Unit, n); if (result != null) return result; } if (n != null && n.Parent is InvocationExpression || n.Parent is ParenthesizedExpression && n.Parent.Parent is InvocationExpression) { if (n.Parent is ParenthesizedExpression) n = n.Parent; var invokeParent = (InvocationExpression)n.Parent; var invokeResult = ResolveExpression( invokeParent.Target ); var mgr = invokeResult != null ? invokeResult.Result as MethodGroupResolveResult : null; if (mgr != null) { int idx = 0; foreach (var arg in invokeParent.Arguments) { if (arg == n) { break; } idx++; } foreach (var method in mgr.Methods) { if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) { AutoSelect = false; AutoCompleteEmptyMatch = false; } foreach (var p in method.Parameters) { contextList.AddNamedParameterVariable(p); } } idx++; foreach (var list in mgr.GetEligibleExtensionMethods (true)) { foreach (var method in list) { if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) { AutoSelect = false; AutoCompleteEmptyMatch = false; } } } } } if (n != null && n.Parent is ObjectCreateExpression) { var invokeResult = ResolveExpression(n.Parent); var mgr = invokeResult != null ? invokeResult.Result as ResolveResult : null; if (mgr != null) { foreach (var constructor in mgr.Type.GetConstructors ()) { foreach (var p in constructor.Parameters) { contextList.AddVariable(p); } } } } if (n is IdentifierExpression) { var bop = n.Parent as BinaryOperatorExpression; Expression evaluationExpr = null; if (bop != null && bop.Right == n && (bop.Operator == BinaryOperatorType.Equality || bop.Operator == BinaryOperatorType.InEquality)) { evaluationExpr = bop.Left; } // check for compare to enum case if (evaluationExpr != null) { resolveResult = ResolveExpression(evaluationExpr); if (resolveResult != null && resolveResult.Result.Type.Kind == TypeKind.Enum) { var wrapper = new CompletionDataWrapper(this); AddContextCompletion( wrapper, resolveResult.Resolver, evaluationExpr ); AddEnumMembers(wrapper, resolveResult.Result.Type, resolveResult.Resolver); AutoCompleteEmptyMatch = false; return wrapper.Result; } } } if (n is Identifier && n.Parent is ForeachStatement) { if (controlSpace) { return DefaultControlSpaceItems(ref isComplete); } 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(ref isComplete); } var initalizerResult = ResolveExpression(n.Parent); var concreteNode = identifierStart.Unit.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(ref isComplete); } if (initalizerResult != null && initalizerResult.Result.Type.Kind != TypeKind.Unknown) { foreach (var property in initalizerResult.Result.Type.GetProperties ()) { if (!property.IsPublic) { continue; } var data = contextList.AddMember(property); if (data != null) data.DisplayFlags |= DisplayFlags.NamedArgument; } foreach (var field in initalizerResult.Result.Type.GetFields ()) { if (!field.IsPublic) { continue; } var data = contextList.AddMember(field); if (data != null) data.DisplayFlags |= DisplayFlags.NamedArgument; } return contextList.Result; } return DefaultControlSpaceItems(ref isComplete); } if (IsAttributeContext(n)) { // add attribute targets if (currentType == null) { contextList.AddCustom("assembly"); contextList.AddCustom("module"); contextList.AddCustom("type"); } else { contextList.AddCustom("param"); contextList.AddCustom("field"); contextList.AddCustom("property"); contextList.AddCustom("method"); contextList.AddCustom("event"); } contextList.AddCustom("return"); } if (n is MemberType) { resolveResult = ResolveExpression( ((MemberType)n).Target ); return CreateTypeAndNamespaceCompletionData( location, resolveResult.Result, ((MemberType)n).Target, resolveResult.Resolver ); } 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 astResolver = CompletionContextProvider.GetResolver(csResolver, identifierStart.Unit); astResolver.ApplyNavigator(new NodeListResolveVisitorNavigator(nodes)); try { csResolver = astResolver.GetResolverStateBefore(n); } catch (Exception) { csResolver = GetState(); } // add attribute properties. if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) { var rr = ResolveExpression(n.Parent); if (rr != null) AddAttributeProperties(contextList, rr.Result); } } else { csResolver = GetState(); } // identifier has already started with the first letter offset--; AddContextCompletion( contextList, csResolver, identifierStart.Node ); 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; }
bool IsInPreprocessorDirective() { var text = GetMemberTextToCaret().Item1; var miniLexer = new MiniLexer(text); miniLexer.Parse(); return miniLexer.IsInPreprocessorDirective; }
protected bool IsInsideCommentStringOrDirective() { var text = GetMemberTextToCaret(); var lexer = new MiniLexer(text.Item1); lexer.Parse(); return lexer.IsInSingleComment || lexer.IsInString || lexer.IsInVerbatimString || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective; }
protected bool IsInsideCommentStringOrDirective(int offset) { var lexer = new MiniLexer(document.Text); lexer.Parse(0, offset); return lexer.IsInSingleComment || lexer.IsInString || lexer.IsInVerbatimString || lexer.IsInChar || lexer.IsInMultiLineComment || lexer.IsInPreprocessorDirective; }
public IParameterDataProvider GetParameterDataProvider(int offset, char completionChar) { //Ignoring completionChar == '\0' because it usually means moving with arrow keys, tab or enter //we don't want to trigger on those events but it probably should be handled somewhere else //since our job is to resolve method and not to decide when to display tooltip or not if (offset <= 0 || completionChar == '\0') { return(null); } SetOffset(offset); int startOffset; string text; if (currentMember == null && currentType == null) { //In case of attributes parse all file startOffset = 0; text = document.Text; } else { var memberText = GetMemberTextToCaret(); text = memberText.Item1; startOffset = document.GetOffset(memberText.Item2); } var parenStack = new Stack <int> (); var chevronStack = new Stack <int> (); var squareStack = new Stack <int> (); var bracketStack = new Stack <int> (); var lex = new MiniLexer(text); bool failed = lex.Parse((ch, off) => { if (lex.IsInString || lex.IsInChar || lex.IsInVerbatimString || lex.IsInSingleComment || lex.IsInMultiLineComment || lex.IsInPreprocessorDirective) { return(false); } switch (ch) { case '(': parenStack.Push(startOffset + off); break; case ')': if (parenStack.Count == 0) { return(true); } parenStack.Pop(); break; case '<': chevronStack.Push(startOffset + off); break; case '>': //Don't abort if we don't have macthing '<' for '>' it could be if (i > 0) Foo($ if (chevronStack.Count == 0) { return(false); } chevronStack.Pop(); break; case '[': squareStack.Push(startOffset + off); break; case ']': if (squareStack.Count == 0) { return(true); } squareStack.Pop(); break; case '{': bracketStack.Push(startOffset + off); break; case '}': if (bracketStack.Count == 0) { return(true); } bracketStack.Pop(); break; } return(false); }); if (failed) { return(null); } int result = -1; if (parenStack.Count > 0) { result = parenStack.Pop(); } if (squareStack.Count > 0) { result = Math.Max(result, squareStack.Pop()); } if (chevronStack.Count > 0) { result = Math.Max(result, chevronStack.Pop()); } //If we are inside { bracket we don't want to display anything if (bracketStack.Count > 0 && bracketStack.Pop() > result) { return(null); } if (result == -1) { return(null); } SetOffset(result + 1); ResolveResult resolveResult; switch (document.GetCharAt(result)) { case '(': var invoke = GetInvocationBeforeCursor(true) ?? GetConstructorInitializerBeforeCursor(); if (invoke == null) { return(null); } if (invoke.Node is ConstructorInitializer) { var init = (ConstructorInitializer)invoke.Node; if (init.ConstructorInitializerType == ConstructorInitializerType.This) { return(factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition, init)); } else { var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface); if (baseType == null) { return(null); } return(factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), baseType)); } } if (invoke.Node is ObjectCreateExpression) { var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type); if (createType.Result.Type.Kind == TypeKind.Unknown) { return(null); } return(factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Result.Type)); } if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { var attribute = ResolveExpression(invoke); if (attribute == null || attribute.Result == null) { return(null); } return(factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Result.Type)); } var invocationExpression = ResolveExpression(invoke); if (invocationExpression == null || invocationExpression.Result == null || invocationExpression.Result.IsError) { return(null); } resolveResult = invocationExpression.Result; if (resolveResult is MethodGroupResolveResult) { return(factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult))); } if (resolveResult is MemberResolveResult) { var mr = resolveResult as MemberResolveResult; if (mr.Member is IMethod) { return(factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member })); } } if (resolveResult.Type.Kind == TypeKind.Delegate) { return(factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type)); } // // if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) { // if (resolveResult is ThisResolveResult) // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult); // if (resolveResult is BaseResolveResult) // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult); // } // IType resolvedType = resolver.SearchType (resolveResult.ResolvedType); // if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) { // return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType); // } break; case '<': invoke = GetMethodTypeArgumentInvocationBeforeCursor(); if (invoke != null) { var tExpr2 = ResolveExpression(invoke); if (tExpr2 != null && tExpr2.Result is MethodGroupResolveResult && !tExpr2.Result.IsError) { return(factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, tExpr2.Result as MethodGroupResolveResult))); } } invoke = GetTypeBeforeCursor(); if (invoke == null || invoke.Node.StartLocation.IsEmpty) { return(null); } var tExpr = ResolveExpression(invoke); if (tExpr == null || tExpr.Result == null || tExpr.Result.IsError) { return(null); } return(factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Result.Type))); case '[': invoke = GetIndexerBeforeCursor(); if (invoke == null) { return(null); } if (invoke.Node is ArrayCreateExpression) { return(null); } var indexerExpression = ResolveExpression(invoke); if (indexerExpression == null || indexerExpression.Result == null || indexerExpression.Result.IsError) { return(null); } return(factory.CreateIndexerParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), indexerExpression.Result.Type, GetAccessibleIndexers(indexerExpression.Result.Type), invoke.Node)); } return(null); }
public IParameterDataProvider GetParameterDataProvider(int offset, char completionChar) { //Ignoring completionChar == '\0' because it usually means moving with arrow keys, tab or enter //we don't want to trigger on those events but it probably should be handled somewhere else //since our job is to resolve method and not to decide when to display tooltip or not if (offset <= 0 || completionChar == '\0') { return null; } SetOffset (offset); int startOffset; string text; if (currentMember == null && currentType == null) { //In case of attributes parse all file startOffset = 0; text = document.Text; } else { var memberText = GetMemberTextToCaret (); text = memberText.Item1; startOffset = document.GetOffset (memberText.Item2); } var parenStack = new Stack<int> (); var chevronStack = new Stack<int> (); var squareStack = new Stack<int> (); var bracketStack = new Stack<int> (); var lex = new MiniLexer (text); bool failed = lex.Parse ((ch, off) => { if (lex.IsInString || lex.IsInChar || lex.IsInVerbatimString || lex.IsInSingleComment || lex.IsInMultiLineComment || lex.IsInPreprocessorDirective) return false; switch (ch) { case '(': parenStack.Push (startOffset + off); break; case ')': if (parenStack.Count == 0) { return true; } parenStack.Pop (); break; case '<': chevronStack.Push (startOffset + off); break; case '>': //Don't abort if we don't have macthing '<' for '>' it could be if (i > 0) Foo($ if (chevronStack.Count == 0) { return false; } chevronStack.Pop (); break; case '[': squareStack.Push (startOffset + off); break; case ']': if (squareStack.Count == 0) { return true; } squareStack.Pop (); break; case '{': bracketStack.Push (startOffset + off); break; case '}': if (bracketStack.Count == 0) { return true; } bracketStack.Pop (); break; } return false; }); if (failed) return null; int result = -1; if (parenStack.Count > 0) result = parenStack.Pop (); if (squareStack.Count > 0) result = Math.Max (result, squareStack.Pop ()); if (chevronStack.Count > 0) result = Math.Max (result, chevronStack.Pop ()); //If we are inside { bracket we don't want to display anything if (bracketStack.Count > 0 && bracketStack.Pop () > result) return null; if (result == -1) return null; SetOffset (result + 1); ResolveResult resolveResult; switch (document.GetCharAt (result)) { case '(': var invoke = GetInvocationBeforeCursor(true) ?? GetConstructorInitializerBeforeCursor(); if (invoke == null) { return null; } if (invoke.Node is ConstructorInitializer) { var init = (ConstructorInitializer)invoke.Node; if (init.ConstructorInitializerType == ConstructorInitializerType.This) { return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition, init); } else { var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface); if (baseType == null) { return null; } return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), baseType); } } if (invoke.Node is ObjectCreateExpression) { var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type); if (createType.Result.Type.Kind == TypeKind.Unknown) return null; return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Result.Type); } if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { var attribute = ResolveExpression(invoke); if (attribute == null || attribute.Result == null) { return null; } return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Result.Type); } var invocationExpression = ResolveExpression(invoke); if (invocationExpression == null || invocationExpression.Result == null || invocationExpression.Result.IsError) { return null; } resolveResult = invocationExpression.Result; if (resolveResult is MethodGroupResolveResult) { return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult)); } if (resolveResult is MemberResolveResult) { var mr = resolveResult as MemberResolveResult; if (mr.Member is IMethod) { return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member }); } } if (resolveResult.Type.Kind == TypeKind.Delegate) { return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type); } // // if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) { // if (resolveResult is ThisResolveResult) // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult); // if (resolveResult is BaseResolveResult) // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult); // } // IType resolvedType = resolver.SearchType (resolveResult.ResolvedType); // if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) { // return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType); // } break; case '<': invoke = GetMethodTypeArgumentInvocationBeforeCursor(); if (invoke != null) { var tExpr2 = ResolveExpression(invoke); if (tExpr2 != null && tExpr2.Result is MethodGroupResolveResult && !tExpr2.Result.IsError) { return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, tExpr2.Result as MethodGroupResolveResult)); } } invoke = GetTypeBeforeCursor(); if (invoke == null || invoke.Node.StartLocation.IsEmpty) { return null; } var tExpr = ResolveExpression(invoke); if (tExpr == null || tExpr.Result == null || tExpr.Result.IsError) { return null; } return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Result.Type)); case '[': invoke = GetIndexerBeforeCursor(); if (invoke == null) { return null; } if (invoke.Node is ArrayCreateExpression) { return null; } var indexerExpression = ResolveExpression(invoke); if (indexerExpression == null || indexerExpression.Result == null || indexerExpression.Result.IsError) { return null; } return factory.CreateIndexerParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), indexerExpression.Result.Type, GetAccessibleIndexers (indexerExpression.Result.Type), invoke.Node); } return null; }