void PHPExpression::DoMakeUnique(PHPEntityBase::List_t& matches) { std::set<wxString> uniqueNames; PHPEntityBase::List_t uniqueList; for(PHPEntityBase::List_t::iterator iter = matches.begin(); iter != matches.end(); ++iter) { if(uniqueNames.count((*iter)->GetFullName()) == 0) { uniqueNames.insert((*iter)->GetFullName()); uniqueList.push_back(*iter); } } matches.swap(uniqueList); }
PHPEntityBase::List_t PHPSourceFile::GetAliases() const { PHPEntityBase::List_t aliases; std::map<wxString, wxString>::const_iterator iter = m_aliases.begin(); for(; iter != m_aliases.end(); ++iter) { // wrap each alias with class entity PHPEntityBase::Ptr_t klass(new PHPEntityClass()); klass->SetFullName(iter->second); klass->SetShortName(iter->first); klass->SetFilename(GetFilename()); aliases.push_back(klass); } return aliases; }
void PHPCodeCompletion::GetMembers(IEditor* editor, PHPEntityBase::List_t& members, wxString& scope) { members.clear(); scope.clear(); if(!editor) { return; } // Parse until the current position to get the current scope name { wxString text = editor->GetTextRange(0, editor->GetCurrentPosition()); PHPSourceFile sourceFile(text); sourceFile.SetParseFunctionBody(true); sourceFile.SetFilename(editor->GetFileName()); sourceFile.Parse(); const PHPEntityClass* scopeAtPoint = sourceFile.Class()->Cast<PHPEntityClass>(); if(!scopeAtPoint) { return; } scope = scopeAtPoint->GetFullName(); } // Second parse: parse the entire buffer so we are not limited by the caret position wxString text = editor->GetTextRange(0, editor->GetLength()); PHPSourceFile sourceFile(text); sourceFile.SetParseFunctionBody(true); sourceFile.SetFilename(editor->GetFileName()); sourceFile.Parse(); // Locate the scope PHPEntityBase::Ptr_t parentClass = sourceFile.Namespace()->FindChild(scope); if(!parentClass) return; // filter out const PHPEntityBase::List_t& children = parentClass->GetChildren(); PHPEntityBase::List_t::const_iterator iter = children.begin(); for(; iter != children.end(); ++iter) { PHPEntityBase::Ptr_t child = *iter; if(child->Is(kEntityTypeVariable) && child->Cast<PHPEntityVariable>()->IsMember() && !child->Cast<PHPEntityVariable>()->IsConst() && !child->Cast<PHPEntityVariable>()->IsStatic()) { // a member of a class members.push_back(child); } } }
PHPEntityBase::List_t PHPCodeCompletion::PhpKeywords(const wxString& prefix) const { LexerConf::Ptr_t lexer = ColoursAndFontsManager::Get().GetLexer("php"); if(!lexer) return PHPEntityBase::List_t(); wxString lcPrefix = prefix.Lower(); PHPEntityBase::List_t lst; wxString phpKeywords = lexer->GetKeyWords(4); wxArrayString phpKeywordsArr = ::wxStringTokenize(phpKeywords, " \t", wxTOKEN_STRTOK); for(size_t i = 0; i < phpKeywordsArr.GetCount(); ++i) { wxString lcWord = phpKeywordsArr.Item(i).Lower(); if(lcWord.StartsWith(lcPrefix)) { PHPEntityBase::Ptr_t keyword(new PHPEntityKeyword()); keyword->SetFullName(phpKeywordsArr.Item(i)); keyword->SetShortName(phpKeywordsArr.Item(i)); lst.push_back(keyword); } } return lst; }
void PHPExpression::Suggest(PHPEntityBase::Ptr_t resolved, PHPLookupTable& lookup, PHPEntityBase::List_t& matches) { // sanity if(!resolved) return; PHPEntityBase::Ptr_t currentScope = GetSourceFile()->CurrentScope(); // GetCount() == 0 && !GetFilter().IsEmpty() i.e. a word completion is required. // We enhance the list with the following: // - PHP keywords // - Global functions // - Global constants // - Function arguments // - Local variables (of the current scope) // - And aliases e.g. 'use foo\bar as Bar;' if(GetCount() == 0 && !GetFilter().IsEmpty()) { // For functions and constants, PHP will fall back to global functions or constants if a // namespaced function or constant does not exist. PHPEntityBase::List_t globals = lookup.FindGlobalFunctionAndConsts(PHPLookupTable::kLookupFlags_Contains, GetFilter()); matches.insert(matches.end(), globals.begin(), globals.end()); if(currentScope && (currentScope->Is(kEntityTypeFunction) || currentScope->Is(kEntityTypeNamespace))) { // If the current scope is a function // add the local variables + function arguments to the current list of matches const PHPEntityBase::List_t& children = currentScope->GetChildren(); PHPEntityBase::List_t::const_iterator iter = children.begin(); for(; iter != children.end(); ++iter) { PHPEntityBase::Ptr_t child = *iter; if(child->Is(kEntityTypeVariable) && child->GetShortName().Contains(GetFilter()) && child->GetShortName() != GetFilter()) { matches.push_back(child); } } } { // Add aliases PHPEntityBase::List_t aliases = GetSourceFile()->GetAliases(); PHPEntityBase::List_t::iterator iter = aliases.begin(); for(; iter != aliases.end(); ++iter) { if((*iter)->GetShortName().Contains(GetFilter())) { matches.push_back(*iter); } } } { // Add $this incase we are inside a class (but only if '$this' contains the filter string) wxString lcFilter = GetFilter().Lower(); if(GetSourceFile()->Class() && wxString("$this").Contains(lcFilter)) { PHPEntityBase::Ptr_t thiz(new PHPEntityVariable()); thiz->SetFullName("$this"); thiz->SetShortName("$this"); thiz->SetFilename(currentScope->GetFilename()); matches.push_back(thiz); } } } // Add the scoped matches // for the code completion size_t flags = PHPLookupTable::kLookupFlags_Contains | GetLookupFlags(); if(resolved->Is(kEntityTypeClass)) { if(resolved->Cast<PHPEntityClass>()->IsInterface() || resolved->Cast<PHPEntityClass>()->IsAbstractClass()) { flags |= PHPLookupTable::kLookupFlags_IncludeAbstractMethods; } } PHPEntityBase::List_t scopeChildren = lookup.FindChildren(resolved->GetDbId(), flags, GetFilter()); matches.insert(matches.end(), scopeChildren.begin(), scopeChildren.end()); // Incase the resolved is a namespace, suggest all children namespaces if(resolved->Is(kEntityTypeNamespace)) { PHPEntityBase::List_t namespaces = lookup.FindNamespaces(resolved->GetFullName(), GetFilter()); matches.insert(matches.end(), namespaces.begin(), namespaces.end()); } // and make the list unique DoMakeUnique(matches); }