예제 #1
0
 public EvaluatedTemplate(final TemplateBuffer buffer, final String lineDelimiter) {
   setContent(buffer.getString());
   final TemplateVariable selectStartVariable =
       findVariable(buffer, SourceEditorContextType.SELECT_START_VARIABLE);
   final TemplateVariable selectEndVariable =
       findVariable(buffer, SourceEditorContextType.SELECT_END_VARIABLE);
   if (selectStartVariable != null && selectStartVariable.getOffsets().length == 1) {
     fSelect =
         new Region(
             selectStartVariable.getOffsets()[0],
             (selectEndVariable != null && selectEndVariable.getOffsets().length == 1)
                 ? Math.max(
                     selectEndVariable.getOffsets()[0] - selectStartVariable.getOffsets()[0], 0)
                 : 0);
   }
   fLineDelimiter = lineDelimiter;
 }
예제 #2
0
  private int getCursorOffset(TemplateBuffer buffer) {
    TemplateVariable[] variables = buffer.getVariables();
    for (int i = 0; i != variables.length; i++) {
      TemplateVariable variable = variables[i];
      if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME))
        return variable.getOffsets()[0];
    }

    return buffer.getString().length();
  }
예제 #3
0
 public static void positionsToVariables(
     final List<TextEdit> positions, final TemplateVariable[] variables) {
   final Iterator<TextEdit> iterator = positions.iterator();
   for (final TemplateVariable variable : variables) {
     final int[] offsets = new int[variable.getOffsets().length];
     for (int j = 0; j < offsets.length; j++) {
       offsets[j] = iterator.next().getOffset();
     }
     variable.setOffsets(offsets);
   }
 }
