@Override public Object visitImportFrom(ImportFrom node) throws Exception { String modRep = NodeUtils.getRepresentationString(node.module); if (NodeUtils.isWithin(line, col, node.module)) { // it is a token in the definition of a module int startingCol = node.module.beginColumn; int endingCol = startingCol; while (endingCol < this.col) { endingCol++; } int lastChar = endingCol - startingCol; moduleImported = modRep.substring(0, lastChar); int i = lastChar; while (i < modRep.length()) { if (Character.isJavaIdentifierPart(modRep.charAt(i))) { i++; } else { break; } } moduleImported += modRep.substring(lastChar, i); } else { // it was not the module, so, we have to check for each name alias imported for (aliasType alias : node.names) { // we do not check the 'as' because if it is some 'as', it will be gotten as a global in the // module if (NodeUtils.isWithin(line, col, alias.name)) { moduleImported = modRep + "." + NodeUtils.getRepresentationString(alias.name); } } } return super.visitImportFrom(node); }
/** * @param s the scope we're checking for * @return if the scope passed as a parameter starts with the same scope we have here. It should * not be called if the size of the scope we're checking is bigger than the size of 'this' * scope. */ @SuppressWarnings("unchecked") private boolean checkIfScopesMatch(ILocalScope s) { Iterator<SimpleNode> otIt = s.getScopeStack().iterator(); for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext(); ) { SimpleNode element = iter.next(); SimpleNode otElement = otIt.next(); if (element.beginColumn != otElement.beginColumn) { return false; } if (element.beginLine != otElement.beginLine) { return false; } if (!element.getClass().equals(otElement.getClass())) { return false; } String rep1 = NodeUtils.getFullRepresentationString(element); String rep2 = NodeUtils.getFullRepresentationString(otElement); if (rep1 == null || rep2 == null) { if (rep1 != rep2) { return false; } } else if (!rep1.equals(rep2)) { return false; } } return true; }
public boolean equals(Object obj) { MemoVisitor other = (MemoVisitor) obj; Iterator<SimpleNode> iter1 = other.visited.iterator(); for (Iterator<SimpleNode> iter = visited.iterator(); iter.hasNext(); ) { SimpleNode n = (SimpleNode) iter.next(); SimpleNode n1 = null; try { n1 = (SimpleNode) iter1.next(); } catch (NoSuchElementException e) { throw new RuntimeException("Just received " + n, e); } if (n instanceof Expr && n1 instanceof Expr) { continue; } print(n.getClass()); if (n.getClass().equals(n1.getClass()) == false) { print("n.getClass() != n1.getClass() " + n.getClass() + " != " + n1.getClass()); return false; } // if(n.beginColumn != n1.beginColumn){ // print("n = "+n+" n1 = "+n1); // print("n = "+NodeUtils.getFullRepresentationString(n)+" n1 = // "+NodeUtils.getFullRepresentationString(n1)); // print("n.beginColumn != n1.beginColumn "+ n.beginColumn +" != "+ // n1.beginColumn); // return false; // } // if(n.beginLine != n1.beginLine){ // print("n.beginLine != n1.beginLine "+ n.beginLine +" != "+ n1.beginLine); // return false; // } String s1 = NodeUtils.getFullRepresentationString(n); String s2 = NodeUtils.getFullRepresentationString(n1); if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) { print("(s1 == null && s2 != null) || (s1 != null && s2 == null)"); return false; } if (s1.equals(s2.replaceAll("\r", "")) == false) { print("s1 != s2 \n-->" + s1 + "<--\n!=\n-->" + s2 + "<--"); return false; } } return true; }
@Override public Object visitNameTok(NameTok node) throws Exception { if (node.ctx == NameTok.KeywordName) { if (this.line == node.beginLine) { String rep = NodeUtils.getRepresentationString(node); if (PySelection.isInside(col, node.beginColumn, rep.length())) { foundAsDefinition = true; // if it is found as a definition it is an 'exact' match, so, erase all the others. ILocalScope scope = new LocalScope(this.defsStack); for (Iterator<Definition> it = definitions.iterator(); it.hasNext(); ) { Definition d = it.next(); if (!d.scope.equals(scope)) { it.remove(); } } definitions.clear(); definitionFound = new KeywordParameterDefinition( line, node.beginColumn, rep, node, scope, module.get(), this.call.peek()); definitions.add(definitionFound); throw new StopVisitingException(); } } } return null; }
@Override public Object visitGlobal(Global node) throws Exception { for (NameTokType n : node.names) { globalDeclarationsStack.peek().add(NodeUtils.getFullRepresentationString(n)); } return null; }
private IInfo addAssignTargets( ASTEntry entry, String moduleName, int doOn, String path, boolean lastIsMethod) { String rep = NodeUtils.getFullRepresentationString(entry.node); if (lastIsMethod) { List<String> parts = StringUtils.dotSplit(rep); if (parts.size() >= 2) { // at least 2 parts are required if (parts.get(0).equals("self")) { rep = parts.get(1); // no intern construct (locked in the loop that calls this method) AttrInfo info = new AttrInfo( ObjectsPool.internUnsynched(rep), moduleName, ObjectsPool.internUnsynched(path), false); add(info, doOn); return info; } } } else { // no intern construct (locked in the loop that calls this method) AttrInfo info = new AttrInfo( ObjectsPool.internUnsynched(FullRepIterable.getFirstPart(rep)), moduleName, ObjectsPool.internUnsynched(path), false); add(info, doOn); return info; } return null; }
/** * Checks if some token is actually undefined and changes its representation if needed * * @return a tuple indicating if it really is undefined and the representation that should be * used. */ protected Tuple<Boolean, String> isActuallyUndefined(IToken token, String rep) { String tokenRepresentation = token.getRepresentation(); if (tokenRepresentation != null) { String firstPart = FullRepIterable.getFirstPart(tokenRepresentation); if (this.prefs.getTokensAlwaysInGlobals().contains(firstPart)) { return new Tuple<Boolean, String>( false, firstPart); // ok firstPart in not really undefined... } } boolean isActuallyUndefined = true; if (rep == null) { rep = tokenRepresentation; } int i; if ((i = rep.indexOf('.')) != -1) { rep = rep.substring(0, i); } String builtinType = NodeUtils.getBuiltinType(rep); if (builtinType != null) { isActuallyUndefined = false; // this is a builtin, so, it is defined after all } return new Tuple<Boolean, String>(isActuallyUndefined, rep); }
/** * @param ret the list where the representation should be added * @param expr the Name or Attribute that determines the class that should be added */ private void addRepresentationIfPossible(ArrayList<String> ret, exprType expr) { if (expr instanceof Name || expr instanceof Attribute) { String string = NodeUtils.getFullRepresentationString(expr); if (string != null) { ret.add(string); } } }
public void run(IAction action) { FastStringBuffer buf = new FastStringBuffer(); try { PyEdit pyEdit = getPyEdit(); PySelection pySelection = new PySelection(pyEdit); IPythonNature nature = pyEdit.getPythonNature(); File editorFile = pyEdit.getEditorFile(); if (editorFile != null) { if (nature != null) { String mod = nature.resolveModule(editorFile); if (mod != null) { buf.append(mod); } else { // Support for external files (not in PYTHONPATH). buf.append(FullRepIterable.getFirstPart(editorFile.getName())); } } else { buf.append(FullRepIterable.getFirstPart(editorFile.getName())); } } List<stmtType> path = FastParser.parseToKnowGloballyAccessiblePath( pySelection.getDoc(), pySelection.getStartLineIndex()); for (stmtType stmtType : path) { if (buf.length() > 0) { buf.append('.'); } buf.append(NodeUtils.getRepresentationString(stmtType)); } } catch (MisconfigurationException e1) { Log.log(e1); return; } Transfer[] dataTypes = new Transfer[] {TextTransfer.getInstance()}; Object[] data = new Object[] {buf.toString()}; Clipboard clipboard = new Clipboard(EditorUtils.getShell().getDisplay()); try { clipboard.setContents(data, dataTypes); } catch (SWTError e) { if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { throw e; } MessageDialog.openError( EditorUtils.getShell(), "Error copying to clipboard.", e.getMessage()); } finally { clipboard.dispose(); } }
/** * @param lastMayBeMethod if true, it gets the path and accepts a method (if it is the last in the * stack) if false, null is returned if a method is found. * @param tempStack is a temporary stack object (which may be cleared) * @return a tuple, where the first element is the path where the entry is located (may return * null). and the second element is a boolen that indicates if the last was actually a method * or not. */ private Tuple<String, Boolean> getPathToRoot( ASTEntry entry, boolean lastMayBeMethod, boolean acceptAny, FastStack<SimpleNode> tempStack) { if (entry.parent == null) { return null; } // just to be sure that it's empty tempStack.clear(); boolean lastIsMethod = false; // if the last 'may be a method', in this case, we have to remember that it will actually be the // first one // to be analyzed. // let's get the stack while (entry.parent != null) { if (entry.parent.node instanceof ClassDef) { tempStack.push(entry.parent.node); } else if (entry.parent.node instanceof FunctionDef) { if (!acceptAny) { if (lastIsMethod) { // already found a method return null; } if (!lastMayBeMethod) { return null; } // ok, the last one may be a method... (in this search, it MUST be the first one...) if (tempStack.size() != 0) { return null; } } // ok, there was a class, so, let's go and set it tempStack.push(entry.parent.node); lastIsMethod = true; } else { return null; } entry = entry.parent; } // now that we have the stack, let's make it into a path... FastStringBuffer buf = new FastStringBuffer(); while (tempStack.size() > 0) { if (buf.length() > 0) { buf.append("."); } buf.append(NodeUtils.getRepresentationString(tempStack.pop())); } return new Tuple<String, Boolean>(buf.toString(), lastIsMethod); }
/** * @param request this is the request for the completion * @param theList OUT - returned completions are added here. (IToken instances) * @param getOnlySupers whether we should only get things from super classes (in this case, we * won't get things from the current class) * @param checkIfInCorrectScope if true, we'll first check if we're in a scope that actually has a * method with 'self' or 'cls' * @return true if we actually tried to get the completions for self or cls. * @throws MisconfigurationException */ @SuppressWarnings("unchecked") public static boolean getSelfOrClsCompletions( CompletionRequest request, List theList, ICompletionState state, boolean getOnlySupers, boolean checkIfInCorrectScope, String lookForRep) throws MisconfigurationException { SimpleNode s = PyParser.reparseDocument( new PyParser.ParserInfo(request.doc, true, request.nature, state.getLine())) .o1; if (s != null) { FindScopeVisitor visitor = new FindScopeVisitor(state.getLine(), 0); try { s.accept(visitor); if (checkIfInCorrectScope) { boolean scopeCorrect = false; FastStack<SimpleNode> scopeStack = visitor.scope.getScopeStack(); for (Iterator<SimpleNode> it = scopeStack.topDownIterator(); scopeCorrect == false && it.hasNext(); ) { SimpleNode node = it.next(); if (node instanceof FunctionDef) { FunctionDef funcDef = (FunctionDef) node; if (funcDef.args != null && funcDef.args.args != null && funcDef.args.args.length > 0) { // ok, we have some arg, let's check for self or cls String rep = NodeUtils.getRepresentationString(funcDef.args.args[0]); if (rep != null && (rep.equals("self") || rep.equals("cls"))) { scopeCorrect = true; } } } } if (!scopeCorrect) { return false; } } if (lookForRep.equals("self")) { state.setLookingFor(ICompletionState.LOOKING_FOR_INSTANCED_VARIABLE); } else { state.setLookingFor(ICompletionState.LOOKING_FOR_CLASSMETHOD_VARIABLE); } getSelfOrClsCompletions(visitor.scope, request, theList, state, getOnlySupers); } catch (Exception e1) { PydevPlugin.log(e1); } return true; } return false; }
private IInfo addAssignTargets( ASTEntry entry, String moduleName, int doOn, String path, boolean lastIsMethod) { String rep = NodeUtils.getFullRepresentationString(entry.node); if (lastIsMethod) { List<String> parts = StringUtils.dotSplit(rep); if (parts.size() >= 2) { // at least 2 parts are required if (parts.get(0).equals("self")) { rep = parts.get(1); return addAttribute(rep, moduleName, doOn, path); } } } else { return addAttribute(FullRepIterable.getFirstPart(rep), moduleName, doOn, path); } return null; }
/** * @param node the declaration node we're interested in (class or function) * @param name the token that represents the name of that declaration */ private void checkDeclaration(SimpleNode node, NameTok name) { String rep = NodeUtils.getRepresentationString(node); if (rep.equals(tokenToFind) && line == name.beginLine && col >= name.beginColumn && col <= name.beginColumn + rep.length()) { foundAsDefinition = true; // if it is found as a definition it is an 'exact' match, so, erase all the others. ILocalScope scope = new LocalScope(this.defsStack); for (Iterator<Definition> it = definitions.iterator(); it.hasNext(); ) { Definition d = it.next(); if (!d.scope.equals(scope)) { it.remove(); } } definitionFound = new Definition(line, name.beginColumn, rep, node, scope, module.get()); definitions.add(definitionFound); } }
/** @see org.python.pydev.core.ILocalScope#getLocalTokens(int, int, boolean) */ public IToken[] getLocalTokens(int endLine, int col, boolean onlyArgs) { Set<SourceToken> comps = new HashSet<SourceToken>(); for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext(); ) { SimpleNode element = iter.next(); stmtType[] body = null; if (element instanceof FunctionDef) { FunctionDef f = (FunctionDef) element; final argumentsType args = f.args; for (int i = 0; i < args.args.length; i++) { String s = NodeUtils.getRepresentationString(args.args[i]); comps.add(new SourceToken(args.args[i], s, "", "", "", IToken.TYPE_PARAM)); } if (args.vararg != null) { String s = NodeUtils.getRepresentationString(args.vararg); comps.add(new SourceToken(args.vararg, s, "", "", "", IToken.TYPE_PARAM)); } if (args.kwarg != null) { String s = NodeUtils.getRepresentationString(args.kwarg); comps.add(new SourceToken(args.kwarg, s, "", "", "", IToken.TYPE_PARAM)); } if (args.kwonlyargs != null) { for (int i = 0; i < args.kwonlyargs.length; i++) { String s = NodeUtils.getRepresentationString(args.kwonlyargs[i]); comps.add(new SourceToken(args.kwonlyargs[i], s, "", "", "", IToken.TYPE_PARAM)); } } if (onlyArgs) { continue; } body = f.body; } else if (element instanceof ClassDef && !iter.hasNext()) { ClassDef classDef = (ClassDef) element; body = classDef.body; } if (body != null) { try { for (int i = 0; i < body.length; i++) { GlobalModelVisitor visitor = new GlobalModelVisitor(GlobalModelVisitor.GLOBAL_TOKENS, "", false, true); stmtType stmt = body[i]; if (stmt == null) { continue; } stmt.accept(visitor); List<IToken> t = visitor.tokens; for (Iterator<IToken> iterator = t.iterator(); iterator.hasNext(); ) { SourceToken tok = (SourceToken) iterator.next(); // if it is found here, it is a local type tok.type = IToken.TYPE_LOCAL; if (tok.getAst().beginLine <= endLine) { comps.add(tok); } } } } catch (Exception e) { Log.log(e); } } } return comps.toArray(new SourceToken[0]); }
/** * Decides which process should take care of the request. * * @param request */ public static IRefactorRenameProcess getProcess( Definition definition, RefactoringRequest request) { if (definition instanceof AssignDefinition) { AssignDefinition d = (AssignDefinition) definition; if (d.target.indexOf('.') != -1) { if (d.target.startsWith("self.")) { // ok, it is a member and not a local return new PyRenameSelfAttributeProcess(definition, d.target); } else { return new PyRenameAttributeProcess(definition, d.target); } } else { if (definition.scope != null) { // classvar if (definition.scope.isLastClassDef()) { return new PyRenameAttributeProcess(definition, d.target); } FastStack scopeStack = definition.scope.getScopeStack(); if (request.moduleName.equals(definition.module.getName())) { if (!scopeStack.empty()) { Object peek = scopeStack.peek(); if (peek instanceof FunctionDef) { return new PyRenameLocalProcess(definition); } } } } return new PyRenameGlobalProcess(definition); } } if (definition.ast != null) { if (definition.ast instanceof ClassDef) { return new PyRenameClassProcess(definition); } if (definition.ast instanceof Name) { Name n = (Name) definition.ast; if (n.ctx == Name.Param || n.ctx == Attribute.KwOnlyParam) { return new PyRenameParameterProcess(definition); } } if (definition instanceof KeywordParameterDefinition) { return new PyRenameParameterProcess( (KeywordParameterDefinition) definition, request.nature); } if (definition.ast instanceof FunctionDef) { return new PyRenameFunctionProcess(definition); } if (NodeUtils.isImport(definition.ast)) { // this means that we found an import and we cannot actually map that import to a definition // (so, it is an unresolved import) return new PyRenameImportProcess(definition); } } else { // the definition ast is null. This should mean that it was actually an import // and pointed to some module return new PyRenameImportProcess(definition); } if (definition.scope != null) { // classvar if (definition.scope.isLastClassDef()) { return new PyRenameAttributeProcess(definition, definition.value); } FastStack scopeStack = definition.scope.getScopeStack(); if (request.moduleName.equals(definition.module.getName())) { if (!scopeStack.empty()) { Object peek = scopeStack.peek(); if (peek instanceof FunctionDef) { return new PyRenameLocalProcess(definition); } } } } return new PyRenameGlobalProcess(definition); }
/** * Puts the found positions referente to the occurrences in the group * * @param document the document that will contain this positions * @param group the group that will contain this positions * @param ps the selection used * @return * @throws BadLocationException * @throws OperationCanceledException * @throws CoreException * @throws MisconfigurationException */ private boolean fillWithOccurrences( IDocument document, LinkedPositionGroup group, IProgressMonitor monitor, PySelection ps) throws BadLocationException, OperationCanceledException, CoreException, MisconfigurationException { RefactoringRequest req = MarkOccurrencesJob.getRefactoringRequest( pyEdit, MarkOccurrencesJob.getRefactorAction(pyEdit), ps); if (monitor.isCanceled()) { return false; } PyRenameEntryPoint processor = new PyRenameEntryPoint(req); // process it to get what we need processor.checkInitialConditions(monitor); processor.checkFinalConditions(monitor, null); HashSet<ASTEntry> occurrences = processor.getOccurrences(); if (monitor.isCanceled()) { return false; } // used so that we don't add duplicates Set<Tuple<Integer, Integer>> found = new HashSet<Tuple<Integer, Integer>>(); List<ProposalPosition> groupPositions = new ArrayList<ProposalPosition>(); if (occurrences != null) { // first, just sort by position (line, col) ArrayList<ASTEntry> sortedOccurrences = new ArrayList<ASTEntry>(occurrences); Collections.sort( sortedOccurrences, new Comparator<ASTEntry>() { public int compare(ASTEntry o1, ASTEntry o2) { int thisVal = o1.node.beginLine; int anotherVal = o2.node.beginLine; int ret; if (thisVal == anotherVal) { // if it's in the same line, let's sort by column thisVal = o1.node.beginColumn; anotherVal = o2.node.beginColumn; ret = (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); } else { ret = (thisVal < anotherVal ? -1 : 1); } return ret; } }); // now, gather positions to add to the group int i = 0; int firstPosition = -1; int absoluteCursorOffset = ps.getAbsoluteCursorOffset(); for (ASTEntry entry : sortedOccurrences) { try { IRegion lineInformation = document.getLineInformation(entry.node.beginLine - 1); int colDef = NodeUtils.getClassOrFuncColDefinition(entry.node) - 1; int offset = lineInformation.getOffset() + colDef; int len = req.initialName.length(); Tuple<Integer, Integer> foundAt = new Tuple<Integer, Integer>(offset, len); if (!found.contains(foundAt)) { i++; ProposalPosition proposalPosition = new ProposalPosition(document, offset, len, i, new ICompletionProposal[0]); found.add(foundAt); groupPositions.add(proposalPosition); if (offset <= absoluteCursorOffset && absoluteCursorOffset < offset + len) { firstPosition = i; } } } catch (Exception e) { Log.log(e); return false; } } if (firstPosition != -1) { ArrayList<ProposalPosition> newGroupPositions = new ArrayList<ProposalPosition>(); // add from current to end for (i = firstPosition - 1; i < groupPositions.size(); i++) { newGroupPositions.add(groupPositions.get(i)); } // and now from the start up to the current for (i = 0; i < firstPosition - 1; i++) { newGroupPositions.add(groupPositions.get(i)); } groupPositions = newGroupPositions; } for (ProposalPosition proposalPosition : groupPositions) { group.addPosition(proposalPosition); } } return groupPositions.size() > 0; }
/** * @see * org.python.pydev.parser.jython.ast.VisitorBase#visitAssign(org.python.pydev.parser.jython.ast.Assign) */ public Object visitAssign(Assign node) throws Exception { ILocalScope scope = new LocalScope(this.defsStack); if (foundAsDefinition && !scope.equals( definitionFound .scope)) { // if it is found as a definition it is an 'exact' match, so, we do not // keep checking it return null; } for (int i = 0; i < node.targets.length; i++) { exprType target = node.targets[i]; if (target instanceof Subscript) { continue; // assigning to an element and not the variable itself. E.g.: mydict[1] = 10 // (instead of mydict = 10) } if (target instanceof Tuple) { // if assign is xxx, yyy = 1, 2 // let's separate those as different assigns and analyze one by one Tuple targetTuple = (Tuple) target; if (node.value instanceof Tuple) { Tuple valueTuple = (Tuple) node.value; checkTupleAssignTarget(targetTuple, valueTuple.elts); } else if (node.value instanceof org.python.pydev.parser.jython.ast.List) { org.python.pydev.parser.jython.ast.List valueList = (org.python.pydev.parser.jython.ast.List) node.value; checkTupleAssignTarget(targetTuple, valueList.elts); } else { checkTupleAssignTarget(targetTuple, new exprType[] {node.value}); } } else { String rep = NodeUtils.getFullRepresentationString(target); if (tokenToFind.equals( rep)) { // note, order of equals is important (because one side may be null). exprType nodeValue = node.value; String value = NodeUtils.getFullRepresentationString(nodeValue); if (value == null) { value = ""; } // get the line and column correspondent to the target int line = NodeUtils.getLineDefinition(target); int col = NodeUtils.getColDefinition(target); AssignDefinition definition = new AssignDefinition(value, rep, i, node, line, col, scope, module.get()); // mark it as global (if it was found as global in some of the previous contexts). for (Set<String> globals : globalDeclarationsStack) { if (globals.contains(rep)) { definition.foundAsGlobal = true; } } definitions.add(definition); } } } return null; }
/** @see {@link ILocalScope#getPossibleClassesForActivationToken(String)} */ public List<String> getPossibleClassesForActivationToken(String actTok) { ArrayList<String> ret = new ArrayList<String>(); Iterator<SimpleNode> it = this.scope.topDownIterator(); if (!it.hasNext()) { return ret; } SimpleNode element = it.next(); // ok, that's the scope we have to analyze // Search for docstrings. String typeForParameter = NodeUtils.getTypeForParameterFromDocstring(actTok, element); if (typeForParameter != null) { ret.add(typeForParameter); } // Search for assert isinstance(). SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element); Iterator<ASTEntry> iterator = visitor.getIterator(); ArrayList<Object> lst = new ArrayList<Object>(); Name nameDefinition = null; while (iterator.hasNext()) { ASTEntry entry = iterator.next(); if (entry.node.specialsAfter != null) { lst.addAll(entry.node.specialsAfter); } if (entry.node.specialsBefore != null) { lst.addAll(entry.node.specialsBefore); } if (!(entry.node instanceof Assert)) { if (entry.node instanceof Str) { lst.add(entry.node); } if (entry.node instanceof Name) { Name name = (Name) entry.node; if (name.ctx == Name.Load) { if (actTok.equals(name.id)) { nameDefinition = name; } } } continue; } Assert ass = (Assert) entry.node; if (ass.test instanceof Call) { Call call = (Call) ass.test; String rep = NodeUtils.getFullRepresentationString(call.func); if (rep == null) { continue; } Integer classIndex = ISINSTANCE_POSSIBILITIES.get(FullRepIterable.getLastPart(rep).toLowerCase()); if (classIndex != null) { if (call.args != null && (call.args.length >= Math.max(classIndex, 1))) { // in all cases, the instance is the 1st parameter. String foundActTok = NodeUtils.getFullRepresentationString(call.args[0]); if (foundActTok != null && foundActTok.equals(actTok)) { if (classIndex > 0) { exprType type = call.args[classIndex - 1]; if (type instanceof Tuple) { // case: isinstance(obj, (Class1,Class2)) Tuple tuple = (Tuple) type; for (exprType expr : tuple.elts) { addRepresentationIfPossible(ret, expr); } } else { // case: isinstance(obj, Class) addRepresentationIfPossible(ret, type); } } else { // zope case Interface.implementedBy(obj) -> Interface added ret.add(FullRepIterable.getWithoutLastPart(rep)); } } } } } } if (nameDefinition != null) { int s = lst.size(); for (int i = 0; i < s; i++) { Object object = lst.get(i); if (object instanceof commentType) { commentType commentType = (commentType) object; // according to http://sphinx-doc.org/ext/autodoc.html#directive-autoattribute, // to be a valid comment must be before the definition or in the same line. if (Math.abs(commentType.beginLine - nameDefinition.beginLine) <= 2) { if (commentType.id != null) { String trim = commentType.id.trim(); if (trim.startsWith("#")) { trim = trim.substring(1).trim(); } if (trim.startsWith(":")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim.substring(1)); if (type != null) { ret.add(type); } } else if (trim.startsWith("@")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim); if (type != null) { ret.add(type); } } } } } else if (object instanceof Str) { Str str = (Str) object; if (Math.abs(str.beginLine - nameDefinition.beginLine) <= 2) { if (str.s != null) { String trim = str.s.trim(); if (trim.startsWith("#")) { trim = trim.substring(1).trim(); } if (trim.startsWith(":")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim.substring(1)); if (type != null) { ret.add(type); } } else if (trim.startsWith("@")) { String type = NodeUtils.getTypeForParameterFromDocstring(actTok, trim); if (type != null) { ret.add(type); } } } } } } } return ret; }
@Override public void addProps( MarkerAnnotationAndPosition markerAnnotation, IAnalysisPreferences analysisPreferences, String line, PySelection ps, int offset, IPythonNature nature, PyEdit edit, List<ICompletionProposal> props) throws BadLocationException, CoreException { if (nature == null) { return; } ICodeCompletionASTManager astManager = nature.getAstManager(); if (astManager == null) { return; } if (markerAnnotation.position == null) { return; } IMarker marker = markerAnnotation.markerAnnotation.getMarker(); Integer id = (Integer) marker.getAttribute(AnalysisRunner.PYDEV_ANALYSIS_TYPE); int start = markerAnnotation.position.offset; int end = start + markerAnnotation.position.length; ps.setSelection(start, end); String markerContents; try { markerContents = ps.getSelectedText(); } catch (Exception e1) { return; // Selection may be wrong. } IDocument doc = ps.getDoc(); List<String> parametersAfterCall = ps.getParametersAfterCall(end); switch (id) { case IAnalysisPreferences.TYPE_UNDEFINED_VARIABLE: addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall); break; case IAnalysisPreferences.TYPE_UNDEFINED_IMPORT_VARIABLE: // Say we had something as: // import sys // sys.Bar // in which case 'Bar' is undefined // in this situation, the activationTokenAndQual would be "sys." and "Bar" // and we want to get the definition for "sys" String[] activationTokenAndQual = ps.getActivationTokenAndQual(true); if (activationTokenAndQual[0].endsWith(".")) { ArrayList<IDefinition> selected = findDefinitions(nature, edit, start - 2, doc); for (IDefinition iDefinition : selected) { IModule module = iDefinition.getModule(); if (module.getFile() != null) { Definition definition = (Definition) iDefinition; File file = module.getFile(); if (definition.ast == null) { // if we have no ast in the definition, it means the module itself was found (global // scope) // Add option to create class at the given module! addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall, file); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall, file); } else if (definition.ast instanceof ClassDef) { ClassDef classDef = (ClassDef) definition.ast; // Ok, we should create a field or method in this case (accessing a classmethod or // staticmethod) PyCreateMethodOrField pyCreateMethod = new PyCreateMethodOrField(); String className = NodeUtils.getNameFromNameTok(classDef.name); pyCreateMethod.setCreateInClass(className); pyCreateMethod.setCreateAs(PyCreateMethodOrField.CLASSMETHOD); addCreateClassmethodOption( ps, edit, props, markerContents, parametersAfterCall, pyCreateMethod, file, className); } } } } break; case IAnalysisPreferences.TYPE_UNRESOLVED_IMPORT: // This case is the following: from other_module4 import Foo // with 'Foo' being undefined. // So, we have to suggest creating a Foo class/method in other_module4 PyImportsHandling importsHandling = new PyImportsHandling(ps.getDoc(), false); int offsetLine = ps.getLineOfOffset(start); String selectedText = ps.getSelectedText(); Tuple<IModule, String> found = null; String foundFromImportStr = null; boolean isImportFrom = false; OUT: for (ImportHandle handle : importsHandling) { if (handle.startFoundLine == offsetLine || handle.endFoundLine == offsetLine || (handle.startFoundLine < offsetLine && handle.endFoundLine > offsetLine)) { List<ImportHandleInfo> importInfo = handle.getImportInfo(); for (ImportHandleInfo importHandleInfo : importInfo) { String fromImportStr = importHandleInfo.getFromImportStr(); List<String> importedStr = importHandleInfo.getImportedStr(); for (String imported : importedStr) { if (selectedText.equals(imported)) { if (fromImportStr != null) { foundFromImportStr = fromImportStr + "." + imported; isImportFrom = true; } else { // if fromImportStr == null, it's not a from xxx import yyy (i.e.: simple // import) foundFromImportStr = imported; } try { String currentModule = nature.resolveModule(edit.getEditorFile()); ICompletionState state = CompletionStateFactory.getEmptyCompletionState( nature, new CompletionCache()); found = nature .getAstManager() .findModule( foundFromImportStr, currentModule, state, new SourceModule( currentModule, edit.getEditorFile(), edit.getAST(), null)); } catch (Exception e) { Log.log(e); } break OUT; } } } break OUT; } } boolean addOptionToCreateClassOrMethod = isImportFrom; if (found != null && found.o1 != null) { // Ok, we found a module, now, it may be that we still have to create some intermediary // modules // or just create a class or method at the end. if (found.o1 instanceof SourceModule) { // if all was found, there's nothing left to create. if (found.o2 != null && found.o2.length() > 0) { SourceModule sourceModule = (SourceModule) found.o1; File file = sourceModule.getFile(); if (found.o2.indexOf('.') != -1) { // We have to create some intermediary structure. if (!addOptionToCreateClassOrMethod) { // Cannot create class or method from the info (only the module structure). if (sourceModule.getName().endsWith(".__init__")) { File f = getFileStructure(file.getParentFile(), found.o2); addCreateModuleOption(ps, edit, props, markerContents, f); } } else { // Ok, the leaf may be a class or method. if (sourceModule.getName().endsWith(".__init__")) { String moduleName = FullRepIterable.getWithoutLastPart(sourceModule.getName()); String withoutLastPart = FullRepIterable.getWithoutLastPart(found.o2); moduleName += "." + withoutLastPart; String classOrMethodName = FullRepIterable.getLastPart(found.o2); File f = getFileStructure(file.getParentFile(), withoutLastPart); addCreateClassInNewModuleOption( ps, edit, props, classOrMethodName, moduleName, parametersAfterCall, f); addCreateMethodInNewModuleOption( ps, edit, props, classOrMethodName, moduleName, parametersAfterCall, f); } } } else { // Ok, it's all there, we just have to create the leaf. if (!addOptionToCreateClassOrMethod || sourceModule.getName().endsWith(".__init__")) { // Cannot create class or method from the info (only the module structure). if (sourceModule.getName().endsWith(".__init__")) { File f = new File( file.getParent(), found.o2 + FileTypesPreferencesPage.getDefaultDottedPythonExtension()); addCreateModuleOption(ps, edit, props, markerContents, f); } } else { // Ok, the leaf may be a class or method. addCreateClassOption(ps, edit, props, markerContents, parametersAfterCall, file); addCreateMethodOption(ps, edit, props, markerContents, parametersAfterCall, file); } } } } } else if (foundFromImportStr != null) { // We couldn't find anything there, so, we have to create the modules structure as needed // and // maybe create a class or module at the end (but only if it's an import from). // Ok, it's all there, we just have to create the leaf. // Discover the source folder where we should create the structure. File editorFile = edit.getEditorFile(); String onlyProjectPythonPathStr = nature.getPythonPathNature().getOnlyProjectPythonPathStr(false); List<String> split = StringUtils.splitAndRemoveEmptyTrimmed(onlyProjectPythonPathStr, '|'); for (int i = 0; i < split.size(); i++) { String fullPath = FileUtils.getFileAbsolutePath(split.get(i)); fullPath = PythonPathHelper.getDefaultPathStr(fullPath); split.set(i, fullPath); } HashSet<String> projectSourcePath = new HashSet<String>(split); if (projectSourcePath.size() == 0) { return; // No source folder for editor... this shouldn't happen (code analysis wouldn't // even run on it). } String fullPath = FileUtils.getFileAbsolutePath(editorFile); fullPath = PythonPathHelper.getDefaultPathStr(fullPath); String foundSourceFolderFullPath = null; if (projectSourcePath.size() == 1) { foundSourceFolderFullPath = projectSourcePath.iterator().next(); } else { for (String string : projectSourcePath) { if (fullPath.startsWith(string)) { // Use this as the source folder foundSourceFolderFullPath = string; break; } } } if (foundSourceFolderFullPath != null) { if (!addOptionToCreateClassOrMethod) { // Cannot create class or method from the info (only the module structure). File f = getFileStructure(new File(foundSourceFolderFullPath), foundFromImportStr); addCreateModuleOption(ps, edit, props, foundFromImportStr, f); } else { // Ok, the leaf may be a class or method. String moduleName = FullRepIterable.getWithoutLastPart(foundFromImportStr); File file = getFileStructure(new File(foundSourceFolderFullPath), moduleName); String lastPart = FullRepIterable.getLastPart(foundFromImportStr); addCreateClassInNewModuleOption( ps, edit, props, lastPart, moduleName, parametersAfterCall, file); addCreateMethodInNewModuleOption( ps, edit, props, lastPart, moduleName, parametersAfterCall, file); } } } break; } }
/** * @return the function name for this breakpoint. * <p>A return of "None" signals that we couldn't discover the function name (so, we should * try to match things in the whole file, and not only in the given context, as we don't know * which context it is) */ public String getFunctionName() { String fileStr = getFile(); File file = fileStr != null ? new File(fileStr) : null; if (file == null || !file.exists()) { return "None"; } if (file.lastModified() == lastModifiedTimeCached) { return functionName; } try { IPythonNature nature = getPythonNature(); if (nature == null) { lastModifiedTimeCached = 0; return "None"; } ICodeCompletionASTManager astManager = nature.getAstManager(); if (astManager == null) { lastModifiedTimeCached = 0; return "None"; } // Only mark it as found if we were able to get the python nature (otherwise, this could // change later // if requesting during a setup) if (nature.startRequests()) { // start requests, as we'll ask for resolve and get module. SourceModule sourceModule = null; try { String modName = nature.resolveModule(fileStr); if (modName != null) { // when all is set up, this is the most likely path we're going to use // so, we shouldn't have delays when the module is changed, as it's already // ok for use. IModule module = astManager.getModule(modName, nature, true); if (module instanceof SourceModule) { sourceModule = (SourceModule) module; } } } finally { nature.endRequests(); } lastModifiedTimeCached = file.lastModified(); if (sourceModule == null) { // the text for the breakpoint requires the function name, and it may be requested before // the ast manager is actually restored (so, modName is None, and we have little // alternative // but making a parse to get the function name) IDocument doc = getDocument(); sourceModule = AbstractModule.createModuleFromDoc("", null, doc, nature, true); } int lineToUse = getLineNumber() - 1; if (sourceModule == null || sourceModule.getAst() == null || lineToUse < 0) { functionName = "None"; return functionName; } SimpleNode ast = sourceModule.getAst(); functionName = NodeUtils.getContextName(lineToUse, ast); if (functionName == null) { functionName = ""; // global context } return functionName; } // If it was found, it would've already returned. So, match anything as we couldn't determine // it. functionName = "None"; } catch (Exception e) { // Some error happened determining it. Match anything. Log.log( "Error determining breakpoint context. Breakpoint at: " + file + " will match any context.", e); functionName = "None"; } return functionName; }
/** * Get self completions when you already have a scope * * @throws MisconfigurationException */ @SuppressWarnings("unchecked") public static void getSelfOrClsCompletions( ILocalScope scope, CompletionRequest request, List theList, ICompletionState state, boolean getOnlySupers) throws BadLocationException, MisconfigurationException { for (Iterator<SimpleNode> it = scope.iterator(); it.hasNext(); ) { SimpleNode node = it.next(); if (node instanceof ClassDef) { ClassDef d = (ClassDef) node; if (getOnlySupers) { List gottenComps = new ArrayList(); for (int i = 0; i < d.bases.length; i++) { if (d.bases[i] instanceof Name) { Name n = (Name) d.bases[i]; state.setActivationToken(n.id); IToken[] completions; try { completions = request .nature .getAstManager() .getCompletionsForToken(request.editorFile, request.doc, state); gottenComps.addAll(Arrays.asList(completions)); } catch (CompletionRecursionException e) { // ok... } } } theList.addAll(gottenComps); } else { // ok, get the completions for the class, only thing we have to take care now is that we // may // not have only 'self' for completion, but something like self.foo. // so, let's analyze our activation token to see what should we do. String trimmed = request.activationToken.replace('.', ' ').trim(); String[] actTokStrs = trimmed.split(" "); if (actTokStrs.length == 0 || (!actTokStrs[0].equals("self") && !actTokStrs[0].equals("cls"))) { throw new AssertionError( "We need to have at least one token (self or cls) for doing completions in the class."); } if (actTokStrs.length == 1) { // ok, it's just really self, let's get on to get the completions state.setActivationToken(NodeUtils.getNameFromNameTok((NameTok) d.name)); try { theList.addAll( Arrays.asList( request .nature .getAstManager() .getCompletionsForToken(request.editorFile, request.doc, state))); } catch (CompletionRecursionException e) { // ok } } else { // it's not only self, so, first we have to get the definition of the token // the first one is self, so, just discard it, and go on, token by token to know what is // the last // one we are completing (e.g.: self.foo.bar) int line = request.doc.getLineOfOffset(request.documentOffset); IRegion region = request.doc.getLineInformationOfOffset(request.documentOffset); int col = request.documentOffset - region.getOffset(); // ok, try our best shot at getting the module name of the current buffer used in the // request. String modName = ""; File requestFile = request.editorFile; if (request.editorFile != null) { String resolveModule = request.nature.resolveModule(requestFile); if (resolveModule != null) { modName = resolveModule; } } IModule module = AbstractModule.createModuleFromDoc( modName, requestFile, request.doc, request.nature, line); AbstractASTManager astMan = ((AbstractASTManager) request.nature.getAstManager()); theList.addAll( new AssignAnalysis() .getAssignCompletions( astMan, module, new CompletionState( line, col, request.activationToken, request.nature, request.qualifier)) .completions); } } } } }
public Collection<IToken> getInterfaceForLocal( String activationToken, boolean addAttributeAccess, boolean addLocalsFromHasAttr) { Set<SourceToken> comps = new HashSet<SourceToken>(); Iterator<SimpleNode> it = this.scope.topDownIterator(); if (!it.hasNext()) { return new ArrayList<IToken>(); } SimpleNode element = it.next(); String dottedActTok = activationToken + '.'; // ok, that's the scope we have to analyze SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element); ArrayList<Class> classes = new ArrayList<Class>(2); if (addAttributeAccess) { classes.add(Attribute.class); } if (addLocalsFromHasAttr) { classes.add(Call.class); } Iterator<ASTEntry> iterator = visitor.getIterator(classes.toArray(new Class[classes.size()])); while (iterator.hasNext()) { ASTEntry entry = iterator.next(); if (entry.node instanceof Attribute) { String rep = NodeUtils.getFullRepresentationString(entry.node); if (rep.startsWith(dottedActTok)) { rep = rep.substring(dottedActTok.length()); if (NodeUtils.isValidNameRepresentation( rep)) { // that'd be something that can happen when trying to recreate the parsing comps.add( new SourceToken( entry.node, FullRepIterable.getFirstPart(rep), "", "", "", IToken.TYPE_OBJECT_FOUND_INTERFACE)); } } } else if (entry.node instanceof Call) { Call call = (Call) entry.node; if ("hasattr".equals(NodeUtils.getFullRepresentationString(call.func)) && call.args != null && call.args.length == 2) { String rep = NodeUtils.getFullRepresentationString(call.args[0]); if (rep.equals(activationToken)) { exprType node = call.args[1]; if (node instanceof Str) { Str str = (Str) node; String attrName = str.s; if (NodeUtils.isValidNameRepresentation(attrName)) { comps.add( new SourceToken( node, attrName, "", "", "", IToken.TYPE_OBJECT_FOUND_INTERFACE)); } } } } } } return new ArrayList<IToken>(comps); }
/** * Called after the creation of any module. Used as a workaround for filling tokens that are in no * way available in the code-completion through the regular inspection. * * <p>The django objects class is the reason why this happens... It's structure for the creation * on a model class follows no real patterns for the creation of the 'objects' attribute in the * class, and thus, we have no real generic way of discovering it (actually, even by looking at * the class definition this is very obscure), so, the solution found is creating the objects by * decorating the module with that info. */ private AbstractModule decorateModule(AbstractModule n, IPythonNature nature) { if (n instanceof SourceModule && "django.db.models.base".equals(n.getName())) { SourceModule sourceModule = (SourceModule) n; SimpleNode ast = sourceModule.getAst(); for (SimpleNode node : ((Module) ast).body) { if (node instanceof ClassDef && "Model".equals(NodeUtils.getRepresentationString(node))) { Object[][] metaclassAttrs = new Object[][] { {"objects", NodeUtils.makeAttribute("django.db.models.manager.Manager()")}, {"DoesNotExist", new Name("Exception", Name.Load, false)}, {"MultipleObjectsReturned", new Name("Exception", Name.Load, false)}, }; ClassDef classDef = (ClassDef) node; stmtType[] newBody = new stmtType[classDef.body.length + metaclassAttrs.length]; System.arraycopy(classDef.body, 0, newBody, metaclassAttrs.length, classDef.body.length); int i = 0; for (Object[] objAndType : metaclassAttrs) { // Note that the line/col is important so that we correctly acknowledge it inside the // "class Model" scope. Name name = new Name((String) objAndType[0], Name.Store, false); name.beginColumn = classDef.beginColumn + 4; name.beginLine = classDef.beginLine + 1; newBody[i] = new Assign(new exprType[] {name}, (exprType) objAndType[1]); newBody[i].beginColumn = classDef.beginColumn + 4; newBody[i].beginLine = classDef.beginLine + 1; i += 1; } classDef.body = newBody; break; } } } return n; }