public static IEnumerable <CompletionItem> GetCompletionForProcedure(FileCompiler fileCompiler, CodeElement codeElement, Token userFilterToken, Dictionary <SignatureInformation, FunctionDeclaration> functionDeclarationSignatureDictionary) { var node = GetMatchingNode(fileCompiler, codeElement); IEnumerable <FunctionDeclaration> procedures = null; IEnumerable <DataDefinition> variables = null; var completionItems = new List <CompletionItem>(); if (node != null) { if (node.SymbolTable != null) { var userFilterText = userFilterToken == null ? string.Empty : userFilterToken.Text; procedures = node.SymbolTable.GetFunctions( f => f.VisualQualifiedName.ToString() .StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase) || f.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase), new List <SymbolTable.Scope> { SymbolTable.Scope.Declarations, SymbolTable.Scope.Intrinsic, SymbolTable.Scope.Namespace }); variables = node.SymbolTable.GetVariables(da => da.Picture != null && da.DataType == Compiler.CodeElements.DataType.Alphanumeric && da.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase), new List <SymbolTable.Scope> { SymbolTable.Scope.Declarations, SymbolTable.Scope.Global }); } } completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForProcedures(procedures, node, functionDeclarationSignatureDictionary)); foreach (var variable in variables) { var completionItem = new CompletionItem(string.Format("{0}", variable.Name)); completionItem.insertText = variable.Name; completionItem.kind = CompletionItemKind.Variable; completionItems.Add(completionItem); } return(completionItems); }
public static IEnumerable <CompletionItem> GetCompletionForQualifiedName(Position position, FileCompiler fileCompiler, CodeElement codeElement, Token qualifiedNameSeparatorToken, Token userFilterToken, Dictionary <SignatureInformation, FunctionDeclaration> functionDeclarationSignatureDictionary) { var completionItems = new List <CompletionItem>(); var arrangedCodeElement = codeElement as CodeElementWrapper; var node = GetMatchingNode(fileCompiler, codeElement); var userFilterText = userFilterToken == null ? string.Empty : userFilterToken.Text; //Get the token before MatchingToken var userTokenToSeek = arrangedCodeElement?.ArrangedConsumedTokens.ElementAt( arrangedCodeElement.ArrangedConsumedTokens.IndexOf(qualifiedNameSeparatorToken) - 1); var qualifiedNameTokens = new List <Token>(); if (arrangedCodeElement != null) { qualifiedNameTokens.AddRange( arrangedCodeElement.ArrangedConsumedTokens?.Where( t => (t?.TokenType == TokenType.UserDefinedWord || t?.TokenType == TokenType.QualifiedNameSeparator) && (t.EndColumn <= position.character && t.Line == position.line + 1) || t.Line < position.line + 1)); //Remove all the userdefinedword token and also QualifiedNameToken arrangedCodeElement.ArrangedConsumedTokens = arrangedCodeElement.ArrangedConsumedTokens.Except(qualifiedNameTokens).ToList(); //We only wants the token that in front of any QualifiedName //Get the first significant token (i.e CALL/TYPE/...) Token firstSignificantToken, tempUserFilterToken; CodeElementMatcher.MatchCompletionCodeElement(position, new List <CodeElementWrapper> { arrangedCodeElement }, out tempUserFilterToken, out firstSignificantToken); //Select the qualifiedName chain closest to cursor Token previousToken = null; qualifiedNameTokens.Reverse(); var filteredQualifiedNameTokens = new List <Token>(); //Will contains all the tokens forming the qualifiedName chain. foreach (var token in qualifiedNameTokens) { if (previousToken == null || ((previousToken.TokenType == TokenType.QualifiedNameSeparator && token.TokenType == TokenType.UserDefinedWord) || (token.TokenType == TokenType.QualifiedNameSeparator && previousToken.TokenType == TokenType.UserDefinedWord))) { filteredQualifiedNameTokens.Add(token); } else { break; } previousToken = token; } filteredQualifiedNameTokens.Reverse(); //For MOVE INPUT OUTPUT variables etc.. , get all the children of a variable that are accessible //Try to find corresponding variables var qualifiedName = string.Join(".", filteredQualifiedNameTokens.Where( t => t.TokenType == TokenType.UserDefinedWord && !(t.Text == userFilterText && userFilterToken != null && t.StartIndex == userFilterToken.StartIndex && t.EndColumn == userFilterToken.EndColumn) && ((firstSignificantToken != null && ((t.StartIndex >= firstSignificantToken.EndColumn && t.Line == firstSignificantToken.Line) || t.Line > firstSignificantToken.Line)) || firstSignificantToken == null) && ((t.EndColumn <= position.character && t.Line == position.line + 1) || t.Line < position.line + 1)) .Select(t => t.Text)); var possibleVariables = node.SymbolTable.GetVariablesExplicit(new URI(qualifiedName)); if (possibleVariables != null && possibleVariables.Any()) { //Get children of a type to get completion possibilities foreach (var variable in possibleVariables) { var children = new List <Node>(); if (variable.Children != null && variable.Children.Count > 0) //It's a variable with levels inside { children.AddRange(variable.Children); } else //It's a typed variable, we have to search for children in the type { var typeChildren = GetTypeChildrens(node.SymbolTable, variable); if (typeChildren != null) { children.AddRange(typeChildren.Where(t => t.Name != null)); } } var computedChildrenList = new List <Node>(); foreach (var child in children) { GetNextRelevantChildren(child, computedChildrenList); } completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForVariables( computedChildrenList.Where( c => c.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase)) //Filter on user text .Select(child => child as DataDefinition), false)); } } else { //If no variables found, it's could be a children declared in a typedef.. var children = new List <Node>(); var potentialTypes = node.SymbolTable.GetTypes( t => t.Children != null && t.Children.Any( tc => tc.Name != null && tc.Name.Equals(userTokenToSeek.Text, StringComparison.InvariantCultureIgnoreCase)), new List <SymbolTable.Scope> { SymbolTable.Scope.Declarations, SymbolTable.Scope.Global, SymbolTable.Scope.Intrinsic, SymbolTable.Scope.Namespace }); foreach (var nodeType in potentialTypes.SelectMany(t => t.Children).Where(c => c != null && c.Name != null && c.Name.Equals(userTokenToSeek.Text, StringComparison.InvariantCultureIgnoreCase))) { var nodeDataDef = nodeType as DataDefinition; if (nodeDataDef == null) { continue; } var typeChildrens = GetTypeChildrens(node.SymbolTable, nodeDataDef); if (typeChildrens != null) { children.AddRange(typeChildrens); } } completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForVariables( children.Where( c => c.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase)) //Filter on user text .Select(child => child as DataDefinition), false)); } if (firstSignificantToken != null) { switch (firstSignificantToken.TokenType) { case TokenType.CALL: { functionDeclarationSignatureDictionary.Clear(); //Clear to avoid key collision //On CALL get possible procedures and functions in the seeked program var programs = node.SymbolTable.GetPrograms(userTokenToSeek.Text); if (programs != null && programs.Any()) { var procedures = programs.First() .SymbolTable.GetFunctions( f => f.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase) || f.VisualQualifiedName.ToString() .StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase), new List <SymbolTable.Scope> { SymbolTable.Scope.Declarations }); completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForProcedures(procedures, node, functionDeclarationSignatureDictionary, false)); } break; } case TokenType.TYPE: { //On TYPE get possible public types in the seeked program var programs = node.SymbolTable.GetPrograms(userTokenToSeek.Text); if (programs != null && programs.Any()) { var types = programs.First() .SymbolTable.GetTypes( t => t.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase), new List <SymbolTable.Scope> { SymbolTable.Scope.Declarations, SymbolTable.Scope.Global }); completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForType(types, node, false)); } break; } } } } return(completionItems.Distinct()); }