예제 #4
0
  public static List<TextEdit> variablesToPositions(final TemplateVariable[] variables) {
    final List<TextEdit> positions = new ArrayList<>(5);
    for (final TemplateVariable variable : variables) {
      final int[] offsets = variable.getOffsets();

      // trim positions off whitespace
      final String value = variable.getDefaultValue();
      int wsStart = 0;
      while (wsStart < value.length()
          && Character.isWhitespace(value.charAt(wsStart))
          && !isLineDelimiterChar(value.charAt(wsStart))) {
        wsStart++;
      }

      variable.getValues()[0] = value.substring(wsStart);

      for (int j = 0; j != offsets.length; j++) {
        offsets[j] += wsStart;
        positions.add(new RangeMarker(offsets[j], 0));
      }
    }
    return positions;
  }
  /**
   * Evalute JDT template code snippet
   *
   * @param effect
   * @param args
   * @return
   */
  private String evaluationJDTTemplate(Effect effect, TemplateBuffer buffer, Object[] args) {
    // Prepare a hash map of snippet variables for use by formulas.
    HashMap<String, String> variableMap = new HashMap<String, String>();
    variableMap.put("cursor", "/*${cursor}*/");

    for (int i = 0; i < args.length; i++) {
      String value = (String) args[i];
      variableMap.put(effect.getParameter(i).getName(), value);
    }
    StringBuilder sb = new StringBuilder(buffer.getString());
    TemplateVariable[] variables = buffer.getVariables();
    List<TemplateVariableElement> varList = new ArrayList<TemplateVariableElement>();
    for (TemplateVariable var : variables) {
      for (int off : var.getOffsets()) {
        String value = variableMap.get(var.getName());
        if (value != null)
          varList.add(new TemplateVariableElement(off, off + var.getLength(), value));
      }
    }

    for (int i = 0; i < varList.size(); i++)
      for (int j = i + 1; j < varList.size(); j++) {
        TemplateVariableElement itemi = varList.get(i);
        TemplateVariableElement itemj = varList.get(j);
        if (itemj.getStart() > itemi.getStart()) {
          TemplateVariableElement temp = itemi;
          varList.set(i, itemj);
          varList.set(j, temp);
        }
      }

    for (TemplateVariableElement item : varList) {
      sb.replace(item.getStart(), item.getLength(), item.getValue());
    }
    return sb.toString();
  }
  @Override
  public void resolve(final TemplateBuffer buffer, final TemplateContext context)
      throws MalformedTreeException, BadLocationException {
    Assert.isNotNull(context);
    final TemplateVariable[] variables = buffer.getVariables();

    final IDocument document = new Document(buffer.getString());
    final List<TextEdit> positions = TemplatesUtil.variablesToPositions(variables);
    final List<TextEdit> edits = new ArrayList<>(5);

    // iterate over all variables and try to resolve them
    for (int i = 0; i != variables.length; i++) {
      final TemplateVariable variable = variables[i];

      if (variable.isUnambiguous()) {
        continue;
      }

      // remember old values
      final int[] oldOffsets = variable.getOffsets();
      final int oldLength = variable.getLength();
      final String oldValue = variable.getDefaultValue();

      final String type = variable.getType();
      TemplateVariableResolver resolver = getResolver(type);
      if (resolver == null) {
        resolver = new TemplateVariableResolver();
        resolver.setType(type);
      }

      resolver.resolve(variable, context);

      final String value = variable.getDefaultValue();
      final String[] ln = document.getLegalLineDelimiters();
      final boolean multiLine = (TextUtilities.indexOf(ln, value, 0)[0] != -1);

      if (!oldValue.equals(value)) {
        // update buffer to reflect new value
        for (int k = 0; k != oldOffsets.length; k++) {
          String thisValue = value;
          if (multiLine) {
            final String indent = TemplatesUtil.searchIndentation(document, oldOffsets[k]);
            if (indent.length() > 0) {
              final StringBuilder temp = new StringBuilder(thisValue);
              int offset = 0;
              while (true) {
                final int[] search = TextUtilities.indexOf(ln, temp.toString(), offset);
                if (search[0] == -1) {
                  break;
                }
                offset = search[0] + ln[search[1]].length();
                temp.insert(offset, indent);
                offset += indent.length();
              }
              thisValue = temp.toString();
            }
          }
          edits.add(new ReplaceEdit(oldOffsets[k], oldLength, thisValue));
        }
      }
    }

    final MultiTextEdit edit = new MultiTextEdit(0, document.getLength());
    edit.addChildren(positions.toArray(new TextEdit[positions.size()]));
    edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
    edit.apply(document, TextEdit.UPDATE_REGIONS);

    TemplatesUtil.positionsToVariables(positions, variables);

    buffer.setContent(document.get(), variables);
  }
