public OffsetRange getReferenceSpan(Document doc, int lexOffset) { TokenHierarchy<Document> th = TokenHierarchy.get(doc); // BaseDocument doc = (BaseDocument)document; TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(th, lexOffset); if (ts == null) { return OffsetRange.NONE; } ts.move(lexOffset); if (!ts.moveNext() && !ts.movePrevious()) { return OffsetRange.NONE; } // Determine whether the caret position is right between two tokens boolean isBetween = (lexOffset == ts.offset()); OffsetRange range = getReferenceSpan(ts, th, lexOffset); if ((range == OffsetRange.NONE) && isBetween) { // The caret is between two tokens, and the token on the right // wasn't linkable. Try on the left instead. if (ts.movePrevious()) { range = getReferenceSpan(ts, th, lexOffset); } } return range; }
@SuppressWarnings("empty-statement") private DeclarationLocation findUrl(PythonParserResult info, Document doc, int lexOffset) { TokenSequence<?> ts = PythonLexerUtils.getPythonSequence((BaseDocument) doc, lexOffset); if (ts == null) { return DeclarationLocation.NONE; } ts.move(lexOffset); if (!ts.moveNext() && !ts.movePrevious()) { return DeclarationLocation.NONE; } Token<?> token = ts.token(); TokenSequence<?> embedded = ts.embedded(); if (embedded != null) { ts = embedded; embedded.move(lexOffset); if (!embedded.moveNext() && !embedded.movePrevious()) { return DeclarationLocation.NONE; } token = embedded.token(); } // Is this a comment? If so, possibly do rdoc-method reference jump if ((token != null) && (token.id() == PythonStringTokenId.URL)) { // TODO - use findLinkedMethod String method = token.text().toString(); if (method.startsWith("www.")) { // NOI18N method = "http://" + method; // NOI18N } // A URL such as http://netbeans.org - try to open it in a browser! try { URL url = new URL(method); return new DeclarationLocation(url); } catch (MalformedURLException mue) { // URL is from user source... don't complain with exception dialogs etc. ; } } return DeclarationLocation.NONE; }
private DeclarationLocation findImport(PythonParserResult info, int lexOffset, BaseDocument doc) { TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPositionedSequence(doc, lexOffset); if (ts == null) { return DeclarationLocation.NONE; } if (ts.offset() == lexOffset) { // We're looking at the offset to the RIGHT of the caret // and here I care about what's on the left if (!ts.movePrevious()) { return DeclarationLocation.NONE; } } Token<? extends PythonTokenId> token = ts.token(); if (token == null) { return DeclarationLocation.NONE; } TokenId id = token.id(); String moduleName = null; while (true) { if (id == PythonTokenId.IDENTIFIER || id.primaryCategory().equals(PythonLexer.KEYWORD_CAT)) { // Possibly inside the import string String tokenText = token.text().toString(); if (moduleName == null) { moduleName = tokenText; } else { moduleName = tokenText + "." + moduleName; } } else if (id != PythonTokenId.DOT) { break; } if (!ts.movePrevious()) { return DeclarationLocation.NONE; } token = ts.token(); id = token.id(); } if (id != PythonTokenId.ERROR && id != PythonTokenId.NEWLINE && id != PythonTokenId.WHITESPACE) { return DeclarationLocation.NONE; } if (!ts.movePrevious()) { return DeclarationLocation.NONE; } token = ts.token(); id = token.id(); if (id != PythonTokenId.IMPORT) { return DeclarationLocation.NONE; } if (moduleName == null) { return DeclarationLocation.NONE; } if (id == PythonTokenId.IMPORT || id == PythonTokenId.FROM) { if (id == PythonTokenId.IMPORT && ts.movePrevious() && ts.token().id() == PythonTokenId.WHITESPACE && ts.movePrevious()) { // See if this was "from foo import bar" such that we really should // be listing symbols inside the foo library token = ts.token(); id = token.id(); String library = null; while (true) { if (id == PythonTokenId.IDENTIFIER || id.primaryCategory().equals(PythonLexer.KEYWORD_CAT)) { // Possibly inside the import string String tokenText = token.text().toString(); if (library == null) { library = tokenText; } else { library = tokenText + "." + library; } } else if (id != PythonTokenId.DOT) { break; } if (!ts.movePrevious()) { return DeclarationLocation.NONE; } token = ts.token(); id = token.id(); } if (library != null) { if (id == PythonTokenId.WHITESPACE && ts.movePrevious() && ts.token().id() == PythonTokenId.FROM) { return findImport(info, library, moduleName); } } } return findImport(info, moduleName, null); } return DeclarationLocation.NONE; }
public void run(RubyRuleContext context, List<Hint> result) { Node node = context.node; ParserResult info = context.parserResult; IfNode ifNode = (IfNode) node; if (ifNode.getCondition() == null) { // Can happen for this code: // if () // end // (typically while editing) return; } Node body = ifNode.getThenBody(); Node elseNode = ifNode.getElseBody(); if (body != null && elseNode != null) { // Can't convert if-then-else conditionals return; } if (body == null && elseNode == null) { // Can't convert empty conditions return; } // Can't convert if !x/elseif blocks if (ifNode.getElseBody() != null && ifNode.getElseBody().getNodeType() == NodeType.IFNODE) { return; } int start = ifNode.getPosition().getStartOffset(); if (!RubyHints.isNullOrInvisible(body) && ( // Can't convert blocks with multiple statements body.getNodeType() == NodeType.BLOCKNODE || // Already a statement modifier? body.getPosition().getStartOffset() <= start)) { return; } else if (!RubyHints.isNullOrInvisible(elseNode) && (elseNode.getNodeType() == NodeType.BLOCKNODE || elseNode.getPosition().getStartOffset() <= start)) { return; } BaseDocument doc = context.doc; try { int keywordOffset = ConvertIfToUnless.findKeywordOffset(context, ifNode); if (keywordOffset == -1 || keywordOffset > doc.getLength() - 1) { return; } char k = doc.getText(keywordOffset, 1).charAt(0); if (!(k == 'i' || k == 'u')) { return; // Probably ternary operator, ?: } } catch (BadLocationException ble) { Exceptions.printStackTrace(ble); } // If statement that is not already a statement modifier OffsetRange range = AstUtilities.getRange(node); if (RubyUtils.isRhtmlDocument(doc) || RubyUtils.isYamlDocument(doc)) { // Make sure that we're in a single contiguous Ruby section; if not, this won't work range = LexUtilities.getLexerOffsets(info, range); if (range == OffsetRange.NONE) { return; } try { doc.readLock(); TokenHierarchy th = TokenHierarchy.get(doc); TokenSequence ts = th.tokenSequence(); ts.move(range.getStart()); if (!ts.moveNext() && !ts.movePrevious()) { return; } if (ts.offset() + ts.token().length() < range.getEnd()) { return; } } finally { doc.readUnlock(); } } ConvertToModifier fix = new ConvertToModifier(context, ifNode); if (fix.getEditList() == null) { return; } List<HintFix> fixes = Collections.<HintFix>singletonList(fix); String displayName = NbBundle.getMessage(ConvertConditionals.class, "ConvertConditionals"); Hint desc = new Hint(this, displayName, RubyUtils.getFileObject(info), range, fixes, 500); result.add(desc); }