Java Code Examples for org.eclipse.xtext.nodemodel.util.NodeModelUtils#findActualNodeFor()

The following examples show how to use org.eclipse.xtext.nodemodel.util.NodeModelUtils#findActualNodeFor() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AbstractCompletePrefixProviderTest.java    From xtext-core with Eclipse Public License 2.0 6 votes vote down vote up
private void assertLastCompleteNode(final String model, final String expectation) {
  try {
    int offset = model.indexOf("<|>");
    if ((offset == (-1))) {
      offset = model.length();
    }
    int completionOffset = model.indexOf("<|>", offset);
    if ((completionOffset == (-1))) {
      completionOffset = offset;
    }
    final Tree tree = this.parseHelper.parse(model.replace("<|>", ""));
    final ICompositeNode nodeModel = NodeModelUtils.findActualNodeFor(tree);
    final INode completeNode = this.getTestee().getLastCompleteNodeByOffset(nodeModel, offset, completionOffset);
    this.assertNodeModel(expectation, completeNode);
  } catch (Throwable _e) {
    throw Exceptions.sneakyThrow(_e);
  }
}
 
Example 2
Source File: SARLQuickfixProvider.java    From sarl with Apache License 2.0 6 votes vote down vote up
private void addAbstractKeyword(XtendTypeDeclaration typeDeclaration, IXtextDocument document,
		String declarationKeyword) throws BadLocationException {
	final ICompositeNode clazzNode = NodeModelUtils.findActualNodeFor(typeDeclaration);
	if (clazzNode == null) {
		throw new IllegalStateException("Cannot determine node for the type declaration" //$NON-NLS-1$
				+ typeDeclaration.getName());
	}
	int offset = -1;
	final Iterator<ILeafNode> nodes = clazzNode.getLeafNodes().iterator();
	while (offset == -1 && nodes.hasNext()) {
		final ILeafNode leafNode  = nodes.next();
		if (leafNode.getText().equals(declarationKeyword)) {
			offset = leafNode.getOffset();
		}
	}
	final ReplacingAppendable appendable = this.appendableFactory.create(document,
			(XtextResource) typeDeclaration.eResource(),
			offset, 0);
	appendable.append(getGrammarAccess()
			.getAbstractKeyword())
			.append(" "); //$NON-NLS-1$
	appendable.commitChanges();
}
 
Example 3
Source File: XbaseLocationInFileProvider.java    From xtext-extras with Eclipse Public License 2.0 6 votes vote down vote up
@Override
public ITextRegion getSignificantTextRegion(EObject element) {
	if (element instanceof XAbstractFeatureCall) {
		XAbstractFeatureCall typeLiteral = typeLiteralHelper.getRootTypeLiteral((XAbstractFeatureCall) element);
		if (typeLiteral != null) {
			if (typeLiteral instanceof XMemberFeatureCall) {
				XAbstractFeatureCall target = (XAbstractFeatureCall) ((XMemberFeatureCall) typeLiteral).getMemberCallTarget();
				if (target.isTypeLiteral()) {
					return super.getSignificantTextRegion(typeLiteral);
				}
			}
			INode node = NodeModelUtils.findActualNodeFor(typeLiteral);
			if (node != null) {
				return toZeroBasedRegion(node.getTextRegionWithLineInformation());
			}
		}
	}
	return super.getSignificantTextRegion(element);
}
 
Example 4
Source File: InsertionOffsets.java    From xtext-xtend with Eclipse Public License 2.0 6 votes vote down vote up
protected int inEmpty(final XtendTypeDeclaration ownerType) {
  int _xblockexpression = (int) 0;
  {
    final ICompositeNode classNode = NodeModelUtils.findActualNodeFor(ownerType);
    final Function1<ILeafNode, Boolean> _function = (ILeafNode it) -> {
      String _text = it.getText();
      return Boolean.valueOf(Objects.equal(_text, "{"));
    };
    final ILeafNode openingBraceNode = IterableExtensions.<ILeafNode>findFirst(classNode.getLeafNodes(), _function);
    int _xifexpression = (int) 0;
    if ((openingBraceNode != null)) {
      int _offset = openingBraceNode.getOffset();
      _xifexpression = (_offset + 1);
    } else {
      _xifexpression = classNode.getEndOffset();
    }
    _xblockexpression = _xifexpression;
  }
  return _xblockexpression;
}
 