예제 #7
0
  /**
   * Generates content for the Roxygen comment for the given function definition
   *
   * @param rMethod function element
   * @param lineDelimiter the line delimiter to be used
   * @return
   * @throws CoreException thrown when the evaluation of the code template fails
   */
  public static EvaluatedTemplate getCommonFunctionRoxygenComment(
      final IRMethod rMethod, final String lineDelimiter) throws CoreException {
    final Template template =
        RUIPlugin.getDefault()
            .getRCodeGenerationTemplateStore()
            .findTemplate(RCodeTemplatesContextType.ROXYGEN_COMMONFUNCTION_TEMPLATE);
    if (template == null) {
      return null;
    }

    final ISourceUnit su = rMethod.getSourceUnit();
    final RCodeTemplatesContext context =
        new RCodeTemplatesContext(
            RCodeTemplatesContextType.ROXYGEN_COMMONFUNCTION_CONTEXTTYPE, su, lineDelimiter);
    context.setRElement(rMethod);

    try {
      final TemplateBuffer buffer = context.evaluate(template);
      if (buffer == null) {
        return null;
      }
      final EvaluatedTemplate data = new EvaluatedTemplate(buffer, lineDelimiter);

      final AbstractDocument content = data.startPostEdit();
      final StringBuilder tagBuffer = new StringBuilder(64);
      final TemplateVariable paramVariable =
          TemplatesUtil.findVariable(buffer, RCodeTemplatesContextType.ROXYGEN_PARAM_TAGS_VARIABLE);
      final Position[] paramPositions =
          new Position[(paramVariable != null) ? paramVariable.getOffsets().length : 0];
      for (int i = 0; i < paramPositions.length; i++) {
        paramPositions[i] = new Position(paramVariable.getOffsets()[i], paramVariable.getLength());
        content.addPosition(paramPositions[i]);
      }

      if (paramPositions.length > 0) {
        String[] tags = null;
        final ArgsDefinition args = rMethod.getArgsDefinition();
        if (args != null) {
          final int count = args.size();
          tags = new String[count];
          for (int i = 0; i < count; i++) {
            tagBuffer.append("@param "); // $NON-NLS-1$
            tagBuffer.append(args.get(i).name);
            tagBuffer.append(" "); // $NON-NLS-1$
            tags[i] = tagBuffer.toString();
            tagBuffer.setLength(0);
          }
        }
        for (final Position pos : paramPositions) {
          insertRoxygen(content, pos, tags);
        }
      }

      data.finishPostEdit();
      return data;
    } catch (final Exception e) {
      throw new CoreException(
          new Status(
              IStatus.ERROR,
              RUI.PLUGIN_ID,
              NLS.bind(
                  TemplateMessages.TemplateEvaluation_error_description, template.getDescription()),
              e));
    }
  }
예제 #8
0
  /**
   * Generates content for the Roxygen comment for the given method definition
   *
   * @param rMethod function element
   * @param lineDelimiter the line delimiter to be used
   * @return
   * @throws CoreException thrown when the evaluation of the code template fails
   */
  public static EvaluatedTemplate getMethodRoxygenComment(
      final IRMethod rMethod, final String lineDelimiter) throws CoreException {
    final Template template =
        RUIPlugin.getDefault()
            .getRCodeGenerationTemplateStore()
            .findTemplate(RCodeTemplatesContextType.ROXYGEN_S4METHOD_TEMPLATE);
    if (template == null) {
      return null;
    }

    final ISourceUnit su = rMethod.getSourceUnit();
    final RCodeTemplatesContext context =
        new RCodeTemplatesContext(
            RCodeTemplatesContextType.ROXYGEN_METHOD_CONTEXTTYPE, su, lineDelimiter);
    context.setRElement(rMethod);

    try {
      final TemplateBuffer buffer = context.evaluate(template);
      if (buffer == null) {
        return null;
      }
      final EvaluatedTemplate data = new EvaluatedTemplate(buffer, lineDelimiter);

      final AbstractDocument content = data.startPostEdit();
      final StringBuilder sb = new StringBuilder(64);

      final Position[] sigPositions;
      String sigText = null;
      {
        final TemplateVariable variable =
            TemplatesUtil.findVariable(buffer, RCodeTemplatesContextType.ROXYGEN_SIG_LIST_VARIABLE);
        sigPositions = new Position[(variable != null) ? variable.getOffsets().length : 0];
        for (int i = 0; i < sigPositions.length; i++) {
          sigPositions[i] = new Position(variable.getOffsets()[i], variable.getLength());
          content.addPosition(sigPositions[i]);
        }

        if (sigPositions.length > 0) {
          final ArgsDefinition args = rMethod.getArgsDefinition();
          if (args != null) {
            final int count = args.size();
            for (int i = 0; i < count; i++) {
              final Arg arg = args.get(i);
              if (arg.className == null || arg.className.equals("ANY")) { // $NON-NLS-1$
                break;
              }
              sb.append(arg.className);
              sb.append(","); // $NON-NLS-1$
            }
            if (sb.length() > 0) {
              sigText = sb.substring(0, sb.length() - 1);
              sb.setLength(0);
            }
          }
        }
      }
      final Position[] paramPositions;
      String[] paramTags = null;
      {
        final TemplateVariable variable =
            TemplatesUtil.findVariable(
                buffer, RCodeTemplatesContextType.ROXYGEN_PARAM_TAGS_VARIABLE);
        paramPositions = new Position[(variable != null) ? variable.getOffsets().length : 0];
        for (int i = 0; i < paramPositions.length; i++) {
          paramPositions[i] = new Position(variable.getOffsets()[i], variable.getLength());
          content.addPosition(paramPositions[i]);
        }

        if (paramPositions.length > 0) {
          String list = null;
          final ArgsDefinition args = rMethod.getArgsDefinition();
          if (args != null) {
            final int count = args.size();
            paramTags = new String[count];
            for (int i = 0; i < count; i++) {
              sb.append("@param "); // $NON-NLS-1$
              sb.append(args.get(i).name);
              sb.append(" "); // $NON-NLS-1$
              paramTags[i] = sb.toString();
              sb.setLength(0);
            }
          }
        }
      }

      if (sigPositions != null) {
        for (final Position pos : sigPositions) {
          insertRoxygen(content, pos, sigText);
        }
      }
      if (paramPositions != null) {
        for (final Position pos : paramPositions) {
          insertRoxygen(content, pos, paramTags);
        }
      }

      data.finishPostEdit();
      return data;
    } catch (final Exception e) {
      throw new CoreException(
          new Status(
              IStatus.ERROR,
              RUI.PLUGIN_ID,
              NLS.bind(
                  TemplateMessages.TemplateEvaluation_error_description, template.getDescription()),
              e));
    }
  }
