@Override
 public long getEndPosition() {
   if (doc != null) {
     OffsetRange range = ASTUtils.getRangeFull(node.getNode(), doc);
     LOG.log(Level.FINEST, "getEndPosition(), end: {0}", range.getEnd());
     return (long) range.getEnd();
   }
   return 0;
 }
 public void testValidUseCase_01() throws Exception {
   AnnotationParsedLine parsedLine = parser.parse("Secure");
   assertEquals("Secure", parsedLine.getName());
   assertEquals("", parsedLine.getDescription());
   Map<OffsetRange, String> types = parsedLine.getTypes();
   for (Map.Entry<OffsetRange, String> entry : types.entrySet()) {
     OffsetRange offsetRange = entry.getKey();
     String value = entry.getValue();
     assertEquals(0, offsetRange.getStart());
     assertEquals(6, offsetRange.getEnd());
     assertEquals("Secure", value);
   }
 }
  private void addFolds(
      BaseDocument doc,
      List<? extends ASTElement> elements,
      Map<String, List<OffsetRange>> folds,
      List<OffsetRange> codeblocks)
      throws BadLocationException {
    for (ASTElement element : elements) {
      ElementKind kind = element.getKind();
      switch (kind) {
        case FIELD:
        case METHOD:
        case CONSTRUCTOR:
        case CLASS:
        case MODULE:
          ASTNode node = element.getNode();
          OffsetRange range = ASTUtils.getRangeFull(node, doc);

          // beware of synthetic elements
          if ((kind == ElementKind.METHOD && !((MethodNode) node).isSynthetic())
              || (kind == ElementKind.CONSTRUCTOR && !((ConstructorNode) node).isSynthetic())
              || (kind == ElementKind.FIELD
                  && ((FieldNode) node).getInitialExpression() instanceof ClosureExpression)
              // Only make nested classes/modules foldable, similar to what the java editor is doing
              || (range.getStart() > Utilities.getRowStart(doc, range.getStart()))
                  && kind != ElementKind.FIELD) {

            int start = range.getStart();
            // Start the fold at the END of the line behind last non-whitespace, remove curly brace,
            // if any
            start = Utilities.getRowLastNonWhite(doc, start);
            if (start >= 0 && doc.getChars(start, 1)[0] != '{') {
              start++;
            }
            int end = range.getEnd();
            if (start != (-1) && end != (-1) && start < end && end <= doc.getLength()) {
              range = new OffsetRange(start, end);
              codeblocks.add(range);
            }
          }
          break;
      }

      List<? extends ASTElement> children = element.getChildren();

      if (children != null && children.size() > 0) {
        addFolds(doc, children, folds, codeblocks);
      }
    }
  }
 public void testValidUseCase_05() throws Exception {
   AnnotationParsedLine parsedLine =
       parser.parse("Annotations\\Secure(roles=\"ROLE_USER, ROLE_FOO, ROLE_ADMIN\")  \t");
   assertEquals("Secure", parsedLine.getName());
   assertEquals("(roles=\"ROLE_USER, ROLE_FOO, ROLE_ADMIN\")", parsedLine.getDescription());
   Map<OffsetRange, String> types = parsedLine.getTypes();
   assertNotNull(types);
   for (Map.Entry<OffsetRange, String> entry : types.entrySet()) {
     OffsetRange offsetRange = entry.getKey();
     String value = entry.getValue();
     assertEquals(0, offsetRange.getStart());
     assertEquals(18, offsetRange.getEnd());
     assertEquals("Annotations\\Secure", value);
   }
 }
    public EditList getEditList() {
      try {
        BaseDocument doc = context.doc;

        Node bodyNode = ifNode.getThenBody();
        boolean isIf = bodyNode != null;
        if (bodyNode == null) {
          bodyNode = ifNode.getElseBody();
        }
        ParserResult info = context.parserResult;
        OffsetRange bodyRange = AstUtilities.getRange(bodyNode);
        bodyRange = LexUtilities.getLexerOffsets(info, bodyRange);
        if (bodyRange == OffsetRange.NONE) {
          return null;
        }

        String body = doc.getText(bodyRange.getStart(), bodyRange.getLength()).trim();
        if (body.endsWith(";")) {
          body = body.substring(0, body.length() - 1);
        }
        StringBuilder sb = new StringBuilder();
        sb.append(body);
        sb.append(" ");
        sb.append(isIf ? "if" : "unless"); // NOI18N
        sb.append(" ");
        OffsetRange range = AstUtilities.getRange(ifNode.getCondition());
        range = LexUtilities.getLexerOffsets(info, range);
        if (range == OffsetRange.NONE) {
          return null;
        }
        sb.append(doc.getText(range.getStart(), range.getLength()));

        OffsetRange ifRange = AstUtilities.getRange(ifNode);
        ifRange = LexUtilities.getLexerOffsets(info, ifRange);
        if (ifRange == OffsetRange.NONE) {
          return null;
        }

        return new EditList(doc)
            .replace(ifRange.getStart(), ifRange.getLength(), sb.toString(), false, 0);
      } catch (Exception ex) {
        Exceptions.printStackTrace(ex);
        return null;
      }
    }
  @Override
  public DeclarationLocation findDeclaration(ParserResult info, int lexOffset) {

    final Document document = info.getSnapshot().getSource().getDocument(false);
    if (document == null) {
      return DeclarationLocation.NONE;
    }

    final BaseDocument doc = (BaseDocument) document;

    PythonParserResult parseResult = PythonAstUtils.getParseResult(info);
    doc.readLock(); // Read-lock due to Token hierarchy use
    try {
      PythonTree root = PythonAstUtils.getRoot(parseResult);
      final int astOffset = PythonAstUtils.getAstOffset(info, lexOffset);
      if (astOffset == -1) {
        return DeclarationLocation.NONE;
      }

      AstPath path = null;
      PythonTree node = null;
      if (root != null) {
        path = AstPath.get(root, astOffset);
        node = path.leaf();
      }

      // See if it's an import
      DeclarationLocation imp = findImport(parseResult, lexOffset, doc);
      if (imp != DeclarationLocation.NONE) {
        return imp;
      }

      DeclarationLocation url = findUrl(parseResult, doc, lexOffset);
      if (url != DeclarationLocation.NONE) {
        return url;
      }

      final TokenHierarchy<Document> th = TokenHierarchy.get(document);
      org.netbeans.modules.python.editor.lexer.Call call =
          org.netbeans.modules.python.editor.lexer.Call.getCallType(doc, th, lexOffset);

      FileObject fileObject = info.getSnapshot().getSource().getFileObject();

      // Search for local variables
      if (root != null && call.getLhs() == null) {
        if ((path.leaf() instanceof Name)) {
          PythonTree scope = PythonAstUtils.getLocalScope(path);
          SymbolTable symbolTable = parseResult.getSymbolTable();

          String name = ((Name) path.leaf()).getInternalId();

          SymInfo sym = symbolTable.findDeclaration(scope, name, true);
          if (sym != null) {
            if (sym.isFree()) {
              PythonIndex index = PythonIndex.get(fileObject);

              List<Import> imports = symbolTable.getImports();
              List<ImportFrom> importsFrom = symbolTable.getImportsFrom();
              Set<IndexedElement> elements =
                  index.getImportedElements(
                      name, QuerySupport.Kind.EXACT, parseResult, imports, importsFrom);
              if (elements != null && elements.size() > 0) {
                return getDeclaration(
                    parseResult, null /*name*/, elements, path, node, index, astOffset, lexOffset);
              }
              // Must be defined by one of the imported symbols
            }
            if (sym.node != null) {
              PythonTree declNode = sym.node;
              if (sym
                  .isImported()) { // Rather than showing the import symbol go to the definition in
                                   // the library!
                // Determine if it's an "as" name (import foo as bar) and if so just show the "as",
                // if not,
                // follow through to the library
                if (declNode instanceof Import) {
                  Import impNode = (Import) declNode;
                  List<alias> names = impNode.getInternalNames();
                  if (names != null) {
                    for (alias at : names) {
                      if (at.getInternalAsname() != null && name.equals(at.getInternalAsname())) {
                        break;
                      } else if (at.getInternalName().equals(name)) {
                        // We found our library - just show it
                        return findImport(parseResult, name, null);
                      }
                    }
                  }
                } else {
                  assert declNode instanceof ImportFrom : declNode;
                  ImportFrom impNode = (ImportFrom) declNode;
                  List<alias> names = impNode.getInternalNames();
                  if (names != null) {
                    for (alias at : names) {
                      if (at.getInternalAsname() != null && name.equals(at.getInternalAsname())) {
                        break;
                      } else if (at.getInternalName().equals(name)) {
                        // We found our library - just show it
                        return findImport(parseResult, impNode.getInternalModule(), name);
                      }
                    }
                  }
                }
              }

              if (sym.isUnresolved()) {
                PythonIndex index = PythonIndex.get(fileObject);

                List<Import> imports = symbolTable.getImports();
                List<ImportFrom> importsFrom = symbolTable.getImportsFrom();
                Set<IndexedElement> elements =
                    index.getImportedElements(
                        name, QuerySupport.Kind.EXACT, parseResult, imports, importsFrom);
                if (elements != null && elements.size() > 0) {
                  return getDeclaration(
                      parseResult,
                      null /*name*/,
                      elements,
                      path,
                      node,
                      index,
                      astOffset,
                      lexOffset);
                }
              } else {
                OffsetRange astRange = PythonAstUtils.getNameRange(null, declNode);
                int lexerOffset = PythonLexerUtils.getLexerOffset(parseResult, astRange.getStart());
                if (lexerOffset == -1) {
                  lexerOffset = 0;
                }
                return new DeclarationLocation(fileObject, lexerOffset);
              }
            }
          }
          //
          //                    List<Name> localVars = PythonAstUtils.getLocalVarNodes(info, scope,
          // name);
          //                    if (localVars.size() > 0) {
          //                        return new DeclarationLocation(info.getFileObject(),
          // PythonAstUtils.getRange(localVars.get(0)).getStart());
          //                    }
        }
      }

      // I'm not doing any data flow analysis at this point, so
      // I can't do anything with a LHS like "foo.". Only actual types.
      String type = call.getType();
      if (type != null && "self".equals(type)) { // NOI18N
        type = PythonAstUtils.getFqnName(path);
      }
      if (type != null && type.length() > 0) {
        String name = null;
        PythonTree leaf = path.leaf();
        if (leaf instanceof Name) {
          name = ((Name) path.leaf()).getInternalId();
        } else if (leaf instanceof Attribute) {
          name = ((Attribute) leaf).getInternalAttr();
        }

        if (name != null) {
          PythonIndex index = PythonIndex.get(fileObject);
          // Add methods in the class (without an FQN)
          Set<IndexedElement> elements =
              index.getInheritedElements(type, name, QuerySupport.Kind.EXACT);
          if (elements != null && elements.size() > 0) {
            return getDeclaration(
                parseResult, null /*name*/, elements, path, node, index, astOffset, lexOffset);
          }
        }
      }

      // Fallback: Index search on all names
      String prefix = new PythonCodeCompleter().getPrefix(info, lexOffset, false);
      if (prefix == null) {
        try {
          prefix = Utilities.getIdentifier(doc, lexOffset);
        } catch (BadLocationException ex) {
          Exceptions.printStackTrace(ex);
        }
      }
      if (prefix != null) {
        PythonIndex index = PythonIndex.get(fileObject);

        Set<? extends IndexedElement> elements = null;
        if (prefix.length() > 0 && Character.isUpperCase(prefix.charAt(0))) {
          elements = index.getClasses(prefix, QuerySupport.Kind.EXACT, parseResult, true);
        }

        if (elements == null || elements.size() == 0) {
          elements = index.getAllElements(prefix, QuerySupport.Kind.EXACT, parseResult, true);
        }

        if (elements == null || elements.size() == 0) {
          elements = index.getAllMembers(prefix, QuerySupport.Kind.EXACT, parseResult, true);
        }

        if (elements != null && elements.size() > 0) {
          return getDeclaration(
              parseResult, null /*name*/, elements, path, node, index, astOffset, lexOffset);
        }

        // TODO - classes
        // WORKING HERE
        //                if (elements == null || elements.size() == 0) {
        //                    elements = index.getClasses(prefix, QuerySupport.Kind.EXACT,
        // PythonIndex.ALL_SCOPE, parseResult, true);
        //                }
        //                if (elements != null && elements.size() > 0) {
        //                    String name = null; // unused!
        //
        //                    return getMethodDeclaration(info, name, elements,
        //                         path, null, index, astOffset, lexOffset);
        //                }
      }
    } finally {
      doc.readUnlock();
    }
    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);
  }