Example 5
Source File: XbaseQuickfixProvider.java    From xtext-eclipse with Eclipse Public License 2.0 6 votes vote down vote up
protected int[] getOffsetAndLength(XIfExpression ifExpression, ICompositeNode node) {
	int offset = node.getOffset();
	int length = node.getLength();
	if (ifExpression.getElse() != null) {
		ICompositeNode elseNode = NodeModelUtils.findActualNodeFor(ifExpression.getElse());
		if (elseNode != null) {
			length = elseNode.getOffset() - offset;
		}
	} else {
		XIfExpression parentIfExpression = EcoreUtil2.getContainerOfType(ifExpression.eContainer(),
				XIfExpression.class);
		if (parentIfExpression != null && parentIfExpression.getElse() == ifExpression) {
			ICompositeNode thenNode = NodeModelUtils.findActualNodeFor(parentIfExpression.getThen());
			if (thenNode != null) {
				int endOffset = thenNode.getEndOffset();
				length = length + (offset - endOffset);
				offset = endOffset;
			}
		}
	}
	return new int[] { offset, length };
}
 
Example 6
Source File: SemanticHighlightingCalculator.java    From xtext-eclipse with Eclipse Public License 2.0 5 votes vote down vote up
public INode getFirstFeatureNode(EObject semantic, EStructuralFeature feature) {
	if (feature == null)
		return NodeModelUtils.findActualNodeFor(semantic);
	List<INode> nodes = NodeModelUtils.findNodesForFeature(semantic, feature);
	if (!nodes.isEmpty())
		return nodes.get(0);
	return null;
}
 
Example 7
Source File: PackageJsonChangeProvider.java    From n4js with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Returns change instance to set the ProjectType to the given value.
 *
 * @param pckJsonResource
 *            The package.json resource
 * @param projectType
 *            The project type to set
 * @param projectDescription
 *            The project description object of the package.json
 */
public static IAtomicChange setProjectType(Resource pckJsonResource, ProjectType projectType,
		ProjectDescription projectDescription) {

	URI uri = pckJsonResource.getURI();
	String newProjectTypeInQuotations = "\"" + projectType.getName().toLowerCase() + "\"";

	List<JSONStringLiteral> pairs = PackageJsonUtils.findNameValuePairs(pckJsonResource,
			PackageJsonProperties.PROJECT_TYPE, JSONStringLiteral.class);

	INode prjTypeNode = null;
	if (!pairs.isEmpty()) {
		JSONStringLiteral jsonStringLiteral = pairs.get(0);
		prjTypeNode = NodeModelUtils.findActualNodeFor(jsonStringLiteral);
	}

	if (prjTypeNode == null) {
		// Append a new entry
		List<JSONObject> n4jss = PackageJsonUtils.findNameValuePairs(pckJsonResource, PackageJsonProperties.N4JS,
				JSONObject.class);

		if (!n4jss.isEmpty()) {
			prjTypeNode = NodeModelUtils.findActualNodeFor(n4jss.get(0));
			int location = (prjTypeNode == null) ? 0 : prjTypeNode.getEndOffset();

			String name = PackageJsonProperties.PROJECT_TYPE.name;
			String nameValuePair = "\n" + name + ": " + newProjectTypeInQuotations + ((location == 0) ? "\n" : "");
			return new Replacement(uri, location, 0, nameValuePair);
		}
	} else {
		// Replace existing entry
		return new Replacement(uri, prjTypeNode.getOffset(), prjTypeNode.getLength(), newProjectTypeInQuotations);
	}

	return new Replacement(uri, 0, 0, "");
}
 
Example 8
Source File: ReorderingHiddenTokenSequencer.java    From dsl-devkit with Eclipse Public License 1.0 5 votes vote down vote up
@Override
public void init(final ISerializationContext context, final EObject semanticObject, final ISequenceAcceptor sequenceAcceptor, final Acceptor errorAcceptor) {
  this.delegate = sequenceAcceptor;
  this.lastNode = NodeModelUtils.findActualNodeFor(semanticObject);
  this.rootNode = lastNode;
  if (rootNode != null) {
    this.rootOffset = rootNode.getTotalOffset();
    this.rootEndOffset = rootNode.getTotalEndOffset();
  }
}
 