예제 #9
0
  /**
   * Generates content for the Roxygen comment for the given class definition
   *
   * @param rClass class element
   * @param lineDelimiter the line delimiter to be used
   * @return
   * @throws CoreException thrown when the evaluation of the code template fails
   */
  public static EvaluatedTemplate getClassRoxygenComment(
      final IRClass rClass, final String lineDelimiter) throws CoreException {
    final Template template =
        RUIPlugin.getDefault()
            .getRCodeGenerationTemplateStore()
            .findTemplate(RCodeTemplatesContextType.ROXYGEN_S4CLASS_TEMPLATE);
    if (template == null) {
      return null;
    }

    final ISourceUnit su = rClass.getSourceUnit();
    final RCodeTemplatesContext context =
        new RCodeTemplatesContext(
            RCodeTemplatesContextType.ROXYGEN_CLASS_CONTEXTTYPE, su, lineDelimiter);
    context.setRElement(rClass);

    try {
      final TemplateBuffer buffer = context.evaluate(template);
      if (buffer == null) {
        return null;
      }
      final EvaluatedTemplate data = new EvaluatedTemplate(buffer, lineDelimiter);

      final AbstractDocument content = data.startPostEdit();
      final StringBuilder tagBuffer = new StringBuilder(64);
      final TemplateVariable slotVariable =
          TemplatesUtil.findVariable(buffer, RCodeTemplatesContextType.ROXYGEN_SLOT_TAGS_VARIABLE);
      final Position[] slotPositions =
          new Position[(slotVariable != null) ? slotVariable.getOffsets().length : 0];
      for (int i = 0; i < slotPositions.length; i++) {
        slotPositions[i] = new Position(slotVariable.getOffsets()[i], slotVariable.getLength());
        content.addPosition(slotPositions[i]);
      }

      if (slotPositions.length > 0) {
        String[] tags = null;
        final List<? extends IModelElement> slots =
            rClass.getModelChildren(IRElement.R_S4SLOT_FILTER);
        final int count = slots.size();
        tags = new String[count];
        for (int i = 0; i < count; i++) {
          final IRSlot slot = (IRSlot) slots.get(i);
          tagBuffer.append("@slot "); // $NON-NLS-1$
          tagBuffer.append(slot.getElementName().getDisplayName());
          tagBuffer.append(" "); // $NON-NLS-1$
          tags[i] = tagBuffer.toString();
          tagBuffer.setLength(0);
        }
        for (final Position pos : slotPositions) {
          insertRoxygen(content, pos, tags);
        }
      }

      data.finishPostEdit();
      return data;
    } catch (final Exception e) {
      throw new CoreException(
          new Status(
              IStatus.ERROR,
              RUI.PLUGIN_ID,
              NLS.bind(
                  TemplateMessages.TemplateEvaluation_error_description, template.getDescription()),
              e));
    }
  }