Example #8
0
  public void run(JsRuleContext context, List<Hint> result) {
    JsParseResult info = AstUtilities.getParseResult(context.parserResult);
    Node node = context.node;

    AstElement element = (AstElement) node.element;
    if (element == null) {
      JsParseResult jps = AstUtilities.getParseResult(info);
      if (jps != null) {
        jps.getStructure();
        element = (AstElement) node.element;
        if (element == null) {
          return;
        }
      }
    }

    if (element.getKind() != ElementKind.METHOD && element.getKind() != ElementKind.CONSTRUCTOR) {
      return;
    }

    if (!(element instanceof FunctionAstElement)) {
      assert false : element;
      return;
    }

    FunctionAstElement func = (FunctionAstElement) element;

    Map<String, String> docProps = element.getDocProps();
    if (docProps == null || docProps.size() == 0) {
      return;
    }

    // Make sure we actually have some parameters in the doc props
    boolean found = false;
    for (String key : docProps.keySet()) {
      if (!key.startsWith("@")) {
        found = true;
        break;
      }
    }

    // Don't complain about functions that don't have any parameters
    if (!found) {
      return;
    }

    // Make sure every parameter is documented
    List<String> params = func.getParameters();
    List<String> missing = null;
    List<String> extra = null;
    for (String param : params) {
      if (!docProps.containsKey(param)) {
        if (missing == null) {
          missing = new ArrayList<String>();
        }
        missing.add(param);
      }
    }

    // TODO - make sure doc props exist even for items without types!!
    for (String key : docProps.keySet()) {
      if (key.startsWith("@")) {
        continue;
      }
      if (!params.contains(key)) {
        if (extra == null) {
          extra = new ArrayList<String>();
        }
        extra.add(key);
      }
    }

    if (missing != null || extra != null) {
      String label;
      if (missing != null && extra != null) {
        label = NbBundle.getMessage(WrongJsDoc.class, "WrongParamsBoth", missing, extra);
      } else if (missing != null) {
        label = NbBundle.getMessage(WrongJsDoc.class, "WrongParamsMissing", missing);
      } else {
        assert extra != null;
        label = NbBundle.getMessage(WrongJsDoc.class, "WrongParamsExtra", extra);
      }

      OffsetRange astRange = AstUtilities.getNameRange(node);
      OffsetRange lexRange = LexUtilities.getLexerOffsets(info, astRange);
      if (lexRange == OffsetRange.NONE) {
        return;
      }
      if (lexRange.getEnd() < context.doc.getLength()) {
        try {
          int startRowEnd = Utilities.getRowEnd(context.doc, lexRange.getStart());
          if (startRowEnd < lexRange.getEnd() && startRowEnd > lexRange.getStart()) {
            lexRange = new OffsetRange(lexRange.getStart(), startRowEnd);
          }
        } catch (BadLocationException ex) {
          Exceptions.printStackTrace(ex);
        }
      }

      List<HintFix> fixList =
          Collections.<HintFix>singletonList(new MoreInfoFix("wrongjsdoc")); // NOI18N
      Hint desc =
          new Hint(
              this, label, info.getSnapshot().getSource().getFileObject(), lexRange, fixList, 1450);
      result.add(desc);
    }
  }