Example 9
Source File: ArithmeticsCodeMiningProvider.java    From xtext-eclipse with Eclipse Public License 2.0 5 votes vote down vote up
@Override
protected void createCodeMinings(IDocument document, XtextResource resource, CancelIndicator indicator,
	IAcceptor<? super ICodeMining> acceptor) throws BadLocationException {

	EList<EObject> contents = resource.getContents();
	if (contents.isEmpty()) {
		return;
	}

	// get all evaluations contained by the open document
	List<Evaluation> allEvaluations = EcoreUtil2.eAllOfType(contents.get(0), Evaluation.class);

	// get keyword for ';'
	Keyword semicolon = grammar.getEvaluationAccess().getSemicolonKeyword_1();

	for (Evaluation evaluation : allEvaluations) {
		ICompositeNode node = NodeModelUtils.findActualNodeFor(evaluation);
		for (Iterator<INode> it = node.getAsTreeIterable().iterator(); it.hasNext();) {
			INode child = it.next();
			if (semicolon.equals(child.getGrammarElement())) {
				int annotationOffset = child.getTotalOffset();
				String annotationText = getAnnotationText(evaluation);
				acceptor.accept(createNewLineContentCodeMining(annotationOffset, annotationText));
			}
		}
	}
}
 
Example 10
Source File: SARLQuickfixProvider.java    From sarl with Apache License 2.0 5 votes vote down vote up
/** Remove the exectuable feature.
 *
 * @param element the executable feature to remove.
 * @param context the context of the change.
 * @throws BadLocationException if there is a problem with the location of the element.
 */
public void removeExecutableFeature(EObject element, IModificationContext context) throws BadLocationException {
	final ICompositeNode node;
	final SarlAction action = EcoreUtil2.getContainerOfType(element, SarlAction.class);
	if (action == null) {
		final XtendMember feature = EcoreUtil2.getContainerOfType(element, XtendMember.class);
		node = NodeModelUtils.findActualNodeFor(feature);
	} else {
		node = NodeModelUtils.findActualNodeFor(action);
	}
	if (node != null) {
		remove(context.getXtextDocument(), node);
	}
}
 