예제 #10
0
  /*
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
   */
  @Override
  public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {

    IDocument document = viewer.getDocument();
    try {
      fContext.setReadOnly(false);
      int start;
      TemplateBuffer templateBuffer;
      try {
        beginCompoundChange(viewer);

        int oldReplaceOffset = getReplaceOffset();
        try {
          // this may already modify the document (e.g. add imports)
          templateBuffer = fContext.evaluate(fTemplate);
        } catch (TemplateException e1) {
          fSelectedRegion = fRegion;
          return;
        }

        start = getReplaceOffset();
        int shift = start - oldReplaceOffset;
        int end = Math.max(getReplaceEndOffset(), offset + shift);

        // insert template string
        if (end > document.getLength()) end = offset;
        String templateString = templateBuffer.getString();
        document.replace(start, end - start, templateString);
      } finally {
        endCompoundChange(viewer);
      }

      // translate positions
      LinkedModeModel model = new LinkedModeModel();
      TemplateVariable[] variables = templateBuffer.getVariables();

      MultiVariableGuess guess =
          fContext instanceof CompilationUnitContext
              ? ((CompilationUnitContext) fContext).getMultiVariableGuess()
              : null;

      boolean hasPositions = false;
      for (int i = 0; i != variables.length; i++) {
        TemplateVariable variable = variables[i];

        if (variable.isUnambiguous()) continue;

        LinkedPositionGroup group = new LinkedPositionGroup();

        int[] offsets = variable.getOffsets();
        int length = variable.getLength();

        LinkedPosition first;
        if (guess != null && variable instanceof MultiVariable) {
          first =
              new VariablePosition(
                  document, offsets[0] + start, length, guess, (MultiVariable) variable);
          guess.addSlave((VariablePosition) first);
        } else {
          String[] values = variable.getValues();
          ICompletionProposal[] proposals = new ICompletionProposal[values.length];
          for (int j = 0; j < values.length; j++) {
            ensurePositionCategoryInstalled(document, model);
            Position pos = new Position(offsets[0] + start, length);
            document.addPosition(getCategory(), pos);
            proposals[j] = new PositionBasedCompletionProposal(values[j], pos, length);
          }

          if (proposals.length > 1)
            first = new ProposalPosition(document, offsets[0] + start, length, proposals);
          else first = new LinkedPosition(document, offsets[0] + start, length);
        }

        for (int j = 0; j != offsets.length; j++)
          if (j == 0) group.addPosition(first);
          else group.addPosition(new LinkedPosition(document, offsets[j] + start, length));

        model.addGroup(group);
        hasPositions = true;
      }

      if (hasPositions) {
        model.forceInstall();
        JavaEditor editor = getJavaEditor();
        if (editor != null) {
          model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
        }

        LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
        ui.setExitPosition(viewer, getCaretOffset(templateBuffer) + start, 0, Integer.MAX_VALUE);
        ui.enter();

        fSelectedRegion = ui.getSelectedRegion();
      } else {
        fSelectedRegion = new Region(getCaretOffset(templateBuffer) + start, 0);
      }

    } catch (BadLocationException e) {
      JavaPlugin.log(e);
      openErrorDialog(viewer.getTextWidget().getShell(), e);
      fSelectedRegion = fRegion;
    } catch (BadPositionCategoryException e) {
      JavaPlugin.log(e);
      openErrorDialog(viewer.getTextWidget().getShell(), e);
      fSelectedRegion = fRegion;
    }
  }