Example 11
Source File: ImportRegionHelper.java    From n4js with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Calculates import offset by analyzing the provided script.
 *
 * @See {@link #getImportRegion(Script)}
 */
public int findInsertionOffset(Script script) {
	int result = 0;
	List<ScriptElement> scriptElements = script.getScriptElements();
	for (int i = 0, size = scriptElements.size(); i < size; i++) {
		ScriptElement element = scriptElements.get(i);
		if (element instanceof ImportDeclaration) {
			// Instead of getting the total offset for the first non-import-declaration, we try to get the
			// total end offset for the most recent import declaration which is followed by any other script
			// element
			// this is required for the linebreak handling for automatic semicolon insertion.
			ICompositeNode importNode = NodeModelUtils.findActualNodeFor(element);
			if (null != importNode) {
				result = importNode.getTotalOffset() + getLengthWithoutAutomaticSemicolon(importNode);
			}
		} else {
			// We assume that all import declarations are to be found in one place, thus
			// at this point we must have seen all of them.
			break;
		}
	}
	// If previously, an existing import declaration could be found, use it as offset.
	if (result != 0) {
		return result;
	}
	// Otherwise, we assume there is no import declarations yet. Use {@link ImportsRegionHelper}
	// to obtain an offset for the insertion of a new import declaration.
	return getImportRegion(script).offset;
}
 
Example 12
Source File: RewritableImportSection.java    From xtext-extras with Eclipse Public License 2.0 5 votes vote down vote up
public List<ReplaceRegion> rewrite() {
	removeObsoleteStaticImports();
	final List<ReplaceRegion> replaceRegions = newArrayList();
	if (isSort) {
		List<XImportDeclaration> allImportDeclarations = newArrayList();
		allImportDeclarations.addAll(originalImportDeclarations);
		allImportDeclarations.addAll(addedImportDeclarations);
		allImportDeclarations.removeAll(removedImportDeclarations);
		String newImportSection = serializeImports(allImportDeclarations);
		importRegion = regionUtil.addLeadingWhitespace(importRegion, resource);
		importRegion = regionUtil.addTrailingWhitespace(importRegion, resource);
		return singletonList(new ReplaceRegion(importRegion, newImportSection));
	} else {
		for (XImportDeclaration removedImportDeclaration : removedImportDeclarations) {
			ICompositeNode node = NodeModelUtils.findActualNodeFor(removedImportDeclaration);
			if (node != null) {
				ITextRegion textRegion = node.getTextRegion();
				textRegion = regionUtil.addTrailingSingleWhitespace(textRegion, lineSeparator, resource);
				replaceRegions.add(new ReplaceRegion(textRegion, ""));
			}
		}
		addSectionToAppend(new IAcceptor<ReplaceRegion>() {
			@Override
			public void accept(ReplaceRegion t) {
				replaceRegions.add(t);
			}
		});
	}
	return replaceRegions;
}
 
Example 13
Source File: AbstractXtextMarkerBasedTest.java    From dsl-devkit with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Searches an object for the given tag. First checks local tags. If not found then searches this tag in the required sources.
 *
 * @param tag
 *          Tag
 * @return EObject or {@code null}
 */
protected EObject getObjectForTag(final int tag) {
  EObject object = getMarkerTagsInfo().getModel(tag);
  if (object == null) {
    // Not in source under test
    String sourceName = getMarkerTagsInfo().getSource(tag);
    if (sourceName != null) {
      INode node = NodeModelUtils.findActualNodeFor(getTestSource(sourceName).getModel());
      INode leafNode = NodeModelUtils.findLeafNodeAtOffset(node, getMarkerTagsInfo().getOffset(tag));
      object = NodeModelUtils.findActualSemanticObjectFor(leafNode);
    }
  }
  assertNotNull("Tag " + tag + " should mark an object. Use «mark(TAG)» in a code snippet.", object); //$NON-NLS-1$//$NON-NLS-2$
  return object;
}
 
Example 14
Source File: XbaseHighlightingCalculator.java    From xtext-extras with Eclipse Public License 2.0 5 votes vote down vote up
protected void highlightAnnotation(XAnnotation annotation, IHighlightedPositionAcceptor acceptor, String highlightingConfiguration) {
	JvmType annotationType = annotation.getAnnotationType();
	if (annotationType != null && !annotationType.eIsProxy() && annotationType instanceof JvmAnnotationType) {
		ICompositeNode xannotationNode = NodeModelUtils.findActualNodeFor(annotation);
		if (xannotationNode != null) {
			ILeafNode firstLeafNode = NodeModelUtils.findLeafNodeAtOffset(xannotationNode, xannotationNode.getOffset() );
			if(firstLeafNode != null)
				highlightNode(acceptor, firstLeafNode, highlightingConfiguration);
		}
		highlightReferenceJvmType(acceptor, annotation, XAnnotationsPackage.Literals.XANNOTATION__ANNOTATION_TYPE, annotationType, highlightingConfiguration);
	}
}
 
Example 15
Source File: AbstractFragmentsTest.java    From xtext-core with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void testFragmentRecursive_02() throws Exception {
	ParserRuleFragments fragments = parseAndValidate("#10 myName ((myPrev))");
	Assert.assertNotNull(fragments);
	Assert.assertEquals("myName", fragments.getElement().getName());
	PRFNamed prev = ((PRFNamedWithAction) fragments.getElement()).getPrev();
	Assert.assertEquals("myPrev", prev.getName());
	ICompositeNode node = NodeModelUtils.findActualNodeFor(prev);
	Assert.assertEquals(" ((myPrev))", node.getText());
	EObject lookup = NodeModelUtils.findActualSemanticObjectFor(node);
	Assert.assertSame(prev, lookup);
}
 
Example 16
Source File: AbstractScopingTest.java    From dsl-devkit with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Asserts whether the two objects are equal.
 *
 * @param sourceObject
 *          First object needed for comparison.
 * @param targetObject
 *          Target object needed for comparison.
 * @param crossReference
 *          CrossReference object, can be {@code null}
 */
protected void assertEObjectsAreEqual(final EObject sourceObject, final EObject targetObject, final CrossReference crossReference) {
  String sourceObjectUri = EcoreUtil.getURI(sourceObject).toString();
  URI targetUri = EcoreUtil.getURI(targetObject);
  StringBuilder expected = new StringBuilder();
  StringBuilder found = new StringBuilder();
  if (crossReference != null) {
    String crossReferenceText = "Cross reference:\n" + crossReference.toString() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
    expected.append(crossReferenceText);
    found.append(crossReferenceText);
  }
  expected.append(LINKS_TO);
  found.append(LINKS_TO);
  expected.append(targetUri);
  found.append(sourceObjectUri);
  expected.append(WHICH_CORRESPONDS_TO);
  INode node;
  node = NodeModelUtils.findActualNodeFor(targetObject);
  if (node != null) {
    expected.append(NodeModelUtils.getTokenText(node));
  } else {
    expected.append(NO_NODE_MODEL_COULD_BE_A_DERIVED_OBJECT);
  }
  found.append(WHICH_CORRESPONDS_TO);
  node = NodeModelUtils.findActualNodeFor(sourceObject);
  if (sourceObject.eIsProxy()) {
    found.append(UNRESOLVED_REFERENCE);
  } else if (node != null) {
    found.append(NodeModelUtils.getTokenText(node));
  } else {
    found.append(NO_NODE_MODEL_COULD_BE_A_DERIVED_OBJECT);
  }
  assertEquals("Errors found. Consider compare view.", expected.toString(), found.toString()); //$NON-NLS-1$
}
 
Example 17
Source File: DocCommentLookup.java    From n4js with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Finds multi line comments on eObject. Comment is consider multiline by its type (e.g. start-end markers). Actual
 * conents can be either single line, or multiline content.
 *
 * @param eObject
 *            on which we look for multiline comment
 * @return list of nodes with comment, can be empty if no comments
 */
protected List<INode> findMultiLineComments(EObject eObject) {
	// get node
	INode elementNode = NodeModelUtils.findActualNodeFor(eObject);
	HiddenLeafs hLeafs = hla.getHiddenLeafsBefore(elementNode);
	// check for comments
	if (!hLeafs.containsComment()) {
		return null;
	}
	// get all comments
	List<LeafInfo> leafs = hLeafs.getLeafs();
	List<INode> comments = new ArrayList<>();

	final TerminalRule SL = grammarAccess.getSL_COMMENTRule();
	// get only MultiLine comments
	for (LeafInfo li : leafs) {
		if (li instanceof CommentInfo) {
			INode commentNode = li.getNode();
			EObject ge = commentNode.getGrammarElement();
			// are we sure we get here only ML/SL ?
			if (ge != SL) { // ignore SL
				// finds ML and SML
				comments.add(commentNode);
			}
		}
	}
	return comments;
}
 
Example 18
Source File: AbstractFragmentsTest.java    From xtext-core with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void testFragmentRecursive_04() throws Exception {
	ParserRuleFragments fragments = parseAndValidate("#11 myName ((myPrev))");
	Assert.assertNotNull(fragments);
	Assert.assertEquals("myName", fragments.getElement().getName());
	PRFNamed prev = ((PRFNamedWithAction) fragments.getElement()).getPrev();
	Assert.assertEquals("myPrev", prev.getName());
	ICompositeNode node = NodeModelUtils.findActualNodeFor(prev);
	Assert.assertEquals("myPrev", node.getText());
	EObject lookup = NodeModelUtils.findActualSemanticObjectFor(node);
	Assert.assertSame(prev, lookup);
}
 
Example 19
Source File: FixedPartialParsingHelper.java    From dsl-devkit with Eclipse Public License 1.0 4 votes vote down vote up
/**
 * Investigates the composite nodes containing the changed region and collects a list of nodes which could possibly
 * replaced by a partial parse. Such a node has a parent that consumes all his current lookahead tokens and all of
 * these tokens are located before the changed region.
 */
private List<ICompositeNode> internalFindValidReplaceRootNodeForChangeRegion(final List<ICompositeNode> nodesEnclosingRegion, final Range range) {
  List<ICompositeNode> result = new ArrayList<ICompositeNode>();
  boolean mustSkipNext = false;
  ICompositeNode previous = null;
  /*
   * set to 'true' as soon as the lookahead of an enclosing
   * exceeds the given range
   */
  boolean done = false;
  for (int i = 0; i < nodesEnclosingRegion.size() && !done; i++) {
    ICompositeNode node = nodesEnclosingRegion.get(i);
    if (node.getGrammarElement() != null) {
      if (!mustSkipNext) {
        boolean process = true;
        if (previous != null && !node.hasNextSibling()) {
          if (previous.getLookAhead() == node.getLookAhead() && previous.getLookAhead() == 0) {
            process = false;
          }
        }
        EObject semanticElement = NodeModelUtils.findActualSemanticObjectFor(node);
        if (semanticElement != null) {
          ICompositeNode actualNode = NodeModelUtils.findActualNodeFor(semanticElement);
          if (actualNode != null && (actualNode.getTotalOffset() < node.getTotalOffset() || actualNode.getTotalEndOffset() > node.getTotalEndOffset())) {
            mustSkipNext = isActionNode(node);
            process = false;
          }
        }
        if (process) {
          int remainingLookAhead = node.getLookAhead();
          if (remainingLookAhead != 0) {
            Iterator<ILeafNode> iterator = node.getLeafNodes().iterator();
            while (iterator.hasNext() && remainingLookAhead > 0) {
              ILeafNode leaf = iterator.next();
              if (!leaf.isHidden()) {
                if (remainingLookAhead > 0) {
                  remainingLookAhead--;
                }
                if (remainingLookAhead == 0) {
                  if (leaf.getTotalEndOffset() <= range.getOffset()) {
                    result.add(node);
                    previous = node;
                    if (isActionNode(node)) {
                      mustSkipNext = true;
                    }
                    break;
                  } else {
                    // lookahead ends left of the range, don't dive into child nodes
                    done = true;
                  }
                }
              }
            }
            if (remainingLookAhead != 0) {
              done = true;
            }
          } else {
            result.add(node);
            previous = node;
            if (isActionNode(node)) {
              mustSkipNext = true;
            }
          }
        }
      } else { // !mustSkipNext
        mustSkipNext = isActionNode(node);
      }
    }
  }
  return result;
}
 
Example 20
Source File: BalzacCodeMiningProvider.java    From balzac with Apache License 2.0 4 votes vote down vote up
@Override
protected void createCodeMinings(
    IDocument document,
    XtextResource resource,
    CancelIndicator indicator,
    IAcceptor<? super ICodeMining> acceptor) throws BadLocationException {

    // get all operations to open document
    List<Constant> allConstants = EcoreUtil2.eAllOfType(resource.getContents().get(0), Constant.class);

    Keyword colon = grammar.getConstantAccess().getColonKeyword_2_0();
    Keyword equalsSign = grammar.getConstantAccess().getEqualsSignKeyword_3();

    for (Constant c : allConstants) {
        // find document offset for inline annotation
        ICompositeNode node = NodeModelUtils.findActualNodeFor(c);

        boolean hasType = false;
        for (Iterator<INode> it = node.getAsTreeIterable().iterator(); it.hasNext();) {
            INode child = it.next();
            if (colon.equals(child.getGrammarElement())) {
                hasType = true;
            }
            if (!hasType && equalsSign.equals(child.getGrammarElement())) {
                // create line content code mining for inline annotation after grammarElement
                // ')'
                Result<Type> res = typeSystem.typeExpression(new TypeSubstitutions(), c);
                if (!res.failed()) {
                    String annotationText = ": " + strRep.stringRep(res.getFirst()) + " ";
                    acceptor.accept(createNewLineContentCodeMining(child.getTotalOffset(), annotationText));
                }
            }
        }
    }

    // TODO: implement me
    // use acceptor.accept(super.createNewLineHeaderCodeMining(...)) to add a new
    // code mining to the
    // final list

    // example:
    // acceptor.accept(createNewLineHeaderCodeMining(1, document, "Header
    // annotation"